#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
void MyHandleError(char *s);
void main(void)
{
//-------------------------------------------------------------
// Declare and initialize variables.
HCRYPTPROV hProv;
BYTE *pbBuffer= (BYTE *)"The data that is to be hashed and signed.";//被签名的数据
DWORD dwBufferLen = strlen((char *)pbBuffer)+1;
HCRYPTHASH hHash;
HCRYPTKEY hKey;
BYTE *pbKeyBlob; //签名者得公钥数据
BYTE *pbSignature; //数字签名
DWORD dwSigLen;
DWORD dwBlobLen;
LPTSTR szDescription = "Test Data Description";
//--------------------------------------------------------------------
// 获得CSP句柄,密钥容器名为登陆用户名
if(CryptAcquireContext(
&hProv,
NULL,
NULL,
PROV_RSA_FULL,
0))
{
printf("CSP context acquired.\n");
}
else //密钥容器不存在创建之
{
if(CryptAcquireContext(
&hProv,
NULL,
NULL,
PROV_RSA_FULL,
CRYPT_NEWKEYSET))
{
printf("A new key container has been created.\n");
}
else
{
MyHandleError("Error during CryptAcquireContext.");
}
}
//--------------------------------------------------------------------
// 从密钥容器中取数字签名用的密钥
if(CryptGetUserKey(
hProv,
AT_SIGNATURE,
&hKey))
{
printf("The signature key has been acquired. \n");
}
else
{
if(GetLastError() == NTE_NO_KEY) //密钥容器里不存在signature key pair创建之
{
if(CryptGenKey(
hProv, //CSP句柄
AT_SIGNATURE, //创建的密钥对类型为signature key pair
0, //key类型,这里用默认值
&hKey)) //创建成功返回新创建的密钥对的句柄
{
printf("Created a signature key pair.\n");
}
else
{
MyHandleError("Error occurred creating a signature key.\n");
}
}
else
{
MyHandleError("Error during CryptGetUserKey for signkey.");
}
}
//--------------------------------------------------------------------
// 因为接收消息者要验证数字签名,所以要导出公钥给接收者。
if(CryptExportKey(
hKey,
NULL,
PUBLICKEYBLOB,
0,
NULL,
&dwBlobLen)) //得到公钥的大小
{
printf("Size of the BLOB for the public key determined. \n");
}
else
{
MyHandleError("Error computing BLOB length.");
}
//--------------------------------------------------------------------
// 为存储公钥的缓冲区分配内存。
if(pbKeyBlob = (BYTE*)malloc(dwBlobLen))
{
printf("Memory has been allocated for the BLOB. \n");
}
else
{
MyHandleError("Out of memory. \n");
}
//--------------------------------------------------------------------
// 真正导出公钥数据
if(CryptExportKey(
hKey,
NULL,
PUBLICKEYBLOB,
0,
pbKeyBlob, //这个数据可以存入文件,发送给接收者。一般被存入数字证书
&dwBlobLen))
{
printf("Contents have been written to the BLOB. \n");
}
else
{
MyHandleError("Error during CryptExportKey.");
}
//--------------------------------------------------------------------
// 创建hash对象
if(CryptCreateHash(
hProv,
CALG_MD5,
0,
0,
&hHash))
{
printf("Hash object created. \n");
}
else
{
MyHandleError("Error during CryptCreateHash.");
}
//--------------------------------------------------------------------
// 对数据进行hash运算
if(CryptHashData(
hHash,
pbBuffer,
dwBufferLen,
0))
{
printf("The data buffer has been hashed.\n");
}
else
{
MyHandleError("Error during CryptHashData.");
}
//--------------------------------------------------------------------
// 使用signature key pair的私钥对hash数据签名
dwSigLen= 0;
if(CryptSignHash(
hHash,
AT_SIGNATURE,
szDescription,
0,
NULL,
&dwSigLen)) //得到数字签名大小
{
printf("Signature length %d found.\n",dwSigLen);
}
else
{
MyHandleError("Error during CryptSignHash.");
}
//--------------------------------------------------------------------
// 为数字签名缓冲区分配内存
if(pbSignature = (BYTE *)malloc(dwSigLen))
{
printf("Memory allocated for the signature.\n");
}
else
{
MyHandleError("Out of memory.");
}
//--------------------------------------------------------------------
// 得到数字签名
if(CryptSignHash(
hHash,
AT_SIGNATURE,
szDescription,
0,
pbSignature, //这里将返回数字签名,同被签名的数据一起发送给接收方
&dwSigLen))
{
printf("pbSignature is the hash signature.\n");
}
else
{
MyHandleError("Error during CryptSignHash.");
}
//--------------------------------------------------------------------
// Destroy the hash object.
if(hHash)
CryptDestroyHash(hHash);
printf("The hash object has been destroyed.\n");
printf("The signing phase of this program is completed.\n\n");
//--------------------------------------------------------------------
// 下面的代码应该是接收者使用的,这里为了说明方便就把它放在一个文件里了。
// pbBuffer, pbSignature, szDescription, pbKeyBlob, 还有他们的长度
// 在这里直接使用了,应该是接收者从文件或其他地方读取的。
// pbBuffer 里保存的是被签名的数据,所以认证时的内容必须跟签名时的一样
// 这里使用的CSP句柄也没有重新创建
// Point szDescription at the text describing the data being
// signed. This is the same description text that was originally
// passed to CryptSignHash.
//--------------------------------------------------------------------
// 把签名者的公钥数据导入生成公钥句柄
HCRYPTKEY hPubKey;
if(CryptImportKey(
hProv,
pbKeyBlob,
dwBlobLen,
0,
0,
&hPubKey))
{
printf("The key has been imported.\n");
}
else
{
MyHandleError("Public key import failed.");
}
//--------------------------------------------------------------------
// 创建哈希对象
if(CryptCreateHash(