现在的位置: 首页 > 综合 > 正文

编写ATL工程实现ActiveX控件调用cryptoAPI接口(一)————签名与验证

2014年12月13日 ⁄ 综合 ⁄ 共 21985字 ⁄ 字号 评论关闭

注:下面的代码中用了Map,Base64,log,Result等都为自定义类型,太长就不一一贴出.

/*
* 
* 
* 文件名称:Signer.cpp
* 摘    要:
*		数字签名及验证
* 当前版本:1.0
* 作    者:周绍禹
* 创建日期:2012年3月4日
*/
#include "StdAfx.h"
#include "Signer.h"
#include "Map.h"
#include "generic.h"
#include "base64.h"
Signer::Signer():CSP_NAME(FEITIAN_CSP_NAME)
{
	log = new Log("Signer");
	certMsg = new CertMsg();
}


Signer::~Signer()
{
	if(log) delete log;
	if(certMsg) delete certMsg;
}
//-----------------------------------------------------------
// 函数名称:
//     sign
// 参数:
//    - string plain_text	明文
//    - BYTE* target_SN_blob	目标证书的序列号字节数组
//    - int cblob	目标证书的序列号字节数组大小
// 返回:
//     Result*
// 说明:
//     通过指定的序列号查找证书以及私钥,对数据做数字签名操作
//-----------------------------------------------------------
Result* Signer::sign(string plain_text,BYTE* target_SN_blob,int cblob)
{
	// 准备数据  
	HCRYPTPROV hProv;  
	if(!CryptAcquireContext(&hProv,
		NULL,
		CSP_NAME,
		PROV_RSA_FULL,
		CRYPT_VERIFYCONTEXT))
	{
		DWORD dwLastErr = GetLastError();


		if(NTE_BAD_KEYSET == dwLastErr) 
		{
			Result* result = new Result("Signer.cpp",20,"密钥库不存在,或者访问被拒绝!","{}");
			return result;
		}
		else{
			if(!CryptAcquireContext(&hProv,
				NULL,
				this->CSP_NAME,
				PROV_RSA_FULL,
				CRYPT_NEWKEYSET))
			{
				Map* map = new Map(1);
				map->put("errcode",dwLastErr);
				string errcode = map->toString();
				delete map;
				Result* result = new Result("Signer.cpp",34,"密钥库已存在,创建密钥库失败!",errcode);
				return result;
			}
		}
	}

	// 请求证书私钥服务  
	HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv = NULL;  
	DWORD dwKeyType = 0;  


	Result* result = certMsg->acquirePrivateKey(hProv,target_SN_blob,cblob,&hKeyProv,&dwKeyType);

	if(!result->isSuccess())
	{
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		log->error("Signer.cpp 86 acquirePrivateKey")->error(getErrorCode());
		return result;
	}

	if(hKeyProv==NULL)
	{
		string errorcode = getErrorCode();
		Result* result = new Result("Signer.cpp",57,"获取私钥服务失败!",errorcode.length()==0?"{}":errorcode);
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		log->error("Signer.cpp 86 acquirePrivateKey")->error(errorcode);
		return result;  
	}

	// 创建离散对象  
	HCRYPTHASH hHash = NULL;  
	if(!CryptCreateHash(  
		hKeyProv,                    // 容器句柄   
		CALG_MD5,                    // 算法标识  
		NULL,                        // 算法使用的Key  
		0,                            // 算法标识  
		&hHash))                    // 返回的HASH对象  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",73,"创建HASH失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 102 CryptCreateHash")->error(errorcode);
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		if(hKeyProv != NULL)  
			CryptReleaseContext(hKeyProv, 0);
		return result;   
	}  


	BYTE *orgTextByte ;  
	int orgTextLen = plain_text.size();  
	orgTextByte = new BYTE[orgTextLen + 1];  
	for(int i=0;i<orgTextLen;i++){  
		orgTextByte[i]=plain_text[i];  
	}  
	orgTextByte[orgTextLen]='\0';  
	// 计算数据摘要  
	if(!CryptHashData(hHash, orgTextByte, orgTextLen, 0))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Signer.cpp",94,"计算摘要失败!",errorcode.length()==0?"{}":errorcode);

		log->error("Signer.cpp 128 CryptHashData")->error(errorcode);
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		if(hKeyProv != NULL)  
			CryptReleaseContext(hKeyProv, 0);
		if(hHash) 
			CryptDestroyHash(hHash);   
		if(orgTextByte) delete[] orgTextByte;
		return result; 
	}  

	DWORD cbSign = 4096;  
	BYTE  *pbSign;  
	//获取签名数据摘要大小  
	if(!CryptSignHash(hHash, dwKeyType, NULL, 0, NULL, &cbSign))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Signer.cpp",106,"获取签名大小失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 147 CryptSignHash")->error(errorcode);
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		if(hKeyProv != NULL)  
			CryptReleaseContext(hKeyProv, 0);
		if(hHash) 
			CryptDestroyHash(hHash);   
		if(orgTextByte) delete[] orgTextByte;
		return result;
	}  
	pbSign = new BYTE[cbSign];  
	//签名数据摘要  
	if(!CryptSignHash(hHash, dwKeyType, NULL, 0, pbSign, &cbSign))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Signer.cpp",116,"签名失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 163 CryptSignHash")->error(errorcode);
		if(hProv != NULL)  
			CryptReleaseContext(hProv, 0);
		if(hKeyProv != NULL)  
			CryptReleaseContext(hKeyProv, 0);
		if(hHash) 
			CryptDestroyHash(hHash);   
		if(orgTextByte) delete[] orgTextByte;
		if(pbSign) delete[] pbSign;
		return result;  
	}  

	//将签名值转成base64编码  
	string baseSign = Base64::base64_encode(pbSign,cbSign);  
	log->info("----------------------")->info("签名值:")->info(baseSign);


	if(hProv != NULL)  
		CryptReleaseContext(hProv, 0);
	if(hKeyProv != NULL)  
		CryptReleaseContext(hKeyProv, 0);
	if(hHash) 
		CryptDestroyHash(hHash);   
	if(orgTextByte) delete[] orgTextByte;
	if(pbSign) delete[] pbSign;

	Result* sign_result = new Result(baseSign);

	return sign_result;  
}
//-----------------------------------------------------------
// 函数名称:
//     verify
// 参数:
//    - string signed_text_base64	签名值base64码
//    - string cert_base64	数字证书base64码
//    - string org_text	明文
// 返回:
//     Result*
// 说明:
//     使用传入的证书base64码创建证书上下文,然后使用该证书及其公钥验证数字签名
//-----------------------------------------------------------
Result* Signer::verify(string signed_text_base64,string cert_base64,string org_text)
{
	BYTE* signedData;  
	int length;
	signedData = Base64::base64_decode(signed_text_base64,length);   
	// 请求容器服务  
	HCRYPTPROV hProv = NULL;   
	if(!CryptAcquireContext(&hProv,
		NULL,
		CSP_NAME,
		PROV_RSA_FULL,
		CRYPT_VERIFYCONTEXT))
	{
		DWORD dwLastErr = GetLastError();
		if(signedData) delete[] signedData;
		if(NTE_BAD_KEYSET == dwLastErr) 
		{
			Result* result = new Result("Signer.cpp",164,"密钥库不存在,或者访问被拒绝!","{}");
			return result;
		}
		else{
			if(!CryptAcquireContext(&hProv,
				NULL,
				this->CSP_NAME,
				PROV_RSA_FULL,
				CRYPT_NEWKEYSET))
			{
				Map* map = new Map(1);
				map->put("errcode",dwLastErr);
				string errcode = map->toString();
				delete map;
				Result* result = new Result("Signer.cpp",178,"密钥库已存在,创建密钥库失败!",errcode);
				return result;
			}
		}
	}

	// 创建离散对象  
	HCRYPTHASH hHash = NULL;  
	if(!CryptCreateHash(  
		hProv,                        // 容器句柄   
		CALG_MD5,                    // 算法标识  
		NULL,                        // 算法使用的Key  
		0,                            // 算法标识  
		&hHash))                    // 返回的HASH对象  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",196,"创建HASH失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 248 CryptCreateHash")->error(errorcode);
		if(signedData) delete[] signedData;
		if(hProv) CryptReleaseContext(hProv,0);
		return result;   
	}  
	BYTE* orgBlob;         
	int orglen = org_text.size();  
	orgBlob = new BYTE[orglen + 1] ;  
	for(int i = 0; i < orglen; ++i)  
	{  
		orgBlob[i] = (byte)org_text[i];  
	}  
	orgBlob[orglen] = '\0';  
	// 计算数据摘要  
	if(CryptHashData(hHash, orgBlob, orglen, 0) == 0)  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",216,"计算摘要失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 271 CryptHashData")->error(errorcode);
		if(signedData) delete[] signedData;
		if(hProv) CryptReleaseContext(hProv,0);
		if(orgBlob) delete[] orgBlob;
		if(hHash) CryptDestroyHash(hHash);
		return result;
	}  

	// 获取签名者证书公钥  

	BYTE* cert;		
	int len;
	cert = Base64::base64_decode(cert_base64,len);  
	char* len_log_str = new char[20];
	itoa(len,len_log_str,10);
	log->info("-----------------------")->info("Signer.cpp 290 CertCreateCertificateContext")->info(cert_base64)->info(len_log_str);
	PCCERT_CONTEXT  pCertContext = NULL;  
	pCertContext = CertCreateCertificateContext(  
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,              
		cert,   
		len) ;
	if(pCertContext == NULL)  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",238,"创建证书上下文失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 290 CertCreateCertificateContext")->error(errorcode);
		if(signedData) delete[] signedData;
		if(hProv) CryptReleaseContext(hProv,0);
		if(orgBlob) delete[] orgBlob;
		if(hHash) CryptDestroyHash(hHash);
		if(cert) delete[] cert;
		return result;
	}  
	//获取公钥句柄
	HCRYPTKEY hPubKey;  
	if(!CryptImportPublicKeyInfo(hProv, pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPubKey))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",250,"导入公钥失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 308 CryptImportPublicKeyInfo")->error(errorcode);
		if(signedData) delete[] signedData;
		if(hProv) CryptReleaseContext(hProv,0);
		if(orgBlob) delete[] orgBlob;
		if(hHash) CryptDestroyHash(hHash);
		if(cert) delete[] cert;
		if(pCertContext) CryptReleaseContext(hProv,0);
		return result;
	}  
	//验证签名
	if(!CryptVerifySignature(hHash, signedData, length, hPubKey, NULL, 0))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Singer.cpp",257,"验证签名失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Signer.cpp 322 CryptVerifySignature")->error(errorcode);
		if(signedData) delete[] signedData;
		if(hProv) CryptReleaseContext(hProv,0);
		if(orgBlob) delete[] orgBlob;
		if(hHash) CryptDestroyHash(hHash);
		if(cert) delete[] cert;
		if(pCertContext) CertFreeCertificateContext(pCertContext);
		if(hPubKey) CryptDestroyKey(hPubKey);  
		return result;
	}  

	//释放内存
	if(signedData) delete[] signedData;
	if(hProv) CryptReleaseContext(hProv,0);
	if(orgBlob) delete[] orgBlob;
	if(hHash) CryptDestroyHash(hHash);
	if(cert) delete[] cert;
	if(pCertContext) CertFreeCertificateContext(pCertContext);
	if(hPubKey) CryptDestroyKey(hPubKey);  

	Result* result = new Result(org_text);
	return result;  
}

-------------------------改版分割线---------------------------------------------
以下代码只做示例,还存在许多问题需要修改
签名与验证(分验证证书合法性与不验证证书两种验证签名)
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
#include "Base.h"   //实现Base64转码
#include <comdef.h>

using namespace std;
#define TEST_CSP_NAME    "FEITIAN ePassNG RSA Cryptographic Service Provider" //飞天CSP

//返回值为'签名base64码'和';'和'证书base64码'
STDMETHODIMP CSignedData::Sign(BSTR orgData, BSTR* signature)
{
	// TODO: Add your implementation code here
	string orgText = _bstr_t (orgData);
	// 准备数据
	HCRYPTPROV hProv;
	//	--------------------------------------------------------------------
	// get the CSP handle
	printf("The following phase of this program is signature.\n\n");
	if(CryptAcquireContext(
		&hProv, 
		NULL, 
		TEST_CSP_NAME,
		PROV_RSA_FULL, 
		0)) 
	{
		printf("CSP context acquired.\n");
	}
	else	//create if not exist
	{
		if(CryptAcquireContext(
			&hProv, 
			NULL, 
			TEST_CSP_NAME, 
			PROV_RSA_FULL, 
			CRYPT_NEWKEYSET)) 
		{
			printf("A new key container has been created.\n");
		}
		else
		{
		}
	}

	// 打开证书库
	HCERTSTORE hCertStore = CertOpenStore(
		CERT_STORE_PROV_SYSTEM,   // The store provider type.
		0,                        // The encoding type is not needed.
		hProv,               // Use the epassNG HCRYPTPROV.
		CERT_SYSTEM_STORE_CURRENT_USER,
		L"MY"
		);
	if(hCertStore == NULL)
	{

	}

	// 查找证书
	PCCERT_CONTEXT hCert = CertFindCertificateInStore(
		hCertStore,
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		0,
		CERT_FIND_SUBJECT_STR,
		L"周绍禹",
		NULL);
	if(hCert == NULL)
	{

		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		return E_FAIL;
	}


	/**//*
		BOOL WINAPI CryptAcquireCertificatePrivateKey(
		__in          PCCERT_CONTEXT pCert,
		__in          DWORD dwFlags,
		__in          void* pvReserved,
		__out         HCRYPTPROV_OR_NCRYPT_KEY_HANDLE* phCryptProvOrNCryptKey,
		__out         DWORD* pdwKeySpec,
		__out         BOOL* pfCallerFreeProvOrNCryptKey
		);
		*/
	// 请求证书私钥服务
	HCRYPTPROV_OR_NCRYPT_KEY_HANDLE hKeyProv = NULL;
	DWORD dwKeyType = 0;
	BOOL bFreeKeyProv = FALSE;
	if(!CryptAcquireCertificatePrivateKey(hCert, 0, 0, &hKeyProv, &dwKeyType, &bFreeKeyProv))
	{

		CertFreeCertificateContext(hCert);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
	}

	// 创建离散对象
	HCRYPTHASH hHash = NULL;
	if(!CryptCreateHash(
		hKeyProv,                    // 容器句柄 
		CALG_MD5,                    // 算法标识
		NULL,                        // 算法使用的Key
		0,                            // 算法标识
		&hHash))                    // 返回的HASH对象
	{

		CertFreeCertificateContext(hCert);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
	}
	BYTE *orgTextByte ;
	int orgTextLen = orgText.size();
	orgTextByte = new BYTE[orgTextLen];
	for(int i=0;i<orgTextLen;i++){
		orgTextByte[i]=orgText[i];
	}
	orgTextByte[orgTextLen]='\0';
	// 计算数据摘要
	if(CryptHashData(hHash, orgTextByte, orgTextLen, 0) == 0)
	{

		CryptDestroyHash(hHash); 
		CryptReleaseContext(hKeyProv, 0);
		CertFreeCertificateContext(hCert);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
	}

	/**//*
		BOOL WINAPI CryptSignHash(
		__in          HCRYPTHASH hHash,
		__in          DWORD dwKeySpec,
		__in          LPCTSTR sDescription,
		__in          DWORD dwFlags,
		__out         BYTE* pbSignature,
		__in_out      DWORD* pdwSigLen
		);
		*/

	DWORD cbSign = 4096;
	BYTE  *pbSign;
	//获取签名数据摘要大小
	if(!CryptSignHash(hHash, dwKeyType, NULL, 0, NULL, &cbSign))
	{

		CryptDestroyHash(hHash); 
		CryptReleaseContext(hKeyProv, 0);
		CertFreeCertificateContext(hCert);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
	}
	pbSign = new BYTE[cbSign];
	//签名数据摘要
	if(!CryptSignHash(hHash, dwKeyType, NULL, 0, pbSign, &cbSign))
	{

		CryptDestroyHash(hHash); 
		CryptReleaseContext(hKeyProv, 0);
		CertFreeCertificateContext(hCert);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
	}
	cout<<base64_encode(pbSign,cbSign)<<endl;
	//将签名值转成base64编码
	string baseSign = base64_encode(pbSign,cbSign);
	//获取证书的base64编码
	BYTE *newCert;
	newCert = new BYTE[hCert->cbCertEncoded];
	newCert = hCert->pbCertEncoded;
	string baseCert = base64_encode(newCert,hCert->cbCertEncoded);
	//返回签名和证书的base64编码
	CComBSTR bstr((baseSign+";"+baseCert).c_str());
	*signature=bstr;
	//释放资源
	if(hHash != NULL)
	{
		CryptDestroyHash(hHash); 
		hHash = NULL;
	}

	if(hKeyProv != NULL && bFreeKeyProv)
	{
		CryptReleaseContext(hKeyProv, 0);
		hKeyProv = NULL;
	}

	if(hCert != NULL)
	{
		CertFreeCertificateContext(hCert);
		hCert = NULL;
	}

	if(hCertStore != NULL)
	{
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		hCertStore = NULL;
	}

	return S_OK;
}

//验证签名(无证书验证)
STDMETHODIMP CSignedData::VerifySign(BSTR Signed_base64, BSTR Cert_base64, BSTR orgData, BOOL* verifySuc)
{
	// TODO: Add your implementation code here
	// 准备数据
	BYTE* signedData;
	string cstrSigned = _bstr_t (Signed_base64);
	string decodeData = base64_decode(cstrSigned);
	int len = decodeData.size();
	signedData = new BYTE[len] ;
	for(int i = 0; i < len; ++i)
	{
		signedData[i] = (byte)decodeData[i];
	}
	signedData[len] = '\0';
	// 请求容器服务
	HCRYPTPROV hProv = NULL; 
	if(!CryptAcquireContext(
		&hProv,                // 返回的句柄
		NULL,                // CSP key 容器名称
		TEST_CSP_NAME,                // CSP 提供者名称
		PROV_RSA_FULL,        // CSP 提供者类型
		0))                    // 附加参数
	{

		return E_FAIL;
	}

	// 创建离散对象
	HCRYPTHASH hHash = NULL;
	if(!CryptCreateHash(
		hProv,                        // 容器句柄 
		CALG_MD5,                    // 算法标识
		NULL,                        // 算法使用的Key
		0,                            // 算法标识
		&hHash))                    // 返回的HASH对象
	{


		CryptReleaseContext(hProv, 0);
		return E_FAIL;
	}
	string cstrOrgData = _bstr_t (orgData);
	BYTE* orgBlob;
	int orglen = cstrOrgData.size();
	orgBlob = new BYTE[orglen] ;
	for(int i = 0; i < orglen; ++i)
	{
		orgBlob[i] = (byte)cstrOrgData[i];
	}
	orgBlob[orglen] = '\0';
	// 计算数据摘要
	if(CryptHashData(hHash, orgBlob, orglen, 0) == 0)
	{


		CryptDestroyHash(hHash); 
		CryptReleaseContext(hProv, 0);
		return E_FAIL;
	}

	// 获取签名者证书公钥
	/*
	HCERTSTORE WINAPI CertOpenStore(
	__in          LPCSTR lpszStoreProvider,
	__in          DWORD dwMsgAndCertEncodingType,
	__in          HCRYPTPROV_LEGACY hCryptProv,
	__in          DWORD dwFlags,
	__in          const void* pvPara
	);
	*/
	BYTE* cert;
	string cstrCert_base64 = _bstr_t (Cert_base64);
	string decodeCert = base64_decode(cstrCert_base64);
	int certLen = decodeCert.size();
	cert = new BYTE[certLen] ;
	for(int i = 0; i < certLen; ++i)
	{
		cert[i] = (byte)decodeCert[i];
	}
	cert[certLen] = '\0';
	PCCERT_CONTEXT  pCertContext = NULL;
	if(pCertContext = CertCreateCertificateContext(
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,              // The encoding type
		cert,   // The encoded data from
		// the certificate retrieved
		certLen))  // The length of the encoded data
	{
		printf("A new certificate has been created.\n");

		// Use the certificate context as needed.
		// ...
	}
	else
	{
		printf("A new certificate could not be created.\n");
		return E_FAIL;
	}
	HCRYPTKEY hPubKey;
	if(!CryptImportPublicKeyInfo(hProv, pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
	{
		CryptDestroyKey(hPubKey);
		CryptReleaseContext(hProv, 0);
		return E_FAIL;
	}
	// 校验签名
	/*
	BOOL WINAPI CryptVerifySignature(
	__in          HCRYPTHASH hHash,
	__in          BYTE* pbSignature,
	__in          DWORD dwSigLen,
	__in          HCRYPTKEY hPubKey,
	__in          LPCTSTR sDescription,
	__in          DWORD dwFlags
	);
	*/
	if(!CryptVerifySignature(hHash, signedData, len, hPubKey, NULL, 0))
	{
		*verifySuc=false;
		return S_FALSE;
	}
	else
	{
		*verifySuc=true;
	}

	// 释放获取的对象
	if(hPubKey != NULL)
	{
		CryptDestroyKey(hPubKey);
		hPubKey = NULL;
	}

	if(hHash != NULL)
	{
		CryptDestroyHash(hHash); 
		hHash = NULL;
	}

	if(pCertContext != NULL)
	{
		CertFreeCertificateContext(pCertContext);
		pCertContext = NULL;
	}


	if(hProv != NULL)
	{
		CryptReleaseContext(hProv, 0);
		hProv = NULL;
	}
	return S_OK;
}

//带证书验证部分的签名验证
STDMETHODIMP CSignedData::VerifySignWithCRL(BSTR Signed_base64, BSTR Cert_base64, BSTR orgData, BSTR CRL_base64, BOOL* verifySuc)
{
	// TODO: 在此添加实现代码
	// TODO: Add your implementation code here
	// 准备数据
	BYTE* signedData;
	string cstrSigned = _bstr_t (Signed_base64);
	string cstrCRL_base64 = _bstr_t(CRL_base64);
	int count  = cstrCRL_base64.size();
	string decodeData = base64_decode(cstrSigned);
	int len = decodeData.size();
	signedData = new BYTE[len] ;
	for(int i = 0; i < len; ++i)
	{
		signedData[i] = (byte)decodeData[i];
	}
	signedData[len] = '\0';
	// 请求容器服务
	HCRYPTPROV hProv = NULL; 
	if(!CryptAcquireContext(
		&hProv,                // 返回的句柄
		NULL,                // CSP key 容器名称
		TEST_CSP_NAME,                // CSP 提供者名称
		PROV_RSA_FULL,        // CSP 提供者类型
		0))                    // 附加参数
	{

		return E_FAIL;
	}

	// 创建离散对象
	HCRYPTHASH hHash = NULL;
	if(!CryptCreateHash(
		hProv,                        // 容器句柄 
		CALG_MD5,                    // 算法标识
		NULL,                        // 算法使用的Key
		0,                            // 算法标识
		&hHash))                    // 返回的HASH对象
	{


		CryptReleaseContext(hProv, 0);
		return E_FAIL;
	}
	string cstrOrgData = _bstr_t (orgData);
	BYTE* orgBlob;
	int orglen = cstrOrgData.size();
	orgBlob = new BYTE[orglen] ;
	for(int i = 0; i < orglen; ++i)
	{
		orgBlob[i] = (byte)cstrOrgData[i];
	}
	orgBlob[orglen] = '\0';
	// 计算数据摘要
	if(CryptHashData(hHash, orgBlob, orglen, 0) == 0)
	{


		CryptDestroyHash(hHash); 
		CryptReleaseContext(hProv, 0);
		return E_FAIL;
	}

	// 获取签名者证书公钥
	/*
	HCERTSTORE WINAPI CertOpenStore(
	__in          LPCSTR lpszStoreProvider,
	__in          DWORD dwMsgAndCertEncodingType,
	__in          HCRYPTPROV_LEGACY hCryptProv,
	__in          DWORD dwFlags,
	__in          const void* pvPara
	);
	*/
	BYTE* cert;
	string cstrCert_base64 = _bstr_t (Cert_base64);
	string decodeCert = base64_decode(cstrCert_base64);
	int certLen = decodeCert.size();
	cert = new BYTE[certLen] ;
	for(int i = 0; i < certLen; ++i)
	{
		cert[i] = (byte)decodeCert[i];
	}
	cert[certLen] = '\0';
	PCCERT_CONTEXT  pCertContext = NULL;
	if(pCertContext = CertCreateCertificateContext(
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,              // The encoding type
		cert,   // The encoded data from
		// the certificate retrieved
		certLen))  // The length of the encoded data
	{
		printf("A new certificate has been created.\n");

		// Use the certificate context as needed.
		// ...
	}
	else
	{
		printf("A new certificate could not be created.\n");
		return E_FAIL;
	}
	bool certIsValid = verifyCert(pCertContext,cstrCRL_base64);
	if(certIsValid){

		HCRYPTKEY hPubKey;
		if(!CryptImportPublicKeyInfo(hProv, pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
		{
			CryptDestroyKey(hPubKey);
			CryptReleaseContext(hProv, 0);
			return E_FAIL;
		}
		// 校验签名
		/*
		BOOL WINAPI CryptVerifySignature(
		__in          HCRYPTHASH hHash,
		__in          BYTE* pbSignature,
		__in          DWORD dwSigLen,
		__in          HCRYPTKEY hPubKey,
		__in          LPCTSTR sDescription,
		__in          DWORD dwFlags
		);
		*/
		if(!CryptVerifySignature(hHash, signedData, len, hPubKey, NULL, 0))
		{
			*verifySuc=false;
			return S_FALSE;
		}
		else
		{
			*verifySuc=true;
		}	
		if(hPubKey != NULL)
		{
			CryptDestroyKey(hPubKey);
			hPubKey = NULL;
		}

	}else{
		*verifySuc=false;
	}

	// 释放获取的对象

	if(hHash != NULL)
	{
		CryptDestroyHash(hHash); 
		hHash = NULL;
	}

	if(pCertContext != NULL)
	{
		CertFreeCertificateContext(pCertContext);
		pCertContext = NULL;
	}


	if(hProv != NULL)
	{
		CryptReleaseContext(hProv, 0);
		hProv = NULL;
	}
	return S_OK;
}

// 校验证书合法性
bool verifyCert(PCCERT_CONTEXT hCert,string CRL_base64)
{
    /*
    *获取CRLContext对象
    */
    string CRL = base64_decode(CRL_base64);
    BYTE *pbCRL = NULL;
    pbCRL = new BYTE[CRL.size()];
    for(int i=0;i<CRL.size();i++){
        pbCRL[i]=(BYTE)CRL[i];
    }
    int cbCRL = CRL.size();
    pbCRL[cbCRL]='\0';
    PCCRL_CONTEXT hCRL = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,pbCRL,cbCRL);
    if(hCRL==NULL){
        printf("未找到CRL");
    }else{
        printf("找到CRL");
    }
    /**//*
        LONG WINAPI CertVerifyTimeValidity(
        __in          LPFILETIME pTimeToVerify,
        __in          PCERT_INFO pCertInfo
        );
        */
    // 校验证书日期
    int nRetCode = CertVerifyTimeValidity(NULL, hCert->pCertInfo);
    if(nRetCode < 0)
    {
        printf("Verify cert's date failed: BEFORE date after TODAY!\n");
        return false;
    }

    if(nRetCode > 0)
    {
        printf("Verify cert's date failed: Cert has expired!\n");
        return false;
    }

    if(nRetCode == 0)
    {
        printf("Verify cert's date succeed!\n");

    }

    // 校验签名者证书

    HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT");
    if(hCertStore != NULL)
    {
        /**//*
            PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(
            __in          HCERTSTORE hCertStore,
            __in          PCCERT_CONTEXT pSubjectContext,
            __in_opt      PCCERT_CONTEXT pPrevIssuerContext,
            __in_out      DWORD* pdwFlags
            );
            */
        // 2.
        DWORD dwFlags = CERT_STORE_SIGNATURE_FLAG;
        PCCERT_CONTEXT hIssuserCert = CertGetIssuerCertificateFromStore(hCertStore, hCert, NULL, &dwFlags);
        if(hIssuserCert != NULL)
        {
            BOOL bCheckOK = FALSE;
            while(hIssuserCert != NULL)
            {
                /**//*
                    BOOL WINAPI CertVerifySubjectCertificateContext(
                    __in          PCCERT_CONTEXT pSubject,
                    __in_opt      PCCERT_CONTEXT pIssuer,
                    __in_out      DWORD* pdwFlags
                    );
                    */
                // 校验证书签发者信息合法性
                dwFlags = CERT_STORE_SIGNATURE_FLAG;
                if(CertVerifySubjectCertificateContext(hCert, hIssuserCert, &dwFlags))
                {
                    if(dwFlags == 0)
                    {
                        printf("Verify cert by issuser's cert succeed! \n");
                        bCheckOK = TRUE;
                        break;
                    }
                }
                else
                {
                    printf("Verify cert by issuser's cert failed! \n");
                    return false;
                    break;
                }

                // Next ..
                hIssuserCert = CertGetIssuerCertificateFromStore(hCertStore, hCert, hIssuserCert, &dwFlags);
            }

            if(!bCheckOK)
            {
                printf("Verify cert by issuser's cert failed! \n");
                return false;
            }

        }
        else
        {
            printf("Can not find cert issuser's cert!\n");
        }

        if(hIssuserCert != NULL)
        {
            CertFreeCertificateContext(hIssuserCert);
            hIssuserCert = NULL;
        }
    }
    else
    {
        printf("Open ROOT CertStore failed!\n");
        return false;
    }

    if(hCertStore != NULL)
    {
        CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
        hCertStore = NULL;
    }


    // 校验 CRL 列表

    // 1.
    //BYTE* pbCrlData = NULL;
    //DWORD cbCrlData = 0;
    //readFile("c:\\cfcaT.crl", NULL, cbCrlData);
    //if(cbCrlData > 0)
    //{
    //    pbCrlData = (BYTE*) new char[cbCrlData];
    //    readFile("c:\\cfcaT.crl", pbCrlData, cbCrlData);
    //}

    ///**//*
    //    PCCRL_CONTEXT WINAPI CertCreateCRLContext(
    //    __in          DWORD dwCertEncodingType,
    //    __in          const BYTE* pbCrlEncoded,
    //    __in          DWORD cbCrlEncoded
    //    );
    //    */

    //// 2.转换CRL数据为CRL句柄
    //PCCRL_CONTEXT hCRL = CertCreateCRLContext(MY_ENCODING_TYPE, pbCrlData, cbCrlData);
    //delete [] pbCrlData;
    if(hCRL != NULL)
    {
        /**//*
            BOOL WINAPI CertIsValidCRLForCertificate(
            __in          PCCERT_CONTEXT pCert,
            __in          PCCRL_CONTEXT pCRL,
            __in          DWORD dwFlags,
            __in          void* pvReserved
            */
        if(CertIsValidCRLForCertificate(hCert, hCRL, 0, NULL))
        {
            printf("CRL is valid for the cert!\n");
        }
        else
        {
            printf("CRL is invalid for the cert!!\n");
            return false;
        }

        /**//*
            BOOL WINAPI CertFindCertificateInCRL(
            __in          PCCERT_CONTEXT pCert,
            __in          PCCRL_CONTEXT pCrlContext,
            __in          DWORD dwFlags,
            __in_opt      void* pvReserved,
            __out         PCRL_ENTRY* pCrlEntry
            );
            */
        // Step 4: 检查CRL是否包含该证书
        PCRL_ENTRY pCrlEntry = NULL;
        if(CertFindCertificateInCRL(hCert, hCRL, 0, 0, &pCrlEntry))
        {
            if(pCrlEntry != NULL)
            {
                printf("Cert has been revoked!\n");
                return false;
            }
            else
            {
                printf("Cert not be revoked!\n");
            }
        }
        else
        {
            printf("Find cert in CRL failed!\n");
            return false;
        }
    }
    else
    {
        printf("Create CRL context failed!\n");
        return false;
    }

    if(hCRL != NULL)
    {
        CertFreeCRLContext(hCRL);
    }
} 

抱歉!评论已关闭.