注:下面的代码中用了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;
}