编写ATL工程实现ActiveX控件调用cryptoAPI接口(二)------------信封加密与解密

注:下面的代码中用了Map,Base64,log,Result等都为自定义类型,太长就不一一贴出.
/*
 * 
 * 
 * 文件名称:Envelop.cpp
 * 摘    要:
 *		数字信封加密与解密
 * 当前版本:1.0
 * 作    者:周绍禹
 * 创建日期:2012年3月4日
 */
#include "StdAfx.h"
#include "Envelop.h"
#include "base64.h"
#include "Map.h"
#include <sstream>
#include "generic.h"

Envelop::Envelop():CSP_NAME(FEITIAN_CSP_NAME)
{
	log = new Log("Envelop");
	certMsg = new CertMsg();
}


Envelop::~Envelop()
{
	delete log;
	delete certMsg;
}
//-----------------------------------------------------------
// 函数名称:
//     envelop
// 参数:
//    - string recCert_base64	用作非对称加密的公钥所对应的证书base64码
//    - string cipher_key_base64	信封加密的目标base64(在项目中也就是对称密钥)
// 返回:
//     Result*
// 说明:
//     会将目标base64码解码,后对得到的二进制数组进行信封加密
//	   成功返回的为包含加密完成的信封base64码,或者返回异常信息
//-----------------------------------------------------------
Result* Envelop::envelop(string recCert_base64, string cipher_key_base64)
{
	// 公钥加密  

	//获取证书  
	BYTE* rec_cert;  
	int length;
	rec_cert = Base64::base64_decode(recCert_base64,length);  
	int cipher_size;
	BYTE* msgContent = Base64::base64_decode(cipher_key_base64,cipher_size);


	PCCERT_CONTEXT  pRecverCert = NULL;             
	if(!(pRecverCert = CertCreateCertificateContext(  
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,             
		rec_cert,   
		length)))
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",42,"创建证书上下文失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 45 CertCreateCertificateContext")->error(errorcode); 
		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		return result;
	}  

	// 设置加密证书  
	PCERT_INFO RecipCertArray[1];  
	RecipCertArray[0] = pRecverCert->pCertInfo;  

	// 设置加密算法  
	CRYPT_ALGORITHM_IDENTIFIER ContentEncryptAlgorithm;  
	memset(&ContentEncryptAlgorithm, 0, sizeof(ContentEncryptAlgorithm));  
	ContentEncryptAlgorithm.pszObjId = szOID_RSA_RC2CBC;  

	// 设置信封参数  
	CMSG_ENVELOPED_ENCODE_INFO EnvelopedEncodeInfo;  
	memset(&EnvelopedEncodeInfo, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO));  
	EnvelopedEncodeInfo.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);  
	EnvelopedEncodeInfo.hCryptProv = NULL;  
	EnvelopedEncodeInfo.ContentEncryptionAlgorithm = ContentEncryptAlgorithm;  
	EnvelopedEncodeInfo.pvEncryptionAuxInfo = NULL;  
	EnvelopedEncodeInfo.cRecipients = 1;  
	EnvelopedEncodeInfo.rgpRecipients = RecipCertArray;  

	// 获取消息编码的长度  
	CRYPT_DATA_BLOB encBlob;               
	memset(&encBlob, 0, sizeof(encBlob));  
	encBlob.cbData = CryptMsgCalculateEncodedLength(  
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,  
		0,  
		CMSG_ENVELOPED,  
		&EnvelopedEncodeInfo,  
		NULL,  
		cipher_size);  
	if(encBlob.cbData == 0)  
	{  
		CertFreeCertificateContext(pRecverCert);  
		log->error("Envelop.cpp 85 CryptMsgCalculateEncodedLength")->error(getErrorCode()); 
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",79,"获取信封块大小失败!",errorcode.length()==0?"{}":errorcode);

		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		if(pRecverCert) CertFreeCertificateContext(pRecverCert); 
		return result;
	}  


	// 分配编码空间  
	encBlob.pbData = (BYTE *) new char[encBlob.cbData];  
	if(encBlob.pbData == NULL)  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",107,"分配编码空间失败!",errorcode.length()==0?"{}":errorcode);
		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		if(pRecverCert) CertFreeCertificateContext(pRecverCert);
		return result;
	}  
	HCRYPTMSG hMsg;  
	// 编码加密  
	hMsg = CryptMsgOpenToEncode(  
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,        
		0,                       
		CMSG_ENVELOPED,        
		&EnvelopedEncodeInfo,  
		NULL,                   
		NULL);  
	if(hMsg == NULL)   
	{  
		string errorcode = getErrorCode();
		log->error("Envelop.cpp 119 CryptMsgOpenToEncode")->error(errorcode); 
		Result* result = new Result("Envelop.cpp",117,"获取信封块大小失败!",errorcode.length()==0?"{}":errorcode);
		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		if(pRecverCert) CertFreeCertificateContext(pRecverCert);
		return result;
	}  

	// 添加数据  
	if(!CryptMsgUpdate(  
		hMsg,               
		msgContent,       
		cipher_size,        
		TRUE))             
	{  

		string errorcode = getErrorCode();
		log->error("Envelop.cpp 138 CryptMsgUpdate")->error(errorcode); 
		Result* result = new Result("Envelop.cpp",141,"添加数据失败!",errorcode.length()==0?"{}":errorcode);
		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		if(pRecverCert) CertFreeCertificateContext(pRecverCert);
		if(hMsg) CryptMsgClose(hMsg);
		return result;
	}  

	// 获取加密结果  
	if(!CryptMsgGetParam(  
		hMsg,                        
		CMSG_CONTENT_PARAM,           
		0,                           
		encBlob.pbData,              
		&encBlob.cbData))          
	{   
		string errorcode = getErrorCode();
		log->error("Envelop.cpp 156 CryptMsgGetParam")->error(errorcode); 
		Result* result = new Result("Envelop.cpp",157,"获得加密失败!",errorcode.length()==0?"{}":errorcode);
		if(rec_cert) delete[] rec_cert;
		if(msgContent) delete[] msgContent;
		if(pRecverCert) CertFreeCertificateContext(pRecverCert);
		if(hMsg) CryptMsgClose(hMsg);
		return result;
	}  

	string baseEnc = Base64::base64_encode(encBlob.pbData,encBlob.cbData);  


	// 清理  
	if(rec_cert) delete[] rec_cert;
	if(msgContent) delete[] msgContent;

	if(encBlob.pbData) delete [] encBlob.pbData;  

	if(hMsg != NULL)  
		CryptMsgClose(hMsg);  

	if(pRecverCert != NULL)  
		CertFreeCertificateContext(pRecverCert);  

	Result* result = new Result(baseEnc);
	return result;  
}
//-----------------------------------------------------------
// 函数名称:
//     develop
// 参数:
//    - string env_base64	加密的信封base64码
//    - BYTE* target_SN_blob	用来解密的数字证书序列号字节数组
//    - int cblob	用来解密的数字证书序列号字节数组大小
// 返回:
//     Result*
// 说明:
//     通过序列号查找到用来解密的证书,并获取私钥用作解密信封
//	   成功返回的为包含目标的base64码(即对称密钥的Base64码),或者异常信息
//-----------------------------------------------------------
Result* Envelop::develop(string enc_base64,BYTE* target_SN_blob,int cblob)
{
	int encLen; 
	BYTE* encBYTE; 
	encBYTE = Base64::base64_decode(enc_base64,encLen);  

	HCRYPTPROV hProv;  


	if(!CryptAcquireContext(&hProv,
		NULL,
		CSP_NAME,
		PROV_RSA_FULL,
		CRYPT_VERIFYCONTEXT))
	{
		DWORD dwLastErr = GetLastError();
		if(encBYTE) delete[] encBYTE;
		if(NTE_BAD_KEYSET == dwLastErr) 
		{
			Result* result = new Result("Envelop.cpp",202,"密钥库不存在,或者访问被拒绝!","{}");
			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("Envelop.cpp",216,"密钥库已存在,创建密钥库失败!",errcode);
				return result;
			}
		}
	}

	HCRYPTMSG hMsg = NULL;   
	hMsg = CryptMsgOpenToDecode(   
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,    
		0,                    
		0,                   
		NULL,               
		NULL,               
		NULL);               
	if(hMsg == NULL)   
	{   
		string errorcode = getErrorCode();
		log->error("Envelop.cpp 239 CryptMsgOpenToDecode")->error(errorcode); 
		Result* result = new Result("Envelop.cpp",239,"获取解码句柄失败!",errorcode.length()==0?"{}":errorcode);
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		return result;
	}   


	if(!CryptMsgUpdate(   
		hMsg,               
		encBYTE,        
		encLen + 1,        
		TRUE))  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",247,"解码失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 257 CryptMsgUpdate")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;
	}  


	// 消息类型  
	DWORD dwType = 0;   
	DWORD dwSize = sizeof(dwType);  
	if(!CryptMsgGetParam(   
		hMsg,                  
		CMSG_TYPE_PARAM,    
		0,                    
		&dwType,             
		&dwSize))              
	{   
		CryptMsgClose(hMsg);  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",263,"解码失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 276 CryptMsgGetParam")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;   
	}  

	// 校验消息类型  
	if (dwType != CMSG_ENVELOPED)   
	{   
		Result* result = new Result("Envelop.cpp",274,"消息类型错误!","{}");
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;
	}   

	// 消息格式  
	char szTypeName[1024];  
	dwSize = 1024;  
	if(!CryptMsgGetParam(   
		hMsg,                            
		CMSG_INNER_CONTENT_TYPE_PARAM,    
		0,                                
		szTypeName,                       
		&dwSize))                       
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",287,"获取消息格式失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 306 CryptMsgGetParam")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;  
	}  

	// 检查消息格式  
	if(strcmp(szTypeName, szOID_PKCS_7_DATA) != 0)   
	{  
		Result* result = new Result("Envelop.cpp",287,"消息格式错误!","{}");
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;   
	}   

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


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

	if(!result_privateKey->isSuccess())
	{
		log->error("Envelop.cpp 338 acquirePrivateKey"); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
		return result_privateKey;
	}

	if(hKeyProv==NULL)
	{
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",316,"获取私钥服务失败!",errorcode.length()==0?"{}":errorcode);
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		return result;  
	}

	CMSG_CTRL_DECRYPT_PARA para;   
	para.cbSize = sizeof (CMSG_CTRL_DECRYPT_PARA);   
	para.dwKeySpec = dwKeyType;   
	para.hCryptProv = hKeyProv;   
	para.dwRecipientIndex = 0; 
	if(!CryptMsgControl(   
		hMsg,               
		0,                   
		CMSG_CTRL_DECRYPT,    
		¶))                
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",335,"解密控制失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 364 CryptMsgControl")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
		return result;   
	}  

	// 获取解密消息大小  
	CRYPT_DATA_BLOB sigBlob;  
	memset(&sigBlob, 0, sizeof(sigBlob));  
	if(!CryptMsgGetParam(   
		hMsg,                
		CMSG_CONTENT_PARAM, 
		0,                    
		NULL,                
		&sigBlob.cbData))    
	{                      
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",351,"获取解密消息大小失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 382 CryptMsgGetParam")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
		return result;   
	}   

	// 分配内存  
	sigBlob.pbData =  new BYTE[sigBlob.cbData];  
	if(sigBlob.pbData == NULL)  
	{  
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",366,"分配内存空间失败!",errorcode.length()==0?"{}":errorcode);
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
		return result;   
	}  

	// 获取解码消息  
	if(!CryptMsgGetParam(   
		hMsg,                
		CMSG_CONTENT_PARAM, 
		0,                    
		sigBlob.pbData,        
		&sigBlob.cbData))   
	{                      
		string errorcode = getErrorCode();
		Result* result = new Result("Envelop.cpp",377,"获取解码消息失败!",errorcode.length()==0?"{}":errorcode);
		log->error("Envelop.cpp 411 CryptMsgGetParam")->error(errorcode); 
		if(encBYTE) delete[] encBYTE;
		if(hProv) CryptReleaseContext(hProv, 0);
		if(hMsg) CryptMsgClose(hMsg);
		if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
		return result;   
	}  
	sigBlob.pbData[sigBlob.cbData]='\0';  
	// 清理解密过程数据  
	if(encBYTE) delete[] encBYTE;
	if(hProv) CryptReleaseContext(hProv, 0);
	if(hMsg) CryptMsgClose(hMsg);
	if(hKeyProv) CryptReleaseContext(hKeyProv, 0);
	string text = Base64::base64_encode(sigBlob.pbData,sigBlob.cbData);

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



------------------------------下面为刚接触的版本,上面为修改后的版本--------------------------


代码有待修改

信封加密与解密


#include "Base.h"  //Base64转码
#include <comdef.h>
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
using namespace std;
#define TEST_CSP_NAME    "FEITIAN ePassNG RSA Cryptographic Service Provider" //飞天CSP
//加密信封
STDMETHODIMP CEnvelop::Envelop(BSTR recCert_base64_bstr, BSTR plainText_bstr, BSTR* envelopedData)
{
	string recCert_base64 = _bstr_t(recCert_base64_bstr);
	string plainText = _bstr_t(plainText_bstr);
	// TODO: Add your implementation code here
	// 公钥加密

	//获取证书
	BYTE* rec_cert;
	string rec_cstrCert_base64 = recCert_base64;
	string rec_decodeCert = base64_decode(rec_cstrCert_base64);
	int rec_certLen = rec_decodeCert.size();
	rec_cert = new BYTE[rec_certLen] ;
	for(int i = 0; i < rec_certLen; ++i)
	{
		rec_cert[i] = (byte)rec_decodeCert[i];
	}
	rec_cert[rec_certLen] = '\0';
	PCCERT_CONTEXT  pRecverCert = NULL;
	if(pRecverCert = CertCreateCertificateContext(
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,              // The encoding type
		rec_cert,   // The encoded data from
		// the certificate retrieved
		rec_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");
	}

	// 设置加密证书
	PCERT_INFO RecipCertArray[1];
	RecipCertArray[0] = pRecverCert->pCertInfo;

	// 设置加密算法
	CRYPT_ALGORITHM_IDENTIFIER ContentEncryptAlgorithm;
	memset(&ContentEncryptAlgorithm, 0, sizeof(ContentEncryptAlgorithm));
	ContentEncryptAlgorithm.pszObjId = szOID_RSA_RC2CBC;

	// 设置信封参数
	CMSG_ENVELOPED_ENCODE_INFO EnvelopedEncodeInfo;
	memset(&EnvelopedEncodeInfo, 0, sizeof(CMSG_ENVELOPED_ENCODE_INFO));
	EnvelopedEncodeInfo.cbSize = sizeof(CMSG_ENVELOPED_ENCODE_INFO);
	EnvelopedEncodeInfo.hCryptProv = NULL;
	EnvelopedEncodeInfo.ContentEncryptionAlgorithm = ContentEncryptAlgorithm;
	EnvelopedEncodeInfo.pvEncryptionAuxInfo = NULL;
	EnvelopedEncodeInfo.cRecipients = 1;
	EnvelopedEncodeInfo.rgpRecipients = RecipCertArray;

	// 获取消息编码的长度
	CRYPT_DATA_BLOB encBlob;
	memset(&encBlob, 0, sizeof(encBlob));
	encBlob.cbData = CryptMsgCalculateEncodedLength(
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
		0,
		CMSG_ENVELOPED,
		&EnvelopedEncodeInfo,
		NULL,
		plainText.size());
	if(encBlob.cbData == 0)
	{
		CertFreeCertificateContext(pRecverCert);
		printf("Getting enveloped cbEncodedBlob length failed.");
	}

	printf("Enveloped message size is %d bytes.", encBlob.cbData);

	// 分配编码空间
	encBlob.pbData = (BYTE *) new char[encBlob.cbData];
	if(encBlob.pbData == NULL)
	{
		CertFreeCertificateContext(pRecverCert);
		printf("Memory allocation failed. \n");
	}
	HCRYPTMSG hMsg;
	// 编码加密
	hMsg = CryptMsgOpenToEncode(
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,        // encoding type
		0,                       // flags
		CMSG_ENVELOPED,          // message type
		&EnvelopedEncodeInfo,    // pointer to structure
		NULL,                     // szOID_RSA_signedData,    // inner content OID
		NULL);
	if(hMsg == NULL) 
	{
		delete [] encBlob.pbData;
		CertFreeCertificateContext(pRecverCert);
		printf("The message open to be encode failed. \n");
	}
	BYTE* msgContent;
	int size = plainText.size();
	msgContent = new BYTE[size];
	for(int i=0;i<size;i++){
		msgContent[i]=(BYTE)plainText[i];
	}
	msgContent[size]='\0';
	// 添加数据
	if(!CryptMsgUpdate(
		hMsg,                // handle to the message
		msgContent,        // pointer to the content
		size,        // size of the content
		TRUE))                // last call
	{
		delete [] encBlob.pbData;
		CryptMsgClose(hMsg);
		CertFreeCertificateContext(pRecverCert);
		printf("Enveloped CryptMsgUpdate failed.\n");
	}

	// 获取加密结果
	if(!CryptMsgGetParam(
		hMsg,                        // handle to the message
		CMSG_CONTENT_PARAM,            // parameter type
		0,                            // index
		encBlob.pbData,                // pointer to the BLOB
		&encBlob.cbData))            // size of the BLOB
	{
		delete [] encBlob.pbData;
		CryptMsgClose(hMsg);
		CertFreeCertificateContext(pRecverCert);
		printf("CryptMsgGetParam enveloped message failed.\n");
	}

	string baseEnc = base64_encode(encBlob.pbData,encBlob.cbData);
	// 清理
	delete [] encBlob.pbData;

	if(hMsg != NULL)
	{
		CryptMsgClose(hMsg);
		hMsg = NULL;
	}

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

	CComBSTR bstr(baseEnc.c_str());
	*envelopedData = bstr;
	return S_OK;
}

//解密信封
STDMETHODIMP CEnvelop::Develop(BSTR enc_base64_bstr, BSTR* plainText)
{
	string enc_base64 = _bstr_t(enc_base64_bstr);
	// TODO: Add your implementation code here
	string enc = base64_decode(enc_base64);
	int encLen = enc.size();
	BYTE* encBYTE;
	encBYTE = new BYTE[encLen];

	for(int i=0;i<encLen;i++){
		encBYTE[i]=enc[i];
	}
	encBYTE[encLen]='\0';
	
	// 准备数据
	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
		{
		}
	}
	// Open
	HCRYPTMSG hMsg = NULL; 
	hMsg = CryptMsgOpenToDecode( 
		X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,    // Encoding type. 
		0,                    // Flags. 
		0,                    // Use the default message type which is listed in the message header. 
		NULL,                // Cryptographic provider. Use NULL for the default provider. 
		NULL,                // Recipient information. 
		NULL);                // Stream information. 
	if(hMsg == NULL) 
	{ 
		printf("Failed in CryptMsgOpenToDecode."); 
	} 

	// Update
	if(!CryptMsgUpdate( 
		hMsg,                // Handle to the message 
		encBYTE,        // Pointer to the encoded BLOB 
		encLen,        // Size of the encoded BLOB 
		TRUE))
	{
		CryptMsgClose(hMsg);
		printf("Failed in CryptMsgUpdate."); 
	}


	// 开始操作解码后的加密数据 ================================

	// 消息类型
	DWORD dwType = 0; 
	DWORD dwSize = sizeof(dwType);
	if(!CryptMsgGetParam( 
		hMsg,                // Handle to the message 
		CMSG_TYPE_PARAM,    // Parameter type 
		0,                    // Index 
		&dwType,            // Buffer
		&dwSize))            // Size of the returned 
	{ 
		CryptMsgClose(hMsg);
		printf("Failed in CryptMsgGetParam for CMSG_TYPE_PARAM."); 
	}

	// 校验消息类型
	if (dwType != CMSG_ENVELOPED) 
	{ 
		CryptMsgClose(hMsg);
		printf("Not an enveloped data."); 
	} 

	// 消息格式
	char szTypeName[1024];
	dwSize = 1024;
	if(!CryptMsgGetParam( 
		hMsg,                            // Handle to the message 
		CMSG_INNER_CONTENT_TYPE_PARAM,    // Parameter type 
		0,                                // Index 
		szTypeName,                        // Buffer 
		&dwSize))                        // Size of the returned 
	{
		CryptMsgClose(hMsg);
		printf("Failed in CryptMsgGetParam for CMSG_INNER_CONTENT_TYPE_PARAM."); 
	}

	// 检查消息格式
	if(strcmp(szTypeName, szOID_PKCS_7_DATA) != 0) 
	{
		//        CryptMsgClose(hMsg);
		//      printf("The inner content is not szOID_PKCS_7_DATA."); 
	} 

	// 打开证书库
	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);
	}


	/**//*
		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);
	}

	
	CMSG_CTRL_DECRYPT_PARA para; 
	para.cbSize = sizeof (CMSG_CTRL_DECRYPT_PARA); 
	para.dwKeySpec = dwKeyType; 
	para.hCryptProv = hProv; 
	para.dwRecipientIndex = 0; 
	if(!CryptMsgControl( 
		hMsg,                // Handle to the message 
		0,                    // Flags 
		CMSG_CTRL_DECRYPT,    // Control type 
		¶))                // Pointer to the CERT_INFO 
	{
		CryptMsgClose(hMsg);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		printf("Failed in CryptMsgControl."); 
	}

	// 获取解密消息大小
	CRYPT_DATA_BLOB sigBlob;
	memset(&sigBlob, 0, sizeof(sigBlob));
	if(!CryptMsgGetParam( 
		hMsg,                // Handle to the message 
		CMSG_CONTENT_PARAM, // Parameter type 
		0,                    // Index 
		NULL,                //
		&sigBlob.cbData))    // Size of the returned 
	{                    
		CryptMsgClose(hMsg);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		printf("Failed in CryptMsgGetParam for CMSG_CONTENT_PARAM."); 
	} 

	// 分配内存
	sigBlob.pbData = (BYTE *) new char[sigBlob.cbData];
	if(sigBlob.pbData == NULL)
	{
		CryptMsgClose(hMsg);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		printf("Not enough memory."); 
	}

	// 获取解码消息
	if(!CryptMsgGetParam( 
		hMsg,                // Handle to the message 
		CMSG_CONTENT_PARAM, // Parameter type 
		0,                    // Index 
		sigBlob.pbData,        //
		&sigBlob.cbData))    // Size of the returned 
	{                    
		delete [] sigBlob.pbData;
		CryptMsgClose(hMsg);
		CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
		printf("Failed in CryptMsgGetParam for CMSG_CONTENT_PARAM."); 
	}
	sigBlob.pbData[sigBlob.cbData]='\0';
	// 清理解密过程数据
	CryptMsgClose(hMsg);
	CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);

	printf("Enveloped message decrypt successfully. \n"); 
	char* text = (char*)sigBlob.pbData;
	CComBSTR bstr(text);
	*plainText = bstr;
	return S_OK;
}



你可能感兴趣的:(加密,String,解密,null,delete,encoding)