vc++网络安全编程范例(17)-open ssl 实现文件加密与解密

来源:互联网 发布:安全投资卫士炒股软件 编辑:程序博客网 时间:2024/05/21 10:37

OpenSSL整个软件包大概可以分成三个主要的功能部分:密码算法库、SSL协议库以及应用程序。OpenSSL的目录结构自然也是围绕这三个功能部分进行规划的。   作为一个基于密码学的安全开发包,OpenSSL提供的功能相当强大和全面,囊括了主要的密码算法、常用的密钥和证书封装管理功能以及SSL协议,并提供了丰富的应用程序供测试或其它目的使用。
对称加密算法
  OpenSSL一共提供了8种对称加密算法,其中7种是分组加密算法,仅有的一种流加密算法是RC4。这7种分组加密算法分别是AES、DES、Blowfish、CAST、IDEA、RC2、RC5,都支持电子密码本模式(ECB)、加密分组链接模式(CBC)、加密反馈模式(CFB)和输出反馈模式(OFB)四种常用的分组密码加密模式。其中,AES使用的加密反馈模式(CFB)和输出反馈模式(OFB)分组长度是128位,其它算法使用的则是64位。事实上,DES算法里面不仅仅是常用的DES算法,还支持三个密钥和两个密钥3DES算法。
非对称加密算法
  OpenSSL一共实现了4种非对称加密算法,包括DH算法、RSA算法、DSA算法和椭圆曲线算法(EC)。DH算法一般用户密钥交换。RSA算法既可以用于密钥交换,也可以用于数字签名,当然,如果你能够忍受其缓慢的速度,那么也可以用于数据加密。DSA算法则一般只用于数字签名。
信息摘要算法
  OpenSSL实现了5种信息摘要算法,分别是MD2、MD5、MDC2、SHA(SHA1)和RIPEMD。SHA算法事实上包括了SHA和SHA1两种信息摘要算法,此外,OpenSSL还实现了DSS标准中规定的两种信息摘要算法DSS和DSS1。

我们来用VC++实现文件加密,请见代码实现与注释讲解

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <conio.h>  
  4. #include <windows.h>  
  5. #include <wincrypt.h>  
  6. #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)  
  7. #define KEYLENGTH  0x00800000  
  8. void HandleError(char *s);  
  9. HCRYPTPROV GetCryptProv();  
  10.   
  11. #define ENCRYPT_ALGORITHM CALG_RC4   
  12. #define ENCRYPT_BLOCK_SIZE 8   
  13.   
  14.   
  15. BOOL EncryptFile(  
  16.      PCHAR szSource,   
  17.      PCHAR szDestination,   
  18.      PCHAR szPassword);   
  19.   
  20. HCRYPTKEY GenKeyByPassword(HCRYPTPROV hCryptProv,PCHAR szPassword);  
  21. HCRYPTKEY GenKeyByRandom(HCRYPTPROV hCryptProv,FILE* hDestination);  
  22.    
  23. //-------------------------------------------------------------------  
  24. // Begin main.  
  25.   
  26. void main(void)   
  27. {   
  28.     PCHAR szSource;   
  29.     PCHAR szDestination;   
  30.     CHAR szPassword[100] = "";   
  31.     char  response;  
  32.    
  33.     if(!(szSource=(char *)malloc(100)))  
  34.         HandleError("Memory allocation failed.");  
  35.     if(!(szDestination=(char *)malloc(100)))  
  36.         HandleError("Memory allocation failed.");  
  37.   
  38.     printf("加密一个文件. \n\n");  
  39.     printf("请输入需要被加密文件的名称: ");  
  40.     fgets(szSource, 100, stdin);  
  41.     if(szSource[strlen(szSource)-1] == '\n')  
  42.          szSource[strlen(szSource)-1] = '\0';  
  43.     printf("请输入需要输出文件文件的名称: ");  
  44.     fgets(szDestination, 100, stdin);  
  45.     if(szDestination[strlen(szDestination)-1] == '\n')  
  46.          szDestination[strlen(szDestination)-1] = '\0';  
  47.     printf("要使用密码对这个文件加密吗? ( y/n ) ");  
  48.     response = getchar();  
  49.     if(response == 'y')  
  50.     {  
  51.         printf("请输入密码:");  
  52.         getchar();  
  53.         gets(szPassword);  
  54.     }  
  55.     else  
  56.     {  
  57.         printf("密钥将生成但没有使用密码. \n");  
  58.     }  
  59.   
  60.     //-------------------------------------------------------------------  
  61.     // 调用函数 EncryptFile 进行实际的加密操作.  
  62.    
  63.     if(EncryptFile(szSource, szDestination, szPassword))  
  64.     {  
  65.            printf("对文件 %s 的加密已经成功! \n",   
  66.                szSource);  
  67.            printf("加密后的数据存储在文件 %s 中.\n",szDestination);  
  68.     }  
  69.     else  
  70.     {  
  71.           HandleError("解密文件出错!");   
  72.     }  
  73.     //-------------------------------------------------------------------  
  74.     // 释放内存.  
  75.     if(szSource)  
  76.          free(szSource);  
  77.     if(szDestination)  
  78.          free(szDestination);  
  79.   
  80. // end main  
  81.    
  82. //-------------------------------------------------------------------  
  83. // 功能:加密原文szSource文件,加密后的数据存储在szDestination文件中  
  84. // 参数:  
  85. //  szSource:原文文件名  
  86. //  szDestination:加密后数据存储文件  
  87. //  szPassword:用户输入的密码  
  88. static BOOL EncryptFile(  
  89.         PCHAR szSource,   
  90.         PCHAR szDestination,   
  91.         PCHAR szPassword)  
  92. {   
  93.     //-------------------------------------------------------------------  
  94.     // 变量申明与初始化.  
  95.   
  96.     FILE *hSource;   
  97.     FILE *hDestination;   
  98.   
  99.     HCRYPTPROV hCryptProv;   
  100.     HCRYPTKEY hKey;   
  101.   
  102.   
  103.     PBYTE pbBuffer;   
  104.     DWORD dwBlockLen;   
  105.     DWORD dwBufferLen;   
  106.     DWORD dwCount;   
  107.    
  108.     //-------------------------------------------------------------------  
  109.     // 打开原文文件.   
  110.     if(hSource = fopen(szSource,"rb"))  
  111.     {  
  112.        printf("原文文件 %s 已经打开. \n", szSource);  
  113.     }  
  114.     else  
  115.     {   
  116.        HandleError("打开原文文件出错!");  
  117.     }   
  118.   
  119.     //-------------------------------------------------------------------  
  120.     // 打开目标文件.   
  121.     if(hDestination = fopen(szDestination,"wb"))  
  122.     {  
  123.          printf("目标文件 %s 已经打开. \n", szDestination);  
  124.     }  
  125.     else  
  126.     {  
  127.         HandleError("打开目标文件出错!");   
  128.     }  
  129.     //获取加密服务者句柄  
  130.     hCryptProv = GetCryptProv();  
  131.   
  132.     //-------------------------------------------------------------------  
  133.     // 创建会话密钥.  
  134.     if(!szPassword || strcmp(szPassword,"")==0 )   
  135.     {   
  136.        
  137.          //--------------------------------------------------------------  
  138.          // 当输入密码为空时,则创建随机的加密密钥,并导出创建的密钥保存到文件中.   
  139.   
  140.         hKey = GenKeyByRandom( hCryptProv, hDestination);  
  141.   
  142.            
  143.     }   
  144.     else   
  145.     {   
  146.          //--------------------------------------------------------------  
  147.          // 当输入密码不为空时,则通过输入密码创建加密密钥  
  148.   
  149.         hKey=GenKeyByPassword( hCryptProv, szPassword);  
  150.           
  151.     }   
  152.    
  153.     //--------------------------------------------------------------------  
  154.     // 因为加密算法按ENCRYPT_BLOCK_SIZE 大小块加密,所以被加密的  
  155.     // 数据长度必须是ENCRYPT_BLOCK_SIZE 的整数倍。下面计算一次加密的  
  156.     // 数据长度。  
  157.   
  158.     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;   
  159.   
  160.     //--------------------------------------------------------------------  
  161.     // 确定加密后密文数据块大小. 若是分组密码模式,则必须有容纳额外块的空间    
  162.   
  163.     if(ENCRYPT_BLOCK_SIZE > 1)   
  164.         dwBufferLen = dwBlockLen + ENCRYPT_BLOCK_SIZE;   
  165.     else   
  166.         dwBufferLen = dwBlockLen;   
  167.       
  168.     //-------------------------------------------------------------------  
  169.     // 分配内存空间.   
  170.     if(pbBuffer = (BYTE *)malloc(dwBufferLen))  
  171.     {  
  172.         printf("已经为缓冲区分配了内存. \n");  
  173.     }  
  174.     else  
  175.     {   
  176.         HandleError("所需内存不够. \n");   
  177.     }  
  178.   
  179.     //-------------------------------------------------------------------  
  180.     // 循环加密 原文件  
  181.     do   
  182.     {   
  183.   
  184.         //-------------------------------------------------------------------  
  185.         // 每次从原文件中读取dwBlockLen字节数据.   
  186.         dwCount = fread(pbBuffer, 1, dwBlockLen, hSource);   
  187.         if(ferror(hSource))  
  188.         {   
  189.             HandleError("读取明文文件出错!\n");  
  190.         }  
  191.    
  192.         //-------------------------------------------------------------------  
  193.         // 加密数据.   
  194.         if(!CryptEncrypt(  
  195.             hKey,           //密钥  
  196.             0,              //如果数据同时进行散列和加密,这里传入一个散列对象  
  197.             feof(hSource),  //如果是最后一个被加密的块,输入TRUE.如果不是输入FALSE.  
  198.                             //这里通过判断是否到文件尾来决定是否为最后一块。  
  199.             0,              //保留  
  200.             pbBuffer,       //输入被加密数据,输出加密后的数据  
  201.             &dwCount,       //输入被加密数据实际长度,输出加密后数据长度  
  202.             dwBufferLen))   //pbBuffer的大小。  
  203.         {   
  204.            HandleError("Error during CryptEncrypt. \n");   
  205.         }   
  206.   
  207.         //-------------------------------------------------------------------  
  208.         // 把加密后数据写到密文文件中   
  209.   
  210.         fwrite(pbBuffer, 1, dwCount, hDestination);   
  211.         if(ferror(hDestination))  
  212.         {   
  213.             HandleError("写入密文时出错.");  
  214.         }  
  215.   
  216.     }   while(!feof(hSource));   
  217.   
  218.     //-------------------------------------------------------------------  
  219.     // 关闭文件  
  220.   
  221.     if(hSource)  
  222.     {  
  223.         if(fclose(hSource))  
  224.             HandleError("关闭原文文件出错!");  
  225.     }  
  226.     if(hDestination)  
  227.     {  
  228.         if(fclose(hDestination))  
  229.             HandleError("关闭目标文件出错!");  
  230.     }  
  231.   
  232.     //-------------------------------------------------------------------  
  233.     // 释放内存空间.   
  234.   
  235.     if(pbBuffer)   
  236.          free(pbBuffer);   
  237.    
  238.     //-------------------------------------------------------------------  
  239.     // 销毁会话密钥  
  240.   
  241.     if(hKey)  
  242.     {  
  243.         if(!(CryptDestroyKey(hKey)))  
  244.             HandleError("Error during CryptDestroyKey");  
  245.     }  
  246.   
  247.     //-------------------------------------------------------------------  
  248.     // 释放CSP句柄  
  249.   
  250.     if(hCryptProv)  
  251.     {  
  252.         if(!(CryptReleaseContext(hCryptProv, 0)))  
  253.             HandleError("Error during CryptReleaseContext");  
  254.     }  
  255.     return(TRUE);   
  256. // end Encryptfile  
  257.   
  258.   
  259. //获取加密提供者句柄  
  260. HCRYPTPROV GetCryptProv()  
  261. {  
  262.     HCRYPTPROV hCryptProv;                      // 加密服务提供者句柄  
  263.       
  264.     //获取加密提供者句柄  
  265.     if(CryptAcquireContext(  
  266.                 &hCryptProv,         // 加密服务提供者句柄  
  267.                 NULL,                // 密钥容器名,这里使用登陆用户名  
  268.                 MS_ENHANCED_PROV,         // 加密服务提供者       
  269.                 PROV_RSA_FULL,       // 加密服务提供者类型,可以提供加密和签名等功能  
  270.                 0))                  // 标志  
  271.     {  
  272.         printf("加密服务提供者句柄获取成功!\n");  
  273.     }  
  274.     else  
  275.     {  
  276.           
  277.     
  278.         //重新建立一个新的密钥集  
  279.         if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))  
  280.         {  
  281.            HandleError("重新建立一个新的密钥集出错!");  
  282.         }  
  283.    
  284.     }  
  285.     return hCryptProv;  
  286. }  
  287.   
  288.   
  289. //  HandleError:错误处理函数,打印错误信息,并退出程序  
  290. void HandleError(char *s)  
  291. {  
  292.     printf("程序执行发生错误!\n");  
  293.     printf("%s\n",s);  
  294.     printf("错误代码为: %x.\n",GetLastError());  
  295.     printf("程序终止执行!\n");  
  296.     exit(1);  
  297. }  
  298.   
  299.   
  300. // GenKeyByRandom:通过随机数创建会话密钥  
  301. // 参数:hCryptProv CSP句柄  
  302. //       hDestination 目标文件,导出的会话密钥保存在此文件中  
  303. HCRYPTKEY GenKeyByRandom(HCRYPTPROV hCryptProv,FILE* hDestination)  
  304. {  
  305.     HCRYPTKEY hKey;   
  306.     HCRYPTKEY hXchgKey;   
  307.   
  308.     PBYTE pbKeyBlob;   
  309.     DWORD dwKeyBlobLen;   
  310.   
  311.     if(CryptGenKey(  
  312.           hCryptProv,   
  313.           ENCRYPT_ALGORITHM,   
  314.           KEYLENGTH | CRYPT_EXPORTABLE,   
  315.           &hKey))  
  316.       {  
  317.           printf("一个会话密钥已经被创建. \n");  
  318.       }   
  319.       else  
  320.       {  
  321.           HandleError("Error during CryptGenKey. \n");   
  322.       }  
  323.      //--------------------------------------------------------------  
  324.        // 创建交换密钥  
  325.        if(CryptGenKey(  
  326.            hCryptProv,  
  327.            AT_KEYEXCHANGE,  
  328.            0,  
  329.            &hXchgKey))   
  330.        {  
  331.            printf("交换密钥对已经创建.\n");  
  332.        }  
  333.        else  
  334.        {  
  335.           HandleError("在试图创建交换密钥时出错.\n");  
  336.        }  
  337.   
  338.      //--------------------------------------------------------------  
  339.      // 确定密钥数据块长度,并分配空间.   
  340.   
  341.      if(CryptExportKey(  
  342.            hKey,   
  343.            hXchgKey,   
  344.            SIMPLEBLOB,   
  345.            0,   
  346.            NULL,   
  347.            &dwKeyBlobLen))  
  348.      {  
  349.            printf("此密钥块的长度是 %d 字节. \n",dwKeyBlobLen);  
  350.        }  
  351.        else  
  352.        {    
  353.             HandleError("计算密钥数据块长度出错! \n");  
  354.        }  
  355.        if(pbKeyBlob =(BYTE *)malloc(dwKeyBlobLen))  
  356.        {   
  357.           printf("已经问此密钥块分配了内存. \n");  
  358.        }  
  359.        else  
  360.        {   
  361.           HandleError("所需内存不够. \n");   
  362.        }  
  363.      //--------------------------------------------------------------  
  364.      // 导出会话密钥到简单密钥数据块中.   
  365.    
  366.      if(CryptExportKey(  
  367.           hKey,   
  368.           hXchgKey,   
  369.           SIMPLEBLOB,   
  370.           0,   
  371.           pbKeyBlob,   
  372.           &dwKeyBlobLen))  
  373.        {  
  374.            printf("此会话密钥已经被导出. \n");  
  375.        }   
  376.        else  
  377.        {  
  378.            HandleError("Error during CryptExportKey!\n");  
  379.        }   
  380.      //--------------------------------------------------------------  
  381.      //释放交换密钥句柄.   
  382.   
  383.      if(hXchgKey)  
  384.      {  
  385.           if(!(CryptDestroyKey(hXchgKey)))  
  386.                HandleError("Error during CryptDestroyKey");   
  387.   
  388.           hXchgKey = 0;  
  389.      }  
  390.   
  391.      //--------------------------------------------------------------  
  392.      // 写密钥块长度到目标文件.   
  393.   
  394.      fwrite(&dwKeyBlobLen, sizeof(DWORD), 1, hDestination);   
  395.      if(ferror(hDestination))  
  396.      {   
  397.          HandleError("写密钥块长度出错.");  
  398.      }  
  399.      else  
  400.      {  
  401.          printf("密钥块长度已经被写入. \n");  
  402.      }  
  403.      //--------------------------------------------------------------  
  404.      //写密钥块数据到目标文件.   
  405.    
  406.      fwrite(pbKeyBlob, 1, dwKeyBlobLen, hDestination);   
  407.      if(ferror(hDestination))  
  408.      {   
  409.         HandleError("写密钥数据出错");  
  410.      }  
  411.      else  
  412.      {  
  413.         printf("此密钥块数据已经被写入目标文件. \n");  
  414.      }  
  415.      // 释放内存空间.  
  416.      free(pbKeyBlob);  
  417.      //返回创建的会话密钥  
  418.      return hKey;  
  419. }  
  420.   
  421. // GenKeyByRandom:通过输入密码创建会话密钥  
  422. // 参数:hCryptProv CSP句柄  
  423. //       szPassword 输入密码  
  424. HCRYPTKEY GenKeyByPassword(HCRYPTPROV hCryptProv,PCHAR szPassword)  
  425. {  
  426.     HCRYPTKEY hKey;   
  427.     HCRYPTHASH hHash;  
  428.     //-------------------------------------------------------------------  
  429.     // 创建哈希句柄.   
  430.   
  431.     if(CryptCreateHash(  
  432.            hCryptProv,   
  433.            CALG_MD5,   
  434.            0,   
  435.            0,   
  436.            &hHash))  
  437.         {  
  438.             printf("一个哈希句柄已经被创建. \n");  
  439.         }  
  440.         else  
  441.         {   
  442.              HandleError("Error during CryptCreateHash!\n");  
  443.         }    
  444.     //-------------------------------------------------------------------  
  445.     // 计算输入密码的哈希值.   
  446.   
  447.     if(CryptHashData(  
  448.            hHash,   
  449.            (BYTE *)szPassword,   
  450.            strlen(szPassword),   
  451.            0))  
  452.      {  
  453.         printf("密码已经被添加到了哈希表中. \n");  
  454.      }  
  455.      else  
  456.      {  
  457.         HandleError("Error during CryptHashData. \n");   
  458.      }  
  459.     //-------------------------------------------------------------------  
  460.     // 通过哈希值创建会话密钥.   
  461.   
  462.     if(CryptDeriveKey(  
  463.            hCryptProv,   
  464.            ENCRYPT_ALGORITHM,   
  465.            hHash,   
  466.            KEYLENGTH,   
  467.            &hKey))  
  468.      {  
  469.        printf("通过密码的哈希值获得了加密密钥. \n");   
  470.      }  
  471.      else  
  472.      {  
  473.        HandleError("Error during CryptDeriveKey!\n");   
  474.      }  
  475.     //-------------------------------------------------------------------  
  476.     // 销毁哈希句柄.   
  477.   
  478.     if(hHash)   
  479.     {  
  480.         if(!(CryptDestroyHash(hHash)))  
  481.            HandleError("Error during CryptDestroyHash");   
  482.         hHash = 0;  
  483.     }  
  484.   
  485.     //返回创建的会话密钥  
  486.     return hKey;  
  487. }  


 

我们来用VC++实现文件解密,请见代码实现与注释讲解

 

[cpp] view plaincopy
  1. #include <stdio.h>  
  2. #include <string.h>  
  3. #include <conio.h>  
  4. #include <windows.h>  
  5. #include <wincrypt.h>  
  6. #define MY_ENCODING_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)  
  7. #define KEYLENGTH  0x00800000  
  8. void HandleError(char *s);  
  9. HCRYPTPROV GetCryptProv();  
  10.   
  11. #define ENCRYPT_ALGORITHM CALG_RC4   
  12. #define ENCRYPT_BLOCK_SIZE 8   
  13.    
  14. BOOL DecryptFile(  
  15.      PCHAR szSource,   
  16.      PCHAR szDestination,   
  17.      CHAR *szPassword);   
  18.   
  19. HCRYPTKEY GenKeyByPassword(HCRYPTPROV hCryptProv,PCHAR szPassword);  
  20. HCRYPTKEY GenKeyFromFile(HCRYPTPROV hCryptProv,FILE* hSource);  
  21.   
  22. void main(void)   
  23. {   
  24.     //--------------------------------------------------------------------  
  25.     // 变量申明与初始化.  
  26.   
  27.     PCHAR szSource;   
  28.     PCHAR szDestination;   
  29.     CHAR szPassword[100] = "";   
  30.     char  response;  
  31.   
  32.     if(!(szSource=(char *)malloc(100)))  
  33.         HandleError("Memory allocation failed.");  
  34.     if(!(szDestination=(char *)malloc(100)))  
  35.         HandleError("Memory allocation failed.");  
  36.   
  37.     printf("解密一个文件. \n\n");  
  38.     printf("请输入需要解密文件的名称: ");  
  39.     fgets(szSource, 100, stdin);  
  40.     if(szSource[strlen(szSource)-1] == '\n')  
  41.          szSource[strlen(szSource)-1] = '\0';  
  42.     printf("请输入要输出文件的名称: ");  
  43.     fgets(szDestination, 100, stdin);  
  44.     if(szDestination[strlen(szDestination)-1] == '\n')  
  45.          szDestination[strlen(szDestination)-1] = '\0';  
  46.     printf("加密这个文件时是否使用了密码? ( y/n ) ");  
  47.     response = getchar();  
  48.     if(response == 'y')  
  49.     {  
  50.         getchar();  
  51.         printf("请输入密码:");         
  52.         gets(szPassword);  
  53.     }  
  54.     else  
  55.     {  
  56.         printf("密钥将被生成但没有使用密码. \n");  
  57.     }  
  58.     //解密文件  
  59.     if(!DecryptFile(szSource, szDestination, szPassword))  
  60.     {  
  61.         printf("\nError decrypting file. \n");   
  62.     }  
  63.     else  
  64.     {   
  65.         printf("\n对文件 %s 的解密成功了. \n", szSource);  
  66.         printf("被解密的文件是 %s .\n",szDestination);  
  67.     }  
  68.     //--------------------------------------------------------------------  
  69.     // 释放内存空间.  
  70.     if(szSource)  
  71.          free(szSource);  
  72.     if(szDestination)  
  73.          free(szDestination);  
  74.   
  75. // End main  
  76.   
  77. //-------------------------------------------------------------------  
  78. // 功能:解密密文szSource文件,解密后的数据存储在szDestination文件中  
  79. // 参数:  
  80. //  szSource:密文文件名  
  81. //  szDestination:解密后数据存储文件  
  82. //  szPassword:用户输入的密码  
  83.   
  84. static BOOL DecryptFile(  
  85.      PCHAR szSource,   
  86.      PCHAR szDestination,   
  87.      PCHAR szPassword)   
  88. {   
  89.     //--------------------------------------------------------------------  
  90.     // 局部变量申明与初始化.  
  91.   
  92.     FILE *hSource;   
  93.     FILE *hDestination;   
  94.   
  95.     HCRYPTPROV hCryptProv;   
  96.     HCRYPTKEY hKey;   
  97.   
  98.     PBYTE pbBuffer;   
  99.     DWORD dwBlockLen;   
  100.     DWORD dwBufferLen;   
  101.     DWORD dwCount;   
  102.   
  103.     BOOL status = FALSE;   
  104.    
  105.     //--------------------------------------------------------------------  
  106.     // 打开密文文件.   
  107.     if(!(hSource = fopen(szSource,"rb")))   
  108.     {  
  109.        HandleError("打开密文文件出错!");  
  110.     }  
  111.     //--------------------------------------------------------------------  
  112.     // 打开目标文件,用于存储解密后的数据.   
  113.   
  114.     if(!(hDestination = fopen(szDestination,"wb")))  
  115.     {  
  116.         HandleError("打开明文文件出错!");  
  117.     }  
  118.       
  119.     //获取加密服务者句柄  
  120.     hCryptProv = GetCryptProv();  
  121.   
  122.     //获取或创建会话密钥  
  123.     if(!szPassword|| strcmp(szPassword,"")==0 )   
  124.     {   
  125.         //--------------------------------------------------------------------  
  126.         //从密文文件导入保存的会话密钥   
  127.   
  128.         hKey = GenKeyFromFile( hCryptProv,hSource);  
  129.           
  130.     }   
  131.     else   
  132.     {   
  133.         //--------------------------------------------------------------------  
  134.         // 通过输入密码重新创建会话密钥.   
  135.    
  136.         hKey=GenKeyByPassword( hCryptProv, szPassword);  
  137.     }   
  138.    
  139.   
  140.     // 计算一次解密的数据长度,它是ENCRYPT_BLOCK_SIZE 的整数倍  
  141.   
  142.     dwBlockLen = 1000 - 1000 % ENCRYPT_BLOCK_SIZE;   
  143.     dwBufferLen = dwBlockLen;   
  144.   
  145.     //--------------------------------------------------------------------  
  146.     // 分配内存空间.   
  147.   
  148.     if(!(pbBuffer = (BYTE *)malloc(dwBufferLen)))  
  149.     {  
  150.        HandleError("所需内存不够!\n");   
  151.     }  
  152.     //--------------------------------------------------------------------  
  153.     // 解密密文文件,解密后数据保存在目标文件   
  154.   
  155.     do {   
  156.         //--------------------------------------------------------------------  
  157.         // 每次从密文文件中读取dwBlockLen字节数据.   
  158.   
  159.         dwCount = fread(  
  160.              pbBuffer,   
  161.              1,   
  162.              dwBlockLen,   
  163.              hSource);   
  164.         if(ferror(hSource))  
  165.         {  
  166.             HandleError("读取密文文件出错!");  
  167.         }  
  168.         //--------------------------------------------------------------------  
  169.         // 解密 数据  
  170.         if(!CryptDecrypt(  
  171.               hKey,   
  172.               0,   
  173.               feof(hSource),   
  174.               0,   
  175.               pbBuffer,   
  176.               &dwCount))  
  177.         {  
  178.            HandleError("Error during CryptDecrypt!");   
  179.         }  
  180.         //--------------------------------------------------------------------  
  181.         // 把解密后的数据写入目标文件中.   
  182.   
  183.         fwrite(  
  184.             pbBuffer,   
  185.             1,   
  186.             dwCount,   
  187.             hDestination);   
  188.         if(ferror(hDestination))  
  189.         {  
  190.            HandleError("Error writing plaintext!");   
  191.         }  
  192.     }   while(!feof(hSource));   
  193.   
  194.     status = TRUE;   
  195.   
  196.     //--------------------------------------------------------------------  
  197.     // 关闭文件  
  198.     if(hSource)  
  199.     {  
  200.         if(fclose(hSource))  
  201.             HandleError("关闭原文件出错");  
  202.     }  
  203.     if(hDestination)  
  204.     {  
  205.         if(fclose(hDestination))  
  206.             HandleError("关闭目标文件出错");  
  207.     }   
  208.    
  209.     //--------------------------------------------------------------------  
  210.     // 释放内存空间   
  211.   
  212.     if(pbBuffer)   
  213.          free(pbBuffer);   
  214.    
  215.     //--------------------------------------------------------------------  
  216.     // 销毁会话密钥  
  217.   
  218.     if(hKey)  
  219.     {  
  220.         if(!(CryptDestroyKey(hKey)))  
  221.             HandleError("Error during CryptDestroyKey");  
  222.     }   
  223.   
  224.     //--------------------------------------------------------------------  
  225.     // 释放CSP句柄  
  226.     if(hCryptProv)  
  227.     {  
  228.         if(!(CryptReleaseContext(hCryptProv, 0)))  
  229.             HandleError("Error during CryptReleaseContext");  
  230.     }   
  231.   
  232.     return status;  
  233. // end Decryptfile  
  234.   
  235.   
  236. //获取加密提供者句柄  
  237. HCRYPTPROV GetCryptProv()  
  238. {  
  239.     HCRYPTPROV hCryptProv;                      // 加密服务提供者句柄  
  240.       
  241.     //获取加密提供者句柄  
  242.     if(CryptAcquireContext(  
  243.                 &hCryptProv,         // 加密服务提供者句柄  
  244.                 NULL,                // 密钥容器名,这里使用登陆用户名  
  245.                 MS_ENHANCED_PROV,         // 加密服务提供者       
  246.                 PROV_RSA_FULL,       // 加密服务提供者类型,可以提供加密和签名等功能  
  247.                 0))                  // 标志  
  248.     {  
  249.         printf("加密服务提供者句柄获取成功!\n");  
  250.     }  
  251.     else  
  252.     {  
  253.           
  254.         //重新建立一个新的密钥集  
  255.         if(!CryptAcquireContext(&hCryptProv, NULL, MS_ENHANCED_PROV, PROV_RSA_FULL, CRYPT_NEWKEYSET))  
  256.         {  
  257.            HandleError("重新建立一个新的密钥集出错!");  
  258.         }  
  259.    
  260.     }  
  261.     return hCryptProv;  
  262. }  
  263.   
  264.   
  265. //  HandleError:错误处理函数,打印错误信息,并退出程序  
  266. void HandleError(char *s)  
  267. {  
  268.     printf("程序执行发生错误!\n");  
  269.     printf("%s\n",s);  
  270.     printf("错误代码为: %x.\n",GetLastError());  
  271.     printf("程序终止执行!\n");  
  272.     exit(1);  
  273. }  
  274.   
  275. // GenKeyFromFile:从密文文件中导出会话密钥  
  276. // 参数:hCryptProv CSP句柄  
  277. //       hSource   保存会话密钥的文件  
  278. HCRYPTKEY GenKeyFromFile(HCRYPTPROV hCryptProv,FILE* hSource)  
  279. {  
  280.     HCRYPTKEY hKey;   
  281.   
  282.     PBYTE pbKeyBlob;   
  283.     DWORD dwKeyBlobLen;   
  284.   
  285.     //从密文文件中获取密钥数据块长度,并分配内存空间.   
  286.     fread(&dwKeyBlobLen, sizeof(DWORD), 1, hSource);   
  287.     if(ferror(hSource) || feof(hSource))  
  288.     {  
  289.         HandleError("读取密文文件中密钥数据块长度出错!");   
  290.     }  
  291.     if(!(pbKeyBlob = (BYTE *)malloc(dwKeyBlobLen)))  
  292.     {  
  293.         HandleError("内存分配出错.");   
  294.     }  
  295.     //--------------------------------------------------------------------  
  296.     // 从密文文件中获取密钥数据块  
  297.   
  298.     fread(pbKeyBlob, 1, dwKeyBlobLen, hSource);   
  299.     if(ferror(hSource) || feof(hSource))  
  300.     {  
  301.         HandleError("读取密文文件中密钥数据块出错!\n");   
  302.     }  
  303.     //--------------------------------------------------------------------  
  304.     // 导入会话密钥到 CSP.   
  305.     if(!CryptImportKey(  
  306.           hCryptProv,   
  307.           pbKeyBlob,   
  308.           dwKeyBlobLen,   
  309.           0,   
  310.           0,   
  311.           &hKey))  
  312.     {  
  313.        HandleError("Error during CryptImportKey!");   
  314.     }  
  315.   
  316.     if(pbKeyBlob)   
  317.         free(pbKeyBlob);  
  318.       
  319.     //返回导出的会话密钥  
  320.     return hKey;  
  321. }  
  322.   
  323. // GenKeyByPassword:通过输入密码创建会话密钥  
  324. // 参数:hCryptProv CSP句柄  
  325. //       szPassword 输入密码  
  326. HCRYPTKEY GenKeyByPassword(HCRYPTPROV hCryptProv,PCHAR szPassword)  
  327. {  
  328.     HCRYPTKEY hKey;   
  329.     HCRYPTHASH hHash;  
  330.     //-------------------------------------------------------------------  
  331.     // 创建哈希句柄.    
  332.   
  333.     if(CryptCreateHash(  
  334.            hCryptProv,   
  335.            CALG_MD5,   
  336.            0,   
  337.            0,   
  338.            &hHash))  
  339.         {  
  340.             printf("一个哈希句柄已经被创建. \n");  
  341.         }  
  342.         else  
  343.         {   
  344.              HandleError("Error during CryptCreateHash!\n");  
  345.         }    
  346.     //-------------------------------------------------------------------  
  347.     // 计算输入密码的哈希值.   
  348.   
  349.     if(CryptHashData(  
  350.            hHash,   
  351.            (BYTE *)szPassword,   
  352.            strlen(szPassword),   
  353.            0))  
  354.      {  
  355.         printf("此密码已经被添加到了哈希表中. \n");  
  356.      }  
  357.      else  
  358.      {  
  359.         HandleError("Error during CryptHashData. \n");   
  360.      }  
  361.     //-------------------------------------------------------------------  
  362.     // 通过哈希值创建会话密钥.  
  363.   
  364.     if(CryptDeriveKey(  
  365.            hCryptProv,   
  366.            ENCRYPT_ALGORITHM,   
  367.            hHash,   
  368.            KEYLENGTH,   
  369.            &hKey))  
  370.      {  
  371.        printf("从这个密码的哈希值获得了一个加密密钥. \n");   
  372.      }  
  373.      else  
  374.      {  
  375.        HandleError("Error during CryptDeriveKey!\n");   
  376.      }  
  377.     //-------------------------------------------------------------------  
  378.     // 销毁哈希句柄.   
  379.   
  380.     if(hHash)   
  381.     {  
  382.         if(!(CryptDestroyHash(hHash)))  
  383.            HandleError("Error during CryptDestroyHash");   
  384.         hHash = 0;  
  385.     }  
  386.           
  387.     //返回创建的会话密钥  
  388.     return hKey;  
  389. }  
0 0
原创粉丝点击