VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--签名与验证 (转)

http://blog.csdn.net/yincheng01/article/details/5334546

windows Sdk for windows7 提供的CrytoAPI是微软推出的安全应用调用函数,用很小的代码就可以实现复杂的安全信息加密。

下面演示一个数字签名与验证,详情请见代码。可以用于信息安全。

·········10········20········30········40········50········60········70········80········90········100·······110·······120·······130·······140·······150
  1. #include <stdio.h>  
  2. #include <stdlib.h>  
  3. #include <windows.h>  
  4. #include "eboy_wincrypt.h"  
  5. //#include <wincrypt.h>  
  6.   
  7.   
  8. void HandleError(char *s);  
  9.   
  10.   
  11. //签名和验证  
  12. void sign()  
  13. {  
  14.     HCRYPTPROV hProv;                                               //CSP句柄  
  15.     //待签名的数据  
  16.     BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";      
  17.     DWORD dwBufferLen = strlen((char *)pbBuffer)+1;                 //待签名的数据长度  
  18.     HCRYPTHASH hHash;                                               //哈希句柄  
  19.     HCRYPTKEY hKey;                                                 //签名密钥句柄  
  20.     HCRYPTKEY hPubKey;                                              //公钥句柄  
  21.     BYTE *pbKeyBlob;                                                //保存密钥Blob缓冲区的指针  
  22.     BYTE *pbSignature;                                              //保存签名值缓冲区的指针  
  23.     DWORD dwSigLen;                                                 //签名长度  
  24.     DWORD dwBlobLen;                                                //数据长度  
  25.     DWORD i;  
  26.   
  27.     //--------------------------------------------------------------------  
  28.     // 打开CSP句柄  
  29.     if(CryptAcquireContext(  
  30.        &hProv,   
  31.        "test_16",//使用容器名为test_16的密钥  
  32.        NULL,   
  33.        PROV_RSA_FULL,   
  34.        0))   
  35.     {  
  36.          printf("打开CSP句柄成功!/n");  
  37.     }  
  38.     else//失败,可能是容器不存在  
  39.     {  
  40.         if(!CryptAcquireContext(  
  41.             &hProv,   
  42.             "test_16",//使用容器名为test_16的密钥  
  43.             NULL,   
  44.             PROV_RSA_FULL,   
  45.             CRYPT_NEWKEYSET))//创建test_16容器  
  46.         {  
  47.             HandleError("调用 CryptAcquireContext 失败。");  
  48.         }  
  49.     }  
  50.     //获得签名密钥句柄  
  51.   
  52.     if(CryptGetUserKey(     
  53.        hProv,      
  54.        AT_SIGNATURE,      
  55.        &hKey))   
  56.     {  
  57.         printf("获得签名密钥句柄成功 /n");  
  58.     }  
  59.     else  
  60.     {  
  61.         printf("获得签名密钥句柄失败,产生一个新RSA密钥对。 /n");  
  62.         if(!CryptAcquireContext(  
  63.             &hProv,   
  64.             "test_16",   
  65.             NULL,   
  66.             PROV_RSA_FULL,   
  67.             0))   
  68.         {  
  69.             HandleError("调用 CryptAcquireContext 失败。");    
  70.         }  
  71.         if(!CryptGenKey(hProv,2,CRYPT_EXPORTABLE|0x04000000,&hKey))//产生一对RSA密钥。  
  72.         {  
  73.             HandleError("调用 CryptGenKey 失败。");  
  74.         }  
  75.           
  76.     }  
  77.     //--------------------------------------------------------------------  
  78.     // 导出明文公钥,签名接收者可使用此公钥验证签名。  
  79.     if(CryptExportKey(     
  80.        hKey,      
  81.        NULL,      
  82.        PUBLICKEYBLOB,  
  83.        0,      
  84.        NULL,   
  85.        &dwBlobLen)) //第一次调用只得到数据长度  
  86.     {  
  87.          printf("导出公钥,获得公钥的长度成功 /n");  
  88.     }  
  89.     else  
  90.     {  
  91.          HandleError("调用 CryptExportKey 失败。");  
  92.     }  
  93.     //--------------------------------------------------------------------  
  94.     // 为pbKeyBlob申请内存  
  95.     if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))   
  96.     {  
  97.         ;  
  98.     }  
  99.     else  
  100.     {  
  101.         HandleError("内存不够了. /n");  
  102.     }  
  103.     //--------------------------------------------------------------------  
  104.     // 导出公钥  
  105.     if(CryptExportKey(     
  106.        hKey,   
  107.        NULL,      
  108.        PUBLICKEYBLOB,      
  109.        0,      
  110.        pbKeyBlob,      
  111.        &dwBlobLen))  
  112.     {  
  113.          printf("导出公钥,获得公钥数据成功! /n");  
  114.     }  
  115.     else  
  116.     {  
  117.         HandleError("调用 CryptExportKey 失败。");  
  118.     }  
  119.     //--------------------------------------------------------------------  
  120.     // 创建哈希句柄,指定哈希算法,这里采用CALG_SHA1,即SHA1算法。  
  121.     if(CryptCreateHash(  
  122.        hProv,   
  123.        CALG_SHA1,   
  124.        0,   
  125.        0,   
  126.        &hHash))   
  127.     {  
  128.          printf("创建哈希句柄成功. /n");  
  129.     }  
  130.     else  
  131.     {  
  132.         HandleError("调用 CryptCreateHash 失败。");  
  133.     }  
  134.     //--------------------------------------------------------------------  
  135.     //计算哈希  
  136.     if(CryptHashData(  
  137.        hHash,   
  138.        pbBuffer,   
  139.        dwBufferLen,   
  140.        0))   
  141.     {  
  142.          printf(" 计算哈希成功/n");  
  143.     }  
  144.     else  
  145.     {  
  146.          HandleError("调用 CryptHashData 失败。");  
  147.     }  
  148.     //--------------------------------------------------------------------  
  149.     // 计算签名,第一次调用获得签名后的数据长度  
  150.     dwSigLen= 0;  
  151.     if(CryptSignHash(  
  152.        hHash,   
  153.        AT_SIGNATURE,   
  154.        NULL,   
  155.        0,   
  156.        NULL,   
  157.        &dwSigLen))   
  158.     {  
  159.          printf("签名值的长度为%d/n",dwSigLen);  
  160.     }  
  161.     else  
  162.     {  
  163.          HandleError("调用 CryptSignHash 失败。");  
  164.     }  
  165.   
  166.     if(pbSignature = (BYTE *)malloc(dwSigLen))  
  167.     {  
  168.          ;  
  169.     }  
  170.     else  
  171.     {  
  172.          HandleError("内存不够了.");  
  173.     }  
  174.     //--------------------------------------------------------------------  
  175.     // 对哈希对象签名  
  176.   
  177.     if(CryptSignHash(  
  178.        hHash,   
  179.        AT_SIGNATURE,   
  180.        NULL,   
  181.        0,   
  182.        pbSignature,   
  183.        &dwSigLen))   
  184.     {  
  185.          printf("数据签名成功!/n");  
  186.     }  
  187.     else  
  188.     {  
  189.          HandleError("调用 CryptSignHash 失败。");  
  190.     }  
  191.     //--------------------------------------------------------------------  
  192.     // 销毁哈希对象  
  193.     if(hHash)   
  194.       CryptDestroyHash(hHash);  
  195.     printf("签名值:/n");  
  196.     for( i=0;i<dwSigLen;i++)   
  197.     {  
  198.         if((i%16==0) &&(i!=0))  
  199.             printf("/n");  
  200.         printf("%2.2x ",pbSignature[i]);  
  201.     }  
  202.     printf("/n");  
  203.     printf("签名完成./n/n");  
  204.     //签名完成,以下是验证签名。首先把公钥导入得到公钥句柄,使用公钥验证签名.  
  205.   
  206.     //把公钥导入CSP  
  207.     if(CryptImportKey(  
  208.        hProv,  
  209.        pbKeyBlob,  
  210.        dwBlobLen,  
  211.        0,  
  212.        0,  
  213.        &hPubKey))  
  214.     {  
  215.          printf("导入公钥成功。/n");  
  216.     }  
  217.     else  
  218.     {  
  219.          HandleError("调用 CryptImportKey 失败。");  
  220.     }  
  221.     //--------------------------------------------------------------------  
  222.     // 创建哈希对象  
  223.   
  224.     if(CryptCreateHash(  
  225.        hProv,   
  226.        CALG_SHA1,   
  227.        0,   
  228.        0,   
  229.        &hHash))   
  230.     {  
  231.          printf("创建哈希对象成功. /n");  
  232.     }  
  233.     else  
  234.     {  
  235.          HandleError("调用 CryptCreateHash 失败。");  
  236.     }  
  237.     //--------------------------------------------------------------------  
  238.     // 计算哈希  
  239.   
  240.     if(CryptHashData(  
  241.        hHash,   
  242.        pbBuffer,   
  243.        dwBufferLen,   
  244.        0))   
  245.     {  
  246.          printf("数据哈希完成./n");  
  247.     }  
  248.     else  
  249.     {  
  250.         HandleError("调用 CryptHashData 失败。");  
  251.     }  
  252.     //--------------------------------------------------------------------  
  253.     // 验证签名  
  254.   
  255.     if(CryptVerifySignature(  
  256.        hHash,   
  257.        pbSignature,   
  258.        dwSigLen,   
  259.        hPubKey,  
  260.        NULL,   
  261.        0))   
  262.     {  
  263.          printf("验证签名成功./n");  
  264.     }  
  265.     else  
  266.     {  
  267.         HandleError("验证签名失败,签名无效");  
  268.     }  
  269.     //--------------------------------------------------------------------  
  270.     // 释放内存  
  271.   
  272.     if(pbSignature)  
  273.       free(pbSignature);  
  274.   
  275.     //--------------------------------------------------------------------  
  276.     // 销毁哈希对象  
  277.   
  278.     if(hHash)   
  279.       CryptDestroyHash(hHash);  
  280.   
  281.     //--------------------------------------------------------------------  
  282.     // 释放CSP句柄  
  283.     if(hProv)   
  284.        CryptReleaseContext(hProv, 0);  
  285. }   
  286. //出错处理函数  
  287. void HandleError(char *s)  
  288. {  
  289.     printf("本程序在运行时有错误发生./n");  
  290.     printf("%s/n",s);  
  291.     printf("错误码: %x/n.",GetLastError());  
  292.     printf("程序退出./n");  
  293.     exit(1);  
  294. }  
  295. int main()  
  296. {  
  297.     sign();  
  298.     return 0;  
  299. }  

本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!

posted @ 2011-11-03 15:38  董雨  阅读(289)  评论(0编辑  收藏  举报