VC++2010基于windows Sdk for windows7 开发CrytoAPI应用--签名与验证 (转)
http://blog.csdn.net/yincheng01/article/details/5334546
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[i]);
- }
- printf("/n");
- printf("签名完成./n/n");
- //签名完成,以下是验证签名。首先把公钥导入得到公钥句柄,使用公钥验证签名.
- //把公钥导入CSP
- if(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开发最新技术!