#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include "eboy_wincrypt.h"
//#include <wincrypt.h>
void HandleError(char *s);
//签名和验证
void Test_16()
{
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()
{
Test_16();
return 0;
}
数字签名
最新推荐文章于 2021-01-25 04:43:07 发布