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开发最新技术!