#define _WIN32_WINNT 0x0400
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <wincrypt.h>
void HandleError(char *s);
void Test(){
HCRYPTPROV hProv;
BYTE *pbBuffer=(BYTE *)"the data 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",//使用容器名为test的密钥
NULL,
PROV_RSA_FULL,
0))
{
printf("打开句柄成功!/n");
}
else//失败,可能是容器不存在
{
if(!CryptAcquireContext(
&hProv,
"test",
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET ))//创建test容器
{
HandleError("调用CryptAcquireContext失败。");
}
}
//-------------csp句柄打开完成------------------------------
//-------------获得签名密钥句柄-----------------------------
if(CryptGetUserKey(
hProv,
AT_SIGNATURE,
&hKey))
{
printf("获得签名密钥句柄成功/n");
}
else
{
printf("获得签名句柄失败,产生一个新的RSA密钥对。/n");
if(!CryptAcquireContext(
&hProv,
"test",
NULL,
PROV_RSA_FULL,
0))
{
HandleError("调用CryptAcquireContext 失败。");
}
//产生一对RSA密钥
if(!CryptGenKey(hProv,2,CRYPT_EXPORTABLE|0x04000000,&hKey))
{
HandleError("调用CryptGenKey失败。");
}
}
//--------------获得签名密钥句柄完成-----------------------------------------------
//导出明文公钥,签名接收者可使用此公钥验证签名
//----------获取明文公钥----------------------------------------------------------------
if(CryptExportKey(
hKey,
NULL,
PUBLICKEYBLOB,
0,
NULL,
&dwBlobLen)) //第一次调用只得到数据长度
{
printf("导出公钥,获得公钥的长度成功 /n");
}
else
{
HandleError("调用CryptExportKey失败。");
}
//------------------------------------------------------------
//为pbKeyBlob申请内存
if(pbKeyBlob=(BYTE*)malloc(dwBlobLen))
{
;
}
else
{
HandleError("内存不够了,/n");
}
//--------------------------------------------------------------
//第二次调用将导出公钥,并保存到pbKeyBlob内存中
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, //对输入的数据进行hash运算,保存输出后的hash摘要数据
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("内存不够啦。");
}
//-----------对hash对象签名------------------------------------------
if(CryptSignHash(
hHash,
AT_SIGNATURE,
NULL,
0,
pbSignature,
&dwSigLen))
{
printf("数据签名成功!/n");
}
else
{
HandleError("调用cryptSignHash失败。");
}
//------------数字签名完成-------------------------------------------
//------------输出签名数据-------------------------------------------
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");
//---------释放资源--------------
//销毁哈希对象
if(hHash)
CryptDestroyHash(hHash);
//-------------------------------
//========================================================================
//-----------以下为验证签名-------------------
//首先把公钥导入得到公钥句柄,使用公钥验证签名
//========================================================================
//----------------把公钥导入到csp------------------------------------
if(CryptImportKey(
hProv,
pbKeyBlob,
dwBlobLen,
0,
0,
&hPubKey))
{
printf("导入公钥成功。/n");
}
else
{
HandleError("导入CryptImportKey失败。");
}
//--------------公钥导入完成---------------------------------------------------------
//--------------创建hash对象--------------------------------------------
if(CryptCreateHash(
hProv,
CALG_SHA1,
0,
0,
&hHash))
{
printf("创建哈希对象成功 /n");
}
else
{
HandleError("调用CryptCreateHash失败");
}
//--------------创建hash对象完成-----------------------------------------------------------
//--------------计算哈希-----------------------------------
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);
//销毁句柄对象
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(){
Test();
return 0;
}
//-----------签名完成---------------------------