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

注:下面的代码中用了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码创建证书上下文,然后使用该证书及其公钥验证数字签名
//----------------------
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值