⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 inituser.c

📁 C++编程实践与技巧一书各章节的源码
💻 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 + -