因为公司最近要做一个读取市民卡信息的项目,从读卡器中读取到用户姓名和身份证后要用数字签名进行加密,然后再进行传输,在网上找了很久,终于找到相关的资料,稍微修改后在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;
}