CryptoAPI:用数字证书加密数据

因为公司最近要做一个读取市民卡信息的项目,从读卡器中读取到用户姓名和身份证后要用数字签名进行加密,然后再进行传输,在网上找了很久,终于找到相关的资料,稍微修改后在visual studio 2010中添加为一个类,在此记下,以供以后忘记时能用上。
//头文件/

#pragma once
#ifndef _WIN32_WINNT
#define _WIN32_WINNT 0x0501
#endif 

#pragma comment (lib, "crypt32.lib")

#include <stdio.h>
#include <malloc.h>
#include <windows.h>
#include <wincrypt.h>

#define MY_TYPE  (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)


class EncryptByCert
{
public:
	EncryptByCert(void);
	~EncryptByCert(void);

//变量声明
public:
	HCERTSTORE hStoreHandle;			//系统证书库
	BYTE* pbMessage;				//预签名消息
	DWORD cbMessage;				//预签名消息长度
	PCCERT_CONTEXT pSignerCert;			//签名证书
	CRYPT_SIGN_MESSAGE_PARA SigParams;		//签名参数结构
	DWORD cbSignedMessageBlob;			//签名数据块长度
	BYTE *pbSignedMessageBlob;			//签名数据块
	DWORD cbDecodedMessageBlob;			//解码数据块长度
	BYTE *pbDecodedMessageBlob;			//解码数据块
	CRYPT_VERIFY_MESSAGE_PARA VerifyParams;	        //验证参数结构

//成员函数声明
public:
	CString PadLeft(CString strSrc,int iLen,const char src);
	CString Hex2Str_OnetoTwo(BYTE byteSrc[],int byteLen);
	void Str2Hex_TwotoOne(CString strSrc,BYTE byteDist[],int byteLen);

	BOOL OpenCertStore(CString strStoreName);
	BOOL GetSignerCert(CString strSignerName);
	int SignMessage(BYTE *bIn, BYTE *bOut, DWORD inlen, DWORD &outlen);
	int EncryptSignMsg(CString strSrc, CString &strDes);
	int UnSignMessage(BYTE *bIn, BYTE *bOut, DWORD inlen);
	int DecryptSignMsg(CString strSrc, CString &strDes);
	BOOL Release();
};
//源文件/

#include "stdafx.h"
#include "EncryptByCert.h"


EncryptByCert::EncryptByCert(void)
{
	//初始化变量
	hStoreHandle = NULL;
	pbMessage = NULL;
	pbSignedMessageBlob = NULL;
	pbDecodedMessageBlob = NULL;
}


EncryptByCert::~EncryptByCert(void)
{
}


CString EncryptByCert::PadLeft(CString strSrc,int iLen,const char src)
{
	CString strDist;
	int strlen = strSrc.GetLength();

	if (iLen <= strlen)
	{
		strDist = strSrc.Left(iLen);
		return strDist;
	}

	for (int i = 0;i < iLen - strlen;i++)
	{
		strDist += src;
	}
	strDist.Append(strSrc);
	return strDist;
}


CString EncryptByCert::Hex2Str_OnetoTwo(BYTE byteSrc[],int byteLen)
{
	CString strOut(_T(""));
	CString strtemp(_T(""));
	int nTemp = 0;

	for (int i = 0; i < byteLen; i++)
	{
		nTemp = byteSrc[i];
		strtemp.Format(_T("%02x"),nTemp);
		strOut.Append(strtemp);
	}
	return strOut;
}


void EncryptByCert::Str2Hex_TwotoOne(CString strSrc,BYTE byteDist[],int byteLen)
{
	int nmid = 0;
	CString strmid(_T(""));
	CString strtemp;

	if (strSrc.IsEmpty())
	{
		return;
	}

	if (strSrc.GetLength() < byteLen * 2)
	{
		//strtemp = strSrc;
		strtemp = PadLeft(strSrc,byteLen * 2,'0');
	}
	else
		strtemp = strSrc;

	for (int i = 0; i < byteLen; i++)
	{
		strmid = strtemp.Mid(i * 2,2);
		nmid = strtol(strmid,NULL,16);
		byteDist[i] = nmid;
	}
}


BOOL EncryptByCert::OpenCertStore(CString strStoreName)
{
	BOOL bResult = FALSE;
	wchar_t wstr[256];
	MultiByteToWideChar(CP_ACP,0,strStoreName,-1,wstr,256);
	//打开证书库
	hStoreHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM,0,NULL,CERT_SYSTEM_STORE_CURRENT_USER,wstr);
	if(hStoreHandle)
	{
		bResult = TRUE;
	}
	return bResult;
}


BOOL EncryptByCert::GetSignerCert(CString strSignerName)
{
	BOOL bResult = FALSE;
	wchar_t wstr[256];
	MultiByteToWideChar(CP_ACP,0,strSignerName,-1,wstr,256);
	//获取签名证书指针,此证书必须拥有签名私钥
	pSignerCert = CertFindCertificateInStore(hStoreHandle, MY_TYPE, 0, CERT_FIND_SUBJECT_STR, wstr, NULL);
	if(pSignerCert)
	{
		bResult = TRUE;
	}
	return bResult;
}


int EncryptByCert::SignMessage(BYTE *bIn, BYTE *bOut, DWORD inlen, DWORD &outlen)
{
	int res = -1;

	// 创建消息队列及消息长度队列
	const BYTE* MessageArray[] = {bIn};
	DWORD MessageSizeArray[1];
	MessageSizeArray[0] = inlen;

	//获取签名数据大小
	if(!CryptSignMessage(
		&SigParams,				//签名参数结构
		FALSE,					//是否拆开
		1,						//消息队列数目
		MessageArray,			//消息队列
		MessageSizeArray,		//消息大小队列
		NULL,					//签名后的数据
		&cbSignedMessageBlob))	//签名数据长度
	{
		return res = 1;
	}

	outlen = cbSignedMessageBlob;
	//分配内存
	pbSignedMessageBlob = new BYTE[cbSignedMessageBlob];

	//签名操作,pbSignedMessageBlob指向签名数据块
	if(!CryptSignMessage(
		&SigParams,				//签名参数结构
		FALSE,					//是否拆开
		1,						//消息队列数目
		MessageArray,			//消息队列
		MessageSizeArray,		//消息大小队列
		pbSignedMessageBlob,	//签名后的数据
		&cbSignedMessageBlob))	//签名数据长度
	{
		res = 2;
	}
	else
	{
		memcpy(&bOut[0], pbSignedMessageBlob, cbSignedMessageBlob);
		res = 0;
	}

	
	return res;
}


int EncryptByCert::EncryptSignMsg(CString strSrc, CString &strDes)
{
	//初始化签名数据结构
	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;

	//初始化消息
	pbMessage = (BYTE*)strSrc.GetBuffer(strSrc.GetLength());
	strSrc.ReleaseBuffer();
	cbMessage = strlen((char*) pbMessage) + 1;

	int res = -1;
	BYTE out[2048] = {0};
	DWORD outlen = 0;
	//开始签名
	res = SignMessage(pbMessage, out, cbMessage, outlen);
	
	if(res == 0)
	{
		strDes = Hex2Str_OnetoTwo(out, outlen);
		return res;
	}
	else
	{
		strDes = _T("");
		return res;
	}
}


int EncryptByCert::UnSignMessage(BYTE *bIn, BYTE *bOut, DWORD inlen)
{
	int res = -1;

	//获取解码消息长度
	if(!CryptVerifyMessageSignature(
		&VerifyParams,			//验证参数结构
		0,						//签名序号
		bIn,					//签名数据
		inlen,					//签名数据长度
		NULL,					//解码后数据
		&cbDecodedMessageBlob,	//解码后数据长度
		NULL))					//签名证书指针
	{
		return res = 1;
	}

	//分配内存
	pbDecodedMessageBlob = new BYTE[cbDecodedMessageBlob];

	//验证签名,获取解码消息
	if(!CryptVerifyMessageSignature(
		&VerifyParams,			//验证参数结构
		0,						//签名序号
		bIn,					//签名数据
		inlen,					//签名数据长度
		pbDecodedMessageBlob,	//解码后数据
		&cbDecodedMessageBlob,	//解码后数据长度
		NULL))					//签名证书指针
	{
		res = 2;
	}
	else
	{
		memcpy(&bOut[0], pbDecodedMessageBlob, cbDecodedMessageBlob);
		res = 0;
	}

	return res;
}


int EncryptByCert::DecryptSignMsg(CString strSrc, CString &strDes)
{
	//初始化验证消息结构体
	VerifyParams.cbSize = sizeof(CRYPT_VERIFY_MESSAGE_PARA);
	VerifyParams.dwMsgAndCertEncodingType = MY_TYPE;
	VerifyParams.hCryptProv = 0;
	VerifyParams.pfnGetSignerCertificate = NULL;
	VerifyParams.pvGetArg = NULL;

	BYTE in[2048] = {0}, out[2048] = {0};
	int len = strSrc.GetLength()/2;
	Str2Hex_TwotoOne(strSrc, in, len);
	
	int res = -1;
	res = UnSignMessage(in, out, len);

	if(res == 0)
	{
		//strDes = Hex2Str_OnetoTwo(out, cbMessage);
		strDes.Format(_T("%s"), out);
		return res;
	}
	else
	{
		strDes = _T("");
		return res;
	}
}


BOOL EncryptByCert::Release()
{
	//释放空间、资源
	if(pbSignedMessageBlob)
	{
		delete [] pbSignedMessageBlob;
		pbSignedMessageBlob = NULL;
	}
	if(pbDecodedMessageBlob)
	{
		delete [] pbDecodedMessageBlob;
		pbDecodedMessageBlob = NULL;
	}
	if(pSignerCert)
		CertFreeCertificateContext(pSignerCert);
	//关闭证书库
	if(!CertCloseStore(hStoreHandle, CERT_CLOSE_STORE_CHECK_FLAG))
	{
		return FALSE;
	}
	return TRUE;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值