您的位置:首页 > 其它

使用Microsoft CryptoAPI进行加密、解密、签名及验证 (转发)

2007-07-05 17:27 866 查看
使用CryptoAPI编写一个文件保护程序,具有如下功能:(1)给定明文文件,生成加密文件,同时产生文件的数字签名文件;(2)给定密文文件,解密出明文文件,并验证签名的正确性。 代码:见所附main.cpp 一、    程序概况a)    开发平台:Visual Studio 2005b)    开发语言:C/C++c)    使用密码库:CryptoAPI二、    主要函数a)    主函数void main(void)b)    加密文件BOOL EncryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);c)    解密文件BOOL DecryptFile(PCHAR szSource, PCHAR szDestination, PCHAR szPassword);d)    签名文件BOOL SignFile (PCHAR szSource, PCHAR szDestination);e)    验证签名BOOL VerifyFile (PCHAR szSource, PCHAR szDestination);f)     错误处理void HandleError(char *s);   三、    加密文件a)    打开源文件hSource = fopen(szSource,"rb")b)    取得密钥容器(CSP)句柄CryptAcquireContext(&hCryptProv,NULL,NULL,PROV_RSA_FULL,0)c)    根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件加密)//创建一个Hash对象CryptCreateHash(hCryptProv,CALG_MD5, 0, 0, &hHash)//用用户输入的密码产生一个散列CryptHashData(hHash, (BYTE *)szPassword, strlen(szPassword), 0)//通过散列生成一个会话密钥CryptDeriveKey(hCryptProv, ENCRYPT_ALGORITHM,hHash, KEYLENGTH, &hKey))//销毁Hash对象CryptDestroyHash(hHash);注:会话密钥即对称密钥,用于对原文件进行加密;非对称密钥由于效率非常低,所以一般不用于对数据直接加密,而是对会话密钥进行加密,然后把它传送给对方。对方通过非对称密钥解密获得这个会话密钥,然后再对数据文件进行解密。可以看出,一个会话密钥的生存期可以限制在这次通信中,即每次通信都用不同的会话密钥加密,而非对称密钥则必须是长期使用的。在此例中,加解密过程中没有使用到非对称RSA密钥对,而只在数字签名及验证使用它。d)    加密数据文件CryptEncrypt(hKey,               //密钥0,                    //如果数据同时进行散列和加密,这里传入一个散列对象feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输//入FALSE这里通过判断是否到文件尾来决定是否为最后一块0,                    //保留pbBuffer,          //输入被加密数据,输出加密后的数据&dwCount,       //输入被加密数据实际长度,输出加密后数据长度dwBufferLen)    //pbBuffer的大小注:查看完整代码时可以发现这是一个循环加密的过程,pbBuffer循环读入待加密文件的固定长度的内存块;当然你也可以将pbBuffer设得很大,一次读入整个文件,但那样浪费内存空间,而且影响扩展性(存在缓冲区溢出的可能)。e)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。if(pbBuffer)free(pbBuffer);if(hKey)CryptDestroyKey(hKey);if(hHash) CryptDestroyHash(hHash);if(hCryptProv)CryptReleaseContext(hCryptProv, 0);            … 四、    解密文件a)    打开加密文件(同上)b)    取得密钥容器(CSP)句柄(同上)c)    根据用户输入的密码创建一个会话密钥(即对称密钥,用于对原文件解密)(同上)注:这里要求用户输入的密码与加密时输入的密码相同。在实际应用中,这个所谓用户输入的“密码”其实只是一个产生密钥的种子,一旦产生完会话密钥,则用户完全可以忘记当初输入的“密码”,接收方可以使用传过来的密钥直接对加密文件进行解密,而不用再重复一次“生成密钥”的过程。d)    解密数据文件CryptDecrypt(hKey,               //密钥0,                    //如果数据同时进行散列和加密,这里传入一个散列对象feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.//入FALSE这里通过判断是否到文件尾来决定是否为最后一块。0,                    //保留pbBuffer,          //输入被加密数据,输出加密后的数据&dwCount))           //输入被加密数据实际长度,输出加密后数据长度e)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)五、    签名文件a)    打开源文件(同上)b)    取得密钥容器(CSP)句柄(同上)c)    取得签名用的密钥句柄(非对称RSA密钥)CryptGetUserKey(hCryptProv,               // 我们已经得到的CSP句柄AT_SIGNATURE,            // 这里想得到signature key pair&hKey))                       // 返回密钥句柄d)    导出签名用密钥对的公钥,保存在pbKeyBlob中CryptExportKey(hKey, NULL,PUBLICKEYBLOB, 0, pbKeyBlob,&dwBlobLen)e)    计算数据文件的Hash值,保存在Hash对象hHash中//生成一个空的Hash对象CryptCreateHash(hCryptProv,CALG_MD5,0,0,&hHash)//计算数据文件的Hash值,保存在Hash对象中CryptHashData(hHash,pbBuffer,dwCount,0)f)     对数据文件的Hash值进行签名,数字签名保存在pbSignature中CryptSignHash(hHash, AT_SIGNATURE, NULL, 0, pbSignature, &dwSigLen)g)    清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)六、    验证签名a)    打开文件(同上)b)    取得密钥容器(CSP)句柄(同上)c)    导入 pbKeyBlob 公钥CryptImportKey(hCryptProv, pbKeyBlob, dwBlobLen, 0, 0, &hPubKey)注:必须是与签名时所用的私钥配对的公钥,在此例中,这个公钥在生成数字签名时已经导出到pbKeyBlob中。d)    计算数据文件的Hash值,保存在Hash对象hHash中。(同上)e)    验证数字签名CryptVerifySignature(hHash, pbSignature, dwSigLen,hPubKey,NULL, 0)f)     清理工作,如释放Buffer空间、密钥句柄、CSP句柄等。(同上)七、    实验结果// 加密文件Encrypt a file.  Enter the name of the file to be encrypted: 1.txt Enter the name of the output file: 2.txt Enter the password:123456 The source plaintext file, 1.txt, is open. Destination file 2.txt is open.A cryptographic provider has been acquired.A hash object has been created.The password has been added to the hash.An encryption key is derived from the password hash.Memory has been allocated for the buffer. Encryption of the file 1.txt was a success. The encrypted data is in file 2.txt. //解密文件Decrypt a file.  Enter the name of the file to be decrypted: 2.txt Enter the name of the output file: 3.txt Enter the password:123456 The source plaintext file, 2.txt, is open. Destination file 3.txt is open.A cryptographic provider has been acquired.A hash object has been created.The password has been added to the hash.An encryption key is derived from the password hash.Memory has been allocated for the buffer. Decryption of the file 2.txt was a success. The decrypted data is in file 3.txt. //数字签名Sign a file.  Enter the name of the file to be signed: 1.txt Enter the name of the signature file: 11 The source plaintext file, 1.txt, is open.Memory has been allocated for the buffer. Destination file 11 is open.A cryptographic provider has been acquired.A signature key is available.Size of the BLOB for the public key determined.Memory has been allocated for the BLOB.Contents have been written to the BLOB.Hash object created.The data buffer has been hashed.Signature length 128 found.Memory allocated for the signature.pbSignature is the hash signature.The hash object has been destroyed.The signing phase of this program is completed.  Signature of the file 1.txt was a success. The signature data is in file 11. //验证签名Verify a file and its signature.  Enter the name of the file to be verified: 1.txt Enter the name of the signature file: 11 The source plaintext file, 1.txt, is open.Memory has been allocated for the buffer.A cryptographic provider has been acquired.The key has been imported.The hash object has been recreated.The new has been created.The signature has been verified. Verification of the file 1.txt was a success.八、    参考资料1)      Microsoft CryptoAPI加密技术http://166.111.203.236:8080/reference/crypto/Microsoft_CryptoAPI_1.mht2)      MSDN http://msdn2.microsoft.com/en-us/library/aa380252.aspxhttp://msdn2.microsoft.com/en-us/library/aa382371.aspx 
main.cpp#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
#define KEYLENGTH 
140ee
0x00800000
void HandleError(char *s);
//--------------------------------------------------------------------
//  These additional #define statements are required.
#define ENCRYPT_ALGORITHM CALG_RC4
#define ENCRYPT_BLOCK_SIZE 8
#define MAX_FILE_SIZE 4000000
#define SIGNATURE_SIZE 500

BYTE *pbKeyBlob;  //用来保存导出的公钥
DWORD dwBlobLen;

//   Declare the functions. The function definition
//   follows main.
BOOL VerifyFile (
     PCHAR szSource,       
     PCHAR szDestination);
BOOL SignFile   (
     PCHAR szSource,       
     PCHAR szDestination);
BOOL DecryptFile(
     PCHAR szSource,
     PCHAR szDestination,
     PCHAR szPassword);

BOOL EncryptFile(
     PCHAR szSource,
     PCHAR szDestination,
     PCHAR szPassword);

//--------------------------------------------------------------------
//   Begin main.

void main(void)
{
 CHAR szSource[100];
 CHAR szDestination[100];
 CHAR szPassword[100];

 
 //--------------------------------------------------------------------
 // Call EncryptFile to do the actual encryption. 加密文件
 printf("/n------------------------------------------------------------/n");
 printf("/n/n1.Encrypt a file. /n/n");
 printf("/nEnter the name of the file to be encrypted: ");
 scanf("%s",szSource);
 printf("/nEnter the name of the output file: ");
 scanf("%s",szDestination);
 printf("/nEnter the password:");
 scanf("%s",szPassword);

 if(EncryptFile(szSource, szDestination, szPassword))
 {
 printf("/nEncryption of the file %s was a success. /n", szSource);
 printf("/nThe encrypted data is in file %s./n",szDestination);
 }
 else
 {
 HandleError("/nError encrypting file!");
 }

 //--------------------------------------------------------------------
 // Call Decryptfile to do the actual decryption. 解密文件
 printf("/n------------------------------------------------------------/n");
 printf("/n/n2.Decrypt a file. /n/n");
 printf("/nEnter the name of the file to be decrypted: ");
 scanf("%s",szSource);
 printf("/nEnter the name of the output file: ");
 scanf("%s",szDestination);
 printf("/nEnter the password:");
 scanf("%s",szPassword);

 if(DecryptFile(szSource, szDestination, szPassword))
 {
 printf("/nDecryption of the file %s was a success. /n", szSource);
 printf("/nThe decrypted data is in file %s./n",szDestination);
 }
 else
 {
 HandleError("/nError decrypting file!");
 }
 
 //--------------------------------------------------------------------
 // Call SignFile to do the actual signature   签名文件
 printf("/n------------------------------------------------------------/n");
 printf("/n/n3.Sign a file. /n/n");
 printf("/nEnter the name of the file to be signed: ");
 scanf("%s",szSource);
 printf("/nEnter the name of the signature file: ");
 scanf("%s",szDestination);

 if(SignFile(szSource, szDestination))
 {
  printf("/nSignature of the file %s was a success. /n", szSource);
  printf("/nThe signature data is in file %s./n",szDestination);
 }
 else
 {
  HandleError("/nError while signing the file!");
 }

 //---------------------------------------------------------------------
 // Call VerifyFile to do the actual verification 验证签名
 printf("/n------------------------------------------------------------/n");
 printf("/n/n4.Verify a file and its signature. /n/n");
 printf("/nEnter the name of the file to be verified: ");
 scanf("%s",szSource);
 printf("/nEnter the name of the signature file: ");
 scanf("%s",szDestination);
 //printf("/nEnter the name of the public key file: ");
 //scanf("%s",szDestination);

 if(VerifyFile(szSource, szDestination))
 {
  printf("/nVerification of the file %s was a success. /n", szSource);
 }
 else
 {
  HandleError("/nVerification failed. Error file!");
 }

} // End of main
//-----------------------------------------------------------------------
//   Code for the function VerifyFile 功能:验证数字签名
static BOOL VerifyFile(
        PCHAR szSource,   //原文件    
        PCHAR szSignature) //数字签名文件
{
 //--------------------------------------------------------------------
 //   Declare and initialize local variables.

 FILE *hSource;
 FILE *hSignature;

 HCRYPTPROV hCryptProv; //CSP:钥匙容器
 HCRYPTKEY hKey;   //公钥对:包括配对的一个公钥和一个密钥
 HCRYPTKEY hPubKey;  //公钥对中的公钥
 HCRYPTHASH hHash;  //hash对象,用于对数据文件进行hash处理,得到hash值
 //公钥签名就是针对hash值进行签名,而不是原文件,
 //这是因为公钥处理的速度非常慢

 BYTE *pbSignature;
 DWORD dwSigLen;
 PBYTE pbBuffer;
 DWORD dwBufferLen;
 DWORD dwCount;

 //DWORD dwBlobLen;

 //--------------------------------------------------------------------
 // Open source file.
 if(hSource = fopen(szSource,"rb"))
 {
  printf("/nThe source plaintext file, %s, is open. /n", szSource);
 }
 else
 {
  HandleError("/nError opening source plaintext file!");
 }
 //--------------------------------------------------------------------
 // Allocate memory.
 if(pbBuffer = (BYTE *)malloc(MAX_FILE_SIZE))
 {
  printf("Memory has been allocated for the buffer. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }
 //将源文件读入pbBuffer
 dwCount = fread(pbBuffer, 1, MAX_FILE_SIZE, hSource);
 if(ferror(hSource))
 {
  HandleError("Error reading plaintext!/n");
 }

 //---------------------------------------------------------------------
 // Open signature file 读入签名文件(特殊处理:直接采用保留在内存中的签名来进行验证)
 if(hSignature = fopen(szSignature,"rb"))
 {
  printf("/nThe signature plaintext file, %s, is open. /n", szSignature);
 }
 else
 {
  HandleError("/nError opening signature file!");
 }
 //--------------------------------------------------------------------
 // Allocate memory.
 if(pbSignature = (BYTE *)malloc(SIGNATURE_SIZE))
 {
  printf("Memory has been allocated for the buffer. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }
 //将签名读入pbSignature
 dwSigLen = fread(pbSignature, 1, SIGNATURE_SIZE, hSignature);
 if(ferror(hSource))
 {
  HandleError("Error reading plaintext!/n");
 }

 //以下获得一个CSP句柄
 if(CryptAcquireContext(
  &hCryptProv,  //调用完成之后hCryptProv保存密钥容器的句柄
  NULL,    //NULL表示使用默认密钥容器,默认密钥容器名为用户登陆名
  NULL,
  PROV_RSA_FULL,
  0))
 {
  printf("A cryptographic provider has been acquired. /n");
 }
 else
 {
  if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   CRYPT_NEWKEYSET))//创建密钥容器
  {
   //创建密钥容器成功,并得到CSP句柄
   printf("A new key container has been created./n");
  }
  else
  {
   HandleError("Could not create a new key container./n");
  }  
 }

 //导入 pbKeyBlob 公钥(这个公钥与签名时所用的私钥配对,在签名时导出到pbKeyBlob中)
 if(CryptImportKey(
  hCryptProv,
  pbKeyBlob,
  dwBlobLen,
  0,
  0,
  &hPubKey))
 {
  printf("The key has been imported./n");
 }
 else
 {
  HandleError("Public key import failed.");
 }
 //-------------------------------------------------------------------
 // Create a new hash object. 对原文件进行hash处理

 if(CryptCreateHash(
  hCryptProv,
  CALG_MD5,
  0,
  0,
  &hHash))
 {
  printf("The hash object has been recreated. /n");
 }
 else
 {
  HandleError("Error during CryptCreateHash.");
 }
 //-------------------------------------------------------------------
 // Compute the cryptographic hash of the buffer.

 if(CryptHashData(
  hHash,
  pbBuffer,
  dwCount,
  0))
 {
  printf("The new has been created./n");
 }
 else
 {
  HandleError("Error during CryptHashData.");
 }
 //-------------------------------------------------------------------
 // Validate the digital signature. 验证数字签名是否正确

 if(CryptVerifySignature(
  hHash,
  pbSignature,
  dwSigLen,
  hPubKey,
  NULL,
  0))
 {
  printf("/n**********************************************/n");
  printf("The signature has passed the verification!/n");
  printf("/n**********************************************/n");
 }
 else
 {
  printf("/n**********************************************/n");
  printf("Signature not validated!");
  printf("/n**********************************************/n");
 }

 //--------------------------------------------------------------------
 // Close files.

 if(hSource)
  fclose(hSource);
 //if(hSignature)
 // fclose(hSignature);

 //-------------------------------------------------------------------
 // Free memory to be used to store signature.

 if(pbSignature)
  free(pbSignature);

 //-------------------------------------------------------------------
 // Destroy the hash object.

 if(hHash)
  CryptDestroyHash(hHash);

 //-------------------------------------------------------------------
 // Release the provider handle.

 if(hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return(TRUE);

}

 

//-----------------------------------------------------------------------
//   Code for the function SignFile 功能:对文件进行数字签名
static BOOL SignFile(
      PCHAR szSource,       
      PCHAR szDestination)
{
 //--------------------------------------------------------------------
 //   Declare and initialize local variables.

 FILE *hSource;
 FILE *hDestination;

 HCRYPTPROV hCryptProv;
 HCRYPTKEY hKey;
 HCRYPTHASH hHash;

 BYTE *pbSignature;
 PBYTE pbBuffer;
 DWORD dwBufferLen;
 DWORD dwCount;
 DWORD dwSigLen;

 //--------------------------------------------------------------------
 // Open source file.
 if(hSource = fopen(szSource,"rb"))
 {
  printf("/nThe source plaintext file, %s, is open. /n", szSource);
 }
 else
 {
  HandleError("/nError opening source plaintext file!");
 }
 //--------------------------------------------------------------------
 // Allocate memory.
 if(pbBuffer = (BYTE *)malloc(MAX_FILE_SIZE))
 {
  printf("Memory has been allocated for the buffer. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }
 dwCount = fread(pbBuffer, 1, MAX_FILE_SIZE, hSource);
 if(ferror(hSource))
 {
  HandleError("Error reading plaintext!/n");
 }
 //--------------------------------------------------------------------
 // Open destination file.
 if(hDestination = fopen(szDestination,"wb"))
 {
  printf("/nDestination file %s is open. /n", szDestination);
 }
 else
 {
  HandleError("/nError opening destination ciphertext file!");
 }

 //以下获得一个CSP句柄
 if(CryptAcquireContext(
  &hCryptProv,
  NULL,    //NULL表示使用默认密钥容器,默认密钥容器名为用户登陆名
  NULL,
  PROV_RSA_FULL,
  0))
 {
  printf("A cryptographic provider has been acquired. /n");
 }
 else
 {
  if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   CRYPT_NEWKEYSET))//创建密钥容器
  {
   //创建密钥容器成功,并得到CSP句柄
   printf("A new key container has been created./n");
  }
  else
  {
   HandleError("Could not create a new key container./n");
  }  
 }
 if(CryptGetUserKey(
  hCryptProv,                     // 我们已经得到的CSP句柄
  AT_SIGNATURE,                   // 这里想得到signature key pair
  &hKey))                         // 返回密钥句柄
 {  
  printf("A signature key is available./n");
 }
 else  //取signature key pair错误
 {
  printf("No signature key is available./n");
  if(GetLastError() == NTE_NO_KEY) //密钥容器里不存在signature key pair
  {
   // 创建 signature key pair.
   printf("The signature key does not exist./n");
   printf("Create a signature key pair./n");
   if(CryptGenKey(
    hCryptProv,  //CSP句柄
    AT_SIGNATURE, //创建的密钥对类型为signature key pair
    0,    //key类型,这里用默认值
    &hKey))   //创建成功返回新创建的密钥对的句柄
   {
    printf("Created a signature key pair./n");
   }
   else
   {
    printf ("Error occurred creating a signature key./n");
   }
  }
  else
  {
   printf ("An error other than NTE_NO_KEY getting signature/key./n");
  }
 } // end if
 //-------------------------------------------------------------------
 // 导出公钥
 // Export the public key. Here the public key is exported to a
 // PUBLICKEYBOLB so that the receiver of the signed hash can
 // verify the signature. This BLOB could be written to a file and
 // sent to another user.

 if(CryptExportKey(  
  hKey,   
  NULL,   
  PUBLICKEYBLOB,
  0,   
  NULL,
  &dwBlobLen))
 {
  printf("Size of the BLOB for the public key determined. /n");
 }
 else
 {
  HandleError("Error computing BLOB length.");
 }
 //-------------------------------------------------------------------
 // Allocate memory for the pbKeyBlob.

 if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
 {
  printf("Memory has been allocated for the BLOB. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }
 //-------------------------------------------------------------------
 // Do the actual exporting into the key BLOB.

 if(CryptExportKey(  
  hKey,
  NULL,   
  PUBLICKEYBLOB,   
  0,   
  pbKeyBlob,   
  &dwBlobLen))
 {
  printf("Contents have been written to the BLOB. /n");
 }
 else
 {
  HandleError("Error during CryptExportKey.");
 } 
 //签名密钥已经准备完毕,公钥也已导出到 pbKeyBlob 中

 

 //*****************************签名***********************************
 //-------------------------------------------------------------------
 // Create the hash object.
 if(CryptCreateHash(
  hCryptProv,
  CALG_MD5,
  0,
  0,
  &hHash))
 {
  printf("Hash object created. /n");
 }
 else
 {
  HandleError("Error during CryptCreateHash.");
 }
 if(CryptHashData(
  hHash,
  pbBuffer,
  dwCount,
  0))
 {
  printf("The data buffer has been hashed./n");
 }
 else
 {
  HandleError("Error during CryptHashData./n");
 }  
 //释放缓冲区
 if(pbBuffer)
  free(pbBuffer);
 pbBuffer = NULL;
 //-------------------------------------------------------------------
 // Determine the size of the signature and allocate memory.

 dwSigLen= 0;
 if(CryptSignHash(
  hHash,
  AT_SIGNATURE,
  NULL,
  0,
  NULL,
  &dwSigLen))
 {
  printf("Signature length %d found./n",dwSigLen);
 }
 else
 {
  HandleError("Error during CryptSignHash.");
 }
 //-------------------------------------------------------------------
 // Allocate memory for the signature buffer.

 if(pbSignature = (BYTE *)malloc(dwSigLen))
 {
  printf("Memory allocated for the signature./n");
 }
 else
 {
  HandleError("Out of memory.");
 }
 //-------------------------------------------------------------------
 // Sign the hash object.

 if(CryptSignHash(
  hHash,
  AT_SIGNATURE,
  NULL,
  0,
  pbSignature,
  &dwSigLen))
 {
  printf("pbSignature is the hash signature./n");
 }
 else
 {
  HandleError("Error during CryptSignHash.");
 }
 
 if(fwrite(pbSignature, 1, dwSigLen, hDestination) != dwSigLen)
  HandleError("Failed to write Signature into file!");

 printf("The hash object has been destroyed./n");
 printf("The signing phase of this program is completed./n/n");

 //善后工作
 //--------------------------------------------------------------------
 // Destroy session key.

 if(hKey)
  CryptDestroyKey(hKey);
 //-------------------------------------------------------------------  // Destroy the hash object.

 if(hHash)
  CryptDestroyHash(hHash);

 //-------------------------------------------------------------------
 // Release the provider handle.

 if(hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 //--------------------------------------------------------------------  // Close files.

 if(hSource)
  fclose(hSource);
 if(hDestination)
  fclose(hDestination);

 return(TRUE);
}
//--------------------------------------------------------------------
//   Code for the function Decryptfile, which is called by main too
static BOOL DecryptFile(
      PCHAR szSource,
      PCHAR szDestination,
      PCHAR szPassword)
      //--------------------------------------------------------------------
      //   Parameters passed are:
      //     szSource, the name of the input, a plaintext file.
      //     szDestination, the name of the output, an encrypted file to be
      //         created.
      //     szPassword, the password.
{
 //--------------------------------------------------------------------
 //   Declare and initialize local variables.

 FILE *hSource;
 FILE *hDestination;

 HCRYPTPROV hCryptProv;
 HCRYPTKEY hKey;
 HCRYPTHASH hHash;

 PBYTE pbBuffer;
 DWORD dwBlockLen;
 DWORD dwBufferLen;
 DWORD dwCount;

 //--------------------------------------------------------------------
 // Open source file.
 if(hSource = fopen(szSource,"rb"))
 {
  printf("/nThe source plaintext file, %s, is open. /n", szSource);
 }
 else
 {
  HandleError("/nError opening source plaintext file!");
 }

 //--------------------------------------------------------------------
 // Open destination file.
 if(hDestination = fopen(szDestination,"wb"))
 {
  printf("/nDestination file %s is open. /n", szDestination);
 }
 else
 {
  HandleError("/nError opening destination ciphertext file!");
 }

 //以下获得一个CSP句柄
 if(CryptAcquireContext(
  &hCryptProv,
  NULL,    //NULL表示使用默认密钥容器,默认密钥容器名为用户登陆名
  NULL,
  PROV_RSA_FULL,
  0))
 {
  printf("A cryptographic provider has been acquired. /n");
 }
 else
 {
  if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   CRYPT_NEWKEYSET))//创建密钥容器
  {
   //创建密钥容器成功,并得到CSP句柄
   printf("A new key container has been created./n");
  }
  else
  {
   HandleError("Could not create a new key container./n");
  }

 }

 //--------------------------------------------------------------------
 // 创建一个会话密钥(session key)
 // 会话密钥也叫对称密钥,用于对称加密算法。
 // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
 //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)

 //--------------------------------------------------------------------
 // Create a hash object.
 if(CryptCreateHash(
  hCryptProv,
  CALG_MD5,
  0,
  0,
  &hHash))
 {
  printf("A hash object has been created. /n");
 }
 else
 {
  HandleError("Error during CryptCreateHash!/n");
 } 

 //--------------------------------------------------------------------
 // 用输入的密码产生一个散列
 if(CryptHashData(
  hHash,
  (BYTE *)szPassword,
  strlen(szPassword),
  0))
 {
  printf("The password has been added to the hash. /n");
 }
 else
 {
  HandleError("Error during CryptHashData. /n");
 }

 //--------------------------------------------------------------------
 // 通过散列生成会话密钥
 if(CryptDeriveKey(
  hCryptProv,
  ENCRYPT_ALGORITHM,
  hHash,
  KEYLENGTH,
  &hKey))
 {
  printf("An encryption key is derived from the password hash. /n");
 }
 else
 {
  HandleError("Error during CryptDeriveKey!/n");
 }
 //--------------------------------------------------------------------
 // Destroy the hash object.

 CryptDestroyHash(hHash);
 hHash = NULL;

 //--------------------------------------------------------------------
 //  The session key is now ready.

 //--------------------------------------------------------------------
 // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
 // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
 // 数据长度。

 dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;

 //--------------------------------------------------------------------
 // Determine the block size. If a block cipher is used,
 // it must have room for an extra block.

 if(ENCRYPT_BLOCK_SIZE > 1)
  dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
 else
  dwBufferLen = dwBlockLen;

 //--------------------------------------------------------------------
 // Allocate memory.
 if(pbBuffer = (BYTE *)malloc(dwBufferLen))
 {
  printf("Memory has been allocated for the buffer. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }

 

 //*****************************解密***********************************

 do
 {   
  //--------------------------------------------------------------------
  // Read up to dwBlockLen bytes from the source file.
  dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
  if(ferror(hSource))
  {
   HandleError("Error reading plaintext!/n");
  }

  //--------------------------------------------------------------------
  // 解密数据
  if(!CryptDecrypt(
   hKey,   //密钥
   0,    //如果数据同时进行散列和加密,这里传入一个散列对象
   feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
   //入FALSE这里通过判断是否到文件尾来决定是否为最后一块。
   0,    //保留
   pbBuffer,  //输入被加密数据,输出加密后的数据
   &dwCount))  //输入被加密数据实际长度,输出加密后数据长度
  {
   HandleError("Error during CryptEncrypt. /n");
  }

  //--------------------------------------------------------------------
  // Write data to the destination file.

  fwrite(pbBuffer, 1, dwCount, hDestination);
  if(ferror(hDestination))
  {
   HandleError("Error writing ciphertext.");
  }  
 }
 while(!feof(hSource));

 //*****************************解密***********************************

 

 //善后工作
 //--------------------------------------------------------------------  // Close files.

 if(hSource)
  fclose(hSource);
 if(hDestination)
  fclose(hDestination);

 

 //--------------------------------------------------------------------
 // Free memory.

 if(pbBuffer)
  free(pbBuffer);

 //--------------------------------------------------------------------
 // Destroy session key.

 if(hKey)
  CryptDestroyKey(hKey);

 //--------------------------------------------------------------------
 // Destroy hash object.

 if(hHash)
  CryptDestroyHash(hHash); 

 //--------------------------------------------------------------------
 // Release provider handle.

 if(hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return(TRUE); 

}
//--------------------------------------------------------------------
//   Code for the function EncryptFile called by main.

static BOOL EncryptFile(
      PCHAR szSource,
      PCHAR szDestination,
      PCHAR szPassword)
      //--------------------------------------------------------------------
      //   Parameters passed are:
      //     szSource, the name of the input, a plaintext file.
      //     szDestination, the name of the output, an encrypted file to be
      //         created.
      //     szPassword, the password.
{
 //--------------------------------------------------------------------
 //   Declare and initialize local variables.

 FILE *hSource;
 FILE *hDestination;

 HCRYPTPROV hCryptProv;
 HCRYPTKEY hKey;
 HCRYPTHASH hHash;

 PBYTE pbBuffer;
 DWORD dwBlockLen;
 DWORD dwBufferLen;
 DWORD dwCount;

 //--------------------------------------------------------------------
 // Open source file.
 if(hSource = fopen(szSource,"rb"))
 {
  printf("/nThe source plaintext file, %s, is open. /n", szSource);
 }
 else
 {
  HandleError("/nError opening source plaintext file!");
 }

 //--------------------------------------------------------------------
 // Open destination file.
 if(hDestination = fopen(szDestination,"wb"))
 {
  printf("/nDestination file %s is open. /n", szDestination);
 }
 else
 {
  HandleError("/nError opening destination ciphertext file!");
 }

 //以下获得一个CSP句柄
 if(CryptAcquireContext(
  &hCryptProv,
  NULL,    //NULL表示使用默认密钥容器,默认密钥容器名为用户登陆名
  NULL,
  PROV_RSA_FULL,
  0))
 {
  printf("A cryptographic provider has been acquired. /n");
 }
 else
 {
  if(CryptAcquireContext(
   &hCryptProv,
   NULL,
   NULL,
   PROV_RSA_FULL,
   CRYPT_NEWKEYSET))//创建密钥容器
  {
   //创建密钥容器成功,并得到CSP句柄
   printf("A new key container has been created./n");
  }
  else
  {
   HandleError("Could not create a new key container./n");
  }

 }

 //--------------------------------------------------------------------
 // 创建一个会话密钥(session key)
 // 会话密钥也叫对称密钥,用于对称加密算法。
 // (注: 一个Session是指从调用函数CryptAcquireContext到调用函数
 //   CryptReleaseContext 期间的阶段。会话密钥只能存在于一个会话过程)

 //--------------------------------------------------------------------
 // Create a hash object.
 if(CryptCreateHash(
  hCryptProv,
  CALG_MD5,
  0,
  0,
  &hHash))
 {
  printf("A hash object has been created. /n");
 }
 else
 {
  HandleError("Error during CryptCreateHash!/n");
 } 

 //--------------------------------------------------------------------
 // 用输入的密码产生一个散列
 if(CryptHashData(
  hHash,
  (BYTE *)szPassword,
  strlen(szPassword),
  0))
 {
  printf("The password has been added to the hash. /n");
 }
 else
 {
  HandleError("Error during CryptHashData. /n");
 }

 //--------------------------------------------------------------------
 // 通过散列生成会话密钥
 if(CryptDeriveKey(
  hCryptProv,
  ENCRYPT_ALGORITHM,
  hHash,
  KEYLENGTH,
  &hKey))
 {
  printf("An encryption key is derived from the password hash. /n");
 }
 else
 {
  HandleError("Error during CryptDeriveKey!/n");
 }
 //--------------------------------------------------------------------
 // Destroy the hash object.

 CryptDestroyHash(hHash);
 hHash = NULL;

 //--------------------------------------------------------------------
 //  The session key is now ready.

 //--------------------------------------------------------------------
 // 因为加密算法是按ENCRYPT_BLOCK_SIZE 大小的块加密的,所以被加密的
 // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的
 // 数据长度。

 dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;

 //--------------------------------------------------------------------
 // Determine the block size. If a block cipher is used,
 // it must have room for an extra block.

 if(ENCRYPT_BLOCK_SIZE > 1)
  dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;
 else
  dwBufferLen = dwBlockLen;

 //--------------------------------------------------------------------
 // Allocate memory.
 if(pbBuffer = (BYTE *)malloc(dwBufferLen))
 {
  printf("Memory has been allocated for the buffer. /n");
 }
 else
 {
  HandleError("Out of memory. /n");
 }
 //--------------------------------------------------------------------
 // In a do loop, encrypt the source file and write to the source file.

 do
 {   
  //--------------------------------------------------------------------
  // Read up to dwBlockLen bytes from the source file.
  dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
  if(ferror(hSource))
  {
   HandleError("Error reading plaintext!/n");
  }

  //--------------------------------------------------------------------
  // 加密数据
  if(!CryptEncrypt(
   hKey,   //密钥
   0,    //如果数据同时进行散列和加密,这里传入一个散列对象
   feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
   //入FALSE这里通过判断是否到文件尾来决定是否为最后一块。
   0,    //保留
   pbBuffer,  //输入被加密数据,输出加密后的数据
   &dwCount,  //输入被加密数据实际长度,输出加密后数据长度
   dwBufferLen)) //pbBuffer的大小。
  {
   HandleError("Error during CryptEncrypt. /n");
  }

  //--------------------------------------------------------------------
  // Write data to the destination file.

  fwrite(pbBuffer, 1, dwCount, hDestination);
  if(ferror(hDestination))
  {
   HandleError("Error writing ciphertext.");
  }  
 }
 while(!feof(hSource));

 //--------------------------------------------------------------------
 //  End the do loop when the last block of the source file has been
 //  read, encrypted, and written to the destination file.

 //--------------------------------------------------------------------
 // Close files.

 if(hSource)
  fclose(hSource);
 if(hDestination)
  fclose(hDestination);

 

 

 

 ////*****************************解密***********************************

 ////解密
 ////--------------------------------------------------------------------
 //// Open source file.
 //if(hSource = fopen(szDestination,"rb"))
 //{
 // printf("The source plaintext file, %s, is open. /n", szSource);
 //}
 //else
 //{
 // HandleError("Error opening source plaintext file!");
 //}

 ////--------------------------------------------------------------------
 //// Open destination file.
 //if(hDestination = fopen("ccc.txt","wb"))
 //{
 // printf("Destination file %s is open. /n", szDestination);
 //}
 //else
 //{
 // HandleError("Error opening destination ciphertext file!");
 //}

 //do
 //{   
 // //--------------------------------------------------------------------
 // // Read up to dwBlockLen bytes from the source file.
 // dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);
 // if(ferror(hSource))
 // {
 //  HandleError("Error reading plaintext!/n");
 // }
 // 
 // //--------------------------------------------------------------------
 // // 解密数据
 // if(!CryptDecrypt(
 //  hKey,   //密钥
 //  0,    //如果数据同时进行散列和加密,这里传入一个散列对象
 //  feof(hSource), //如果是最后一个被加密的块,输入TRUE.如果不是输.
 //      //入FALSE这里通过判断是否到文件尾来决定是否为最后一块。
 //  0,    //保留
 //  pbBuffer,  //输入被加密数据,输出加密后的数据
 //  &dwCount))  //输入被加密数据实际长度,输出加密后数据长度
 // {
 //  HandleError("Error during CryptEncrypt. /n");
 // }
 // 
 // //--------------------------------------------------------------------
 // // Write data to the destination file.
 // 
 // fwrite(pbBuffer, 1, dwCount, hDestination);
 // if(ferror(hDestination))
 // {
 //  HandleError("Error writing ciphertext.");
 // }  
 //}
 //while(!feof(hSource));

 ////*****************************解密***********************************

 

 

 

 

 //--------------------------------------------------------------------
 // Free memory.

 if(pbBuffer)
  free(pbBuffer);

 //--------------------------------------------------------------------
 // Destroy session key.

 if(hKey)
  CryptDestroyKey(hKey);

 //--------------------------------------------------------------------
 // Destroy hash object.

 if(hHash)
  CryptDestroyHash(hHash); 

 //--------------------------------------------------------------------
 // Release provider handle.

 if(hCryptProv)
  CryptReleaseContext(hCryptProv, 0);
 return(TRUE);
} // End of Encryptfile

//--------------------------------------------------------------------
//  This example uses the function HandleError, a simple error
//  handling function, to print an error message to the standard error
//  (stderr) file and exit the program.
//  For most applications, replace this function with one
//  that does more extensive error reporting.

void HandleError(char *s)
{
 fprintf(stderr,"An error occurred in running the program. /n");
 fprintf(stderr,"%s/n",s);
 fprintf(stderr, "Error number %x./n", GetLastError());
 fprintf(stderr, "Program terminating. /n");
 exit(1);
} // End of HandleError
 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息