📄 inituser.c
字号:
// certsignver.c 利用证书技术的签名和验证演示程序
#include <stdio.h>
#include <windows.h>
#include <wincrypt.h>
#define MY_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
// 定义证书主题的名字
// 要成功运行该程序,SIGNER_NAME必须为能够使用签名私钥的证书主题名
#define SIGNER_NAME L"Zeke"
//--------------------------------------------------------------------
// 定义证书库名字
#define CERT_STORE_NAME L"MY"
//--------------------------------------------------------------------
void HandleError(char *s);
void main(void)
{
//--------------------------------------------------------------------
HCERTSTORE hStoreHandle; //系统库句柄
// 要签名的消息
BYTE* pbMessage =
(BYTE*)"这些是要签名的消息";
//--------------------------------------------------------------------
//要签名消息的大小
DWORD cbMessage = strlen((char*) pbMessage)+1;
//--------------------------------------------------------------------
PCCERT_CONTEXT pSignerCert; //指向签名者证书的指针
CRYPT_SIGN_MESSAGE_PARA SigParams;
DWORD cbSignedMessageBlob;
BYTE *pbSignedMessageBlob;
DWORD cbDecodedMessageBlob;
BYTE *pbDecodedMessageBlob;
CRYPT_VERIFY_MESSAGE_PARA VerifyParams;
//--------------------------------------------------------------------
// 创建MessageArray和MessageSizeArray.
const BYTE* MessageArray[] = {pbMessage};
DWORD MessageSizeArray[1];
MessageSizeArray[0] = cbMessage;
//--------------------------------------------------------------------
//开始签名处理,首先显示原始信息
printf("开始消息处理\n");
printf("要签名的消息为\n-> %s.\n",pbMessage);
//--------------------------------------------------------------------
//打开证书库
if ( !( hStoreHandle = CertOpenStore(
CERT_STORE_PROV_SYSTEM,
0,
NULL,
CERT_SYSTEM_STORE_CURRENT_USER,
CERT_STORE_NAME)))
{
HandleError("证书库打开失败");
}
//--------------------------------------------------------------------
// 获取签名者证书的指针
//该证书必须能够使用签名者的私钥
if(pSignerCert = CertFindCertificateInStore(
hStoreHandle,
MY_TYPE,
0,
CERT_FIND_SUBJECT_STR,
SIGNER_NAME,
NULL))
{
printf("已找到签名者证书\n");
}
else
{
HandleError( "签名证书没有被找到");
}
//--------------------------------------------------------------------
// 签名结构初始化
SigParams.cbSize = sizeof(CRYPT_SIGN_MESSAGE_PARA);
SigParams.dwMsgEncodingType = MY_TYPE;
SigParams.pSigningCert = pSignerCert;
SigParams.HashAlgorithm.pszObjId = szOID_RSA_MD5;
SigParams.HashAlgorithm.Parameters.cbData = NULL;
SigParams.cMsgCert = 1;
SigParams.rgpMsgCert = &pSignerCert;
SigParams.cAuthAttr = 0;
SigParams.dwInnerContentType = 0;
SigParams.cMsgCrl = 0;
SigParams.cUnauthAttr = 0;
SigParams.dwFlags = 0;
SigParams.pvHashAuxInfo = NULL;
SigParams.rgAuthAttr = NULL;
//--------------------------------------------------------------------
// 调用两次CryptSignMessage签名消息
// 首先,获取输出签名块的大小
if(CryptSignMessage(
&SigParams, //签名参数
FALSE, // 不附加
1, // 消息数目
MessageArray, // 要签名的消息
MessageSizeArray, // 要签名的消息大小
NULL, // 签名后消息缓存
&cbSignedMessageBlob)) // 签名后消息缓存大小
{
printf("签名后消息块大小为%d\n",cbSignedMessageBlob);
}
else
{
HandleError("获取签名块大小失败");
}
//--------------------------------------------------------------------
//为签名块分配内存
if(!(pbSignedMessageBlob =
(BYTE*)malloc(cbSignedMessageBlob)))
{
HandleError("签名时内存分配出错");
}
//--------------------------------------------------------------------
//获取签名消息SignedMessageBlob.
if(CryptSignMessage(
&SigParams, // 签名参数
FALSE, // 不附加
1, // 消息数目
MessageArray, // 要签名的消息
MessageSizeArray, // 要签名的消息大小
pbSignedMessageBlob, // 签名后消息缓存
&cbSignedMessageBlob)) // 签名后消息缓存大小
{
printf("消息签名成功\n");
}
else
{
HandleError("消息签名失败");
}
//--------------------------------------------------------------------
// pbSignedMessageBlob指向签名块
//--------------------------------------------------------------------
//验证签名消息,下面的代码可以放在一个单独的程序中用于验证签名。
//--------------------------------------------------------------------
//初始化签名验证参数VerifyParams数据结构
VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
VerifyParams.dwMsgAndCertEncodingType = MY_TYPE;
VerifyParams.hCryptProv = 0;
VerifyParams.pfnGetSignerCertificate = NULL;
VerifyParams.pvGetArg = NULL;
//--------------------------------------------------------------------
// 两次调用CryptVerifyMessageSignature,验证并解码签名消息。
// 第一次调用CryptVerifyMessageSignature函数获取
//解码后消息所需缓存的大小
//因为网络传输的签名信息都是经过编码后传输的,
//所有验证签名之前要对数据进行解码
if(CryptVerifyMessageSignature(
&VerifyParams, // 验证参数
0, // 签名者索引
pbSignedMessageBlob, // 指向签名块的指针
cbSignedMessageBlob, // 签名块大小
NULL, // 解码后消息缓存
&cbDecodedMessageBlob, // 解码后消息大小
NULL)) // 指向签名者证书的指针
{
printf("共需要%d字节的缓存\n",cbDecodedMessageBlob);
}
else
{
printf("消息验证失败\n");
}
//--------------------------------------------------------------------
//内存分配
if(!(pbDecodedMessageBlob =
(BYTE*)malloc(cbDecodedMessageBlob)))
{
HandleError("为解码数据块分配内存失败");
}
//--------------------------------------------------------------------
// 再次调用CryptVerifyMessageSignature函数把消息拷贝到缓存中
if(CryptVerifyMessageSignature(
&VerifyParams, // 验证参数
0, // 签名这索引
pbSignedMessageBlob, // 指向签名块的指针
cbSignedMessageBlob, // 签名块大小
pbDecodedMessageBlob, // 存放解码后消息的缓存
&cbDecodedMessageBlob, // 解码缓存大小
NULL)) // 指向签名者证书的指针
{
printf("验证的消息为\n-> %s \n",pbDecodedMessageBlob);
}
else
{
printf("验证消息失败\n");
}
//--------------------------------------------------------------------
//内存释放
if(pbSignedMessageBlob)
free(pbSignedMessageBlob);
if(pbDecodedMessageBlob)
free(pbDecodedMessageBlob);
if(pSignerCert)
CertFreeCertificateContext(pSignerCert);
if(CertCloseStore(
hStoreHandle,
CERT_CLOSE_STORE_CHECK_FLAG))
{
printf("库已经关闭,所有的证书都已经释放\n");
}
else
{
printf("签名后证书库关闭 -- \n"
"并非所有的证书,CRLs或CTLs都被释放");
}
} // End of main
//错误处理函数
void HandleError(char *s)
{
printf("在运行程序时出现错误\n");
printf("%s\n",s);
printf("错误代号 %x\n.",GetLastError());
printf("程序终止运行\n");
exit(1);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -