winzenghua 发表于 2013-2-7 04:27:21

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

windows Sdk for windows7 提供的CrytoAPI是微软推出的安全应用调用函数,用很小的代码就可以实现复杂的安全信息加密。
下面演示一个数字签名与验证,详情请见代码。可以用于信息安全。
#include <stdio.h>#include <stdlib.h>#include <windows.h>#include "eboy_wincrypt.h"//#include <wincrypt.h>void HandleError(char *s);//签名和验证void sign(){HCRYPTPROV hProv;//CSP句柄//待签名的数据BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";DWORD dwBufferLen = strlen((char *)pbBuffer)+1;//待签名的数据长度HCRYPTHASH hHash;//哈希句柄HCRYPTKEY hKey;//签名密钥句柄HCRYPTKEY hPubKey;//公钥句柄BYTE *pbKeyBlob;//保存密钥Blob缓冲区的指针BYTE *pbSignature;//保存签名值缓冲区的指针DWORD dwSigLen;//签名长度DWORD dwBlobLen;//数据长度DWORD i;//--------------------------------------------------------------------// 打开CSP句柄if(CryptAcquireContext(   &hProv,    "test_16",//使用容器名为test_16的密钥   NULL,    PROV_RSA_FULL,    0)) { printf("打开CSP句柄成功!\n");}else//失败,可能是容器不存在{if(!CryptAcquireContext(&hProv, "test_16",//使用容器名为test_16的密钥NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET))//创建test_16容器{HandleError("调用 CryptAcquireContext 失败。");}}//获得签名密钥句柄if(CryptGetUserKey(      hProv,       AT_SIGNATURE,       &hKey)) {printf("获得签名密钥句柄成功 \n");}else{printf("获得签名密钥句柄失败,产生一个新RSA密钥对。 \n");if(!CryptAcquireContext(&hProv, "test_16", NULL, PROV_RSA_FULL, 0)) {HandleError("调用 CryptAcquireContext 失败。");}if(!CryptGenKey(hProv,2,CRYPT_EXPORTABLE|0x04000000,&hKey))//产生一对RSA密钥。{HandleError("调用 CryptGenKey 失败。");}}//--------------------------------------------------------------------// 导出明文公钥,签名接收者可使用此公钥验证签名。if(CryptExportKey(      hKey,       NULL,       PUBLICKEYBLOB,   0,       NULL,    &dwBlobLen)) //第一次调用只得到数据长度{ printf("导出公钥,获得公钥的长度成功 \n");}else{ HandleError("调用 CryptExportKey 失败。");}//--------------------------------------------------------------------// 为pbKeyBlob申请内存if(pbKeyBlob = (BYTE*)malloc(dwBlobLen)) {;}else{HandleError("内存不够了. \n");}//--------------------------------------------------------------------// 导出公钥if(CryptExportKey(      hKey,    NULL,       PUBLICKEYBLOB,       0,       pbKeyBlob,       &dwBlobLen)){ printf("导出公钥,获得公钥数据成功! \n");}else{HandleError("调用 CryptExportKey 失败。");}//--------------------------------------------------------------------// 创建哈希句柄,指定哈希算法,这里采用CALG_SHA1,即SHA1算法。if(CryptCreateHash(   hProv,    CALG_SHA1,    0,    0,    &hHash)) { printf("创建哈希句柄成功. \n");}else{HandleError("调用 CryptCreateHash 失败。");}//--------------------------------------------------------------------//计算哈希if(CryptHashData(   hHash,    pbBuffer,    dwBufferLen,    0)) { printf(" 计算哈希成功\n");}else{ HandleError("调用 CryptHashData 失败。");}//--------------------------------------------------------------------// 计算签名,第一次调用获得签名后的数据长度dwSigLen= 0;if(CryptSignHash(   hHash,    AT_SIGNATURE,    NULL,    0,    NULL,    &dwSigLen)) { printf("签名值的长度为%d\n",dwSigLen);}else{ HandleError("调用 CryptSignHash 失败。");}if(pbSignature = (BYTE *)malloc(dwSigLen)){ ;}else{ HandleError("内存不够了.");}//--------------------------------------------------------------------// 对哈希对象签名if(CryptSignHash(   hHash,    AT_SIGNATURE,    NULL,    0,    pbSignature,    &dwSigLen)) { printf("数据签名成功!\n");}else{ HandleError("调用 CryptSignHash 失败。");}//--------------------------------------------------------------------// 销毁哈希对象if(hHash)   CryptDestroyHash(hHash);printf("签名值:\n");for( i=0;i<dwSigLen;i++) {if((i%16==0) &&(i!=0))printf("\n");printf("%2.2x ",pbSignature);}printf("\n");printf("签名完成.\n\n");//签名完成,以下是验证签名。首先把公钥导入得到公钥句柄,使用公钥验证签名.//把公钥导入CSPif(CryptImportKey(   hProv,   pbKeyBlob,   dwBlobLen,   0,   0,   &hPubKey)){ printf("导入公钥成功。\n");}else{ HandleError("调用 CryptImportKey 失败。");}//--------------------------------------------------------------------// 创建哈希对象if(CryptCreateHash(   hProv,    CALG_SHA1,    0,    0,    &hHash)) { printf("创建哈希对象成功. \n");}else{ HandleError("调用 CryptCreateHash 失败。");}//--------------------------------------------------------------------// 计算哈希if(CryptHashData(   hHash,    pbBuffer,    dwBufferLen,    0)) { printf("数据哈希完成.\n");}else{HandleError("调用 CryptHashData 失败。");}//--------------------------------------------------------------------// 验证签名if(CryptVerifySignature(   hHash,    pbSignature,    dwSigLen,    hPubKey,   NULL,    0)) { printf("验证签名成功.\n");}else{HandleError("验证签名失败,签名无效");}//--------------------------------------------------------------------// 释放内存if(pbSignature)free(pbSignature);//--------------------------------------------------------------------// 销毁哈希对象if(hHash)   CryptDestroyHash(hHash);//--------------------------------------------------------------------// 释放CSP句柄if(hProv)    CryptReleaseContext(hProv, 0);} //出错处理函数void HandleError(char *s){    printf("本程序在运行时有错误发生.\n");    printf("%s\n",s);    printf("错误码: %x\n.",GetLastError());    printf("程序退出.\n");    exit(1);}int main(){sign();return 0;}
本文作者专著《Visual C++2010开发权威指南》即将推出,敬请关注,Visual C++2010最近技术,Windows7开发最新技术!
页: [1]
查看完整版本: VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--签名与验证