以下代码只做示例,还存在许多问题需要修改
签名与验证(分验证证书合法性与不验证证书两种验证签名)
#include <stdio.h>
#include <conio.h>
#include <windows.h>
#include <wincrypt.h>
#include <iostream>
#include "Base.h" //实现Base64转码
#include <comdef.h>
using namespace std;
#define TEST_CSP_NAME "FEITIAN ePassNG RSA Cryptographic Service Provider" //飞天CSP
//返回值为'签名base64码'和';'和'证书base64码'
STDMETHODIMP CSignedData::Sign(BSTR orgData, BSTR* signature)
{
// TODO: Add your implementation code here
string orgText = _bstr_t (orgData);
// 准备数据
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
{
}
}
// 打开证书库
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);
return E_FAIL;
}
/**//*
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);
}
// 创建离散对象
HCRYPTHASH hHash = NULL;
if(!CryptCreateHash(
hKeyProv, // 容器句柄
CALG_MD5, // 算法标识
NULL, // 算法使用的Key
0, // 算法标识
&hHash)) // 返回的HASH对象
{
CertFreeCertificateContext(hCert);
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
BYTE *orgTextByte ;
int orgTextLen = orgText.size();
orgTextByte = new BYTE[orgTextLen];
for(int i=0;i<orgTextLen;i++){
orgTextByte[i]=orgText[i];
}
orgTextByte[orgTextLen]='\0';
// 计算数据摘要
if(CryptHashData(hHash, orgTextByte, orgTextLen, 0) == 0)
{
CryptDestroyHash(hHash);
CryptReleaseContext(hKeyProv, 0);
CertFreeCertificateContext(hCert);
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
/**//*
BOOL WINAPI CryptSignHash(
__in HCRYPTHASH hHash,
__in DWORD dwKeySpec,
__in LPCTSTR sDescription,
__in DWORD dwFlags,
__out BYTE* pbSignature,
__in_out DWORD* pdwSigLen
);
*/
DWORD cbSign = 4096;
BYTE *pbSign;
//获取签名数据摘要大小
if(!CryptSignHash(hHash, dwKeyType, NULL, 0, NULL, &cbSign))
{
CryptDestroyHash(hHash);
CryptReleaseContext(hKeyProv, 0);
CertFreeCertificateContext(hCert);
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
pbSign = new BYTE[cbSign];
//签名数据摘要
if(!CryptSignHash(hHash, dwKeyType, NULL, 0, pbSign, &cbSign))
{
CryptDestroyHash(hHash);
CryptReleaseContext(hKeyProv, 0);
CertFreeCertificateContext(hCert);
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
}
cout<<base64_encode(pbSign,cbSign)<<endl;
//将签名值转成base64编码
string baseSign = base64_encode(pbSign,cbSign);
//获取证书的base64编码
BYTE *newCert;
newCert = new BYTE[hCert->cbCertEncoded];
newCert = hCert->pbCertEncoded;
string baseCert = base64_encode(newCert,hCert->cbCertEncoded);
//返回签名和证书的base64编码
CComBSTR bstr((baseSign+";"+baseCert).c_str());
*signature=bstr;
//释放资源
if(hHash != NULL)
{
CryptDestroyHash(hHash);
hHash = NULL;
}
if(hKeyProv != NULL && bFreeKeyProv)
{
CryptReleaseContext(hKeyProv, 0);
hKeyProv = NULL;
}
if(hCert != NULL)
{
CertFreeCertificateContext(hCert);
hCert = NULL;
}
if(hCertStore != NULL)
{
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
hCertStore = NULL;
}
return S_OK;
}
//验证签名(无证书验证)
STDMETHODIMP CSignedData::VerifySign(BSTR Signed_base64, BSTR Cert_base64, BSTR orgData, BOOL* verifySuc)
{
// TODO: Add your implementation code here
// 准备数据
BYTE* signedData;
string cstrSigned = _bstr_t (Signed_base64);
string decodeData = base64_decode(cstrSigned);
int len = decodeData.size();
signedData = new BYTE[len] ;
for(int i = 0; i < len; ++i)
{
signedData[i] = (byte)decodeData[i];
}
signedData[len] = '\0';
// 请求容器服务
HCRYPTPROV hProv = NULL;
if(!CryptAcquireContext(
&hProv, // 返回的句柄
NULL, // CSP key 容器名称
TEST_CSP_NAME, // CSP 提供者名称
PROV_RSA_FULL, // CSP 提供者类型
0)) // 附加参数
{
return E_FAIL;
}
// 创建离散对象
HCRYPTHASH hHash = NULL;
if(!CryptCreateHash(
hProv, // 容器句柄
CALG_MD5, // 算法标识
NULL, // 算法使用的Key
0, // 算法标识
&hHash)) // 返回的HASH对象
{
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
string cstrOrgData = _bstr_t (orgData);
BYTE* orgBlob;
int orglen = cstrOrgData.size();
orgBlob = new BYTE[orglen] ;
for(int i = 0; i < orglen; ++i)
{
orgBlob[i] = (byte)cstrOrgData[i];
}
orgBlob[orglen] = '\0';
// 计算数据摘要
if(CryptHashData(hHash, orgBlob, orglen, 0) == 0)
{
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
// 获取签名者证书公钥
/*
HCERTSTORE WINAPI CertOpenStore(
__in LPCSTR lpszStoreProvider,
__in DWORD dwMsgAndCertEncodingType,
__in HCRYPTPROV_LEGACY hCryptProv,
__in DWORD dwFlags,
__in const void* pvPara
);
*/
BYTE* cert;
string cstrCert_base64 = _bstr_t (Cert_base64);
string decodeCert = base64_decode(cstrCert_base64);
int certLen = decodeCert.size();
cert = new BYTE[certLen] ;
for(int i = 0; i < certLen; ++i)
{
cert[i] = (byte)decodeCert[i];
}
cert[certLen] = '\0';
PCCERT_CONTEXT pCertContext = NULL;
if(pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, // The encoding type
cert, // The encoded data from
// the certificate retrieved
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");
return E_FAIL;
}
HCRYPTKEY hPubKey;
if(!CryptImportPublicKeyInfo(hProv, pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
{
CryptDestroyKey(hPubKey);
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
// 校验签名
/*
BOOL WINAPI CryptVerifySignature(
__in HCRYPTHASH hHash,
__in BYTE* pbSignature,
__in DWORD dwSigLen,
__in HCRYPTKEY hPubKey,
__in LPCTSTR sDescription,
__in DWORD dwFlags
);
*/
if(!CryptVerifySignature(hHash, signedData, len, hPubKey, NULL, 0))
{
*verifySuc=false;
return S_FALSE;
}
else
{
*verifySuc=true;
}
// 释放获取的对象
if(hPubKey != NULL)
{
CryptDestroyKey(hPubKey);
hPubKey = NULL;
}
if(hHash != NULL)
{
CryptDestroyHash(hHash);
hHash = NULL;
}
if(pCertContext != NULL)
{
CertFreeCertificateContext(pCertContext);
pCertContext = NULL;
}
if(hProv != NULL)
{
CryptReleaseContext(hProv, 0);
hProv = NULL;
}
return S_OK;
}
//带证书验证部分的签名验证
STDMETHODIMP CSignedData::VerifySignWithCRL(BSTR Signed_base64, BSTR Cert_base64, BSTR orgData, BSTR CRL_base64, BOOL* verifySuc)
{
// TODO: 在此添加实现代码
// TODO: Add your implementation code here
// 准备数据
BYTE* signedData;
string cstrSigned = _bstr_t (Signed_base64);
string cstrCRL_base64 = _bstr_t(CRL_base64);
int count = cstrCRL_base64.size();
string decodeData = base64_decode(cstrSigned);
int len = decodeData.size();
signedData = new BYTE[len] ;
for(int i = 0; i < len; ++i)
{
signedData[i] = (byte)decodeData[i];
}
signedData[len] = '\0';
// 请求容器服务
HCRYPTPROV hProv = NULL;
if(!CryptAcquireContext(
&hProv, // 返回的句柄
NULL, // CSP key 容器名称
TEST_CSP_NAME, // CSP 提供者名称
PROV_RSA_FULL, // CSP 提供者类型
0)) // 附加参数
{
return E_FAIL;
}
// 创建离散对象
HCRYPTHASH hHash = NULL;
if(!CryptCreateHash(
hProv, // 容器句柄
CALG_MD5, // 算法标识
NULL, // 算法使用的Key
0, // 算法标识
&hHash)) // 返回的HASH对象
{
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
string cstrOrgData = _bstr_t (orgData);
BYTE* orgBlob;
int orglen = cstrOrgData.size();
orgBlob = new BYTE[orglen] ;
for(int i = 0; i < orglen; ++i)
{
orgBlob[i] = (byte)cstrOrgData[i];
}
orgBlob[orglen] = '\0';
// 计算数据摘要
if(CryptHashData(hHash, orgBlob, orglen, 0) == 0)
{
CryptDestroyHash(hHash);
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
// 获取签名者证书公钥
/*
HCERTSTORE WINAPI CertOpenStore(
__in LPCSTR lpszStoreProvider,
__in DWORD dwMsgAndCertEncodingType,
__in HCRYPTPROV_LEGACY hCryptProv,
__in DWORD dwFlags,
__in const void* pvPara
);
*/
BYTE* cert;
string cstrCert_base64 = _bstr_t (Cert_base64);
string decodeCert = base64_decode(cstrCert_base64);
int certLen = decodeCert.size();
cert = new BYTE[certLen] ;
for(int i = 0; i < certLen; ++i)
{
cert[i] = (byte)decodeCert[i];
}
cert[certLen] = '\0';
PCCERT_CONTEXT pCertContext = NULL;
if(pCertContext = CertCreateCertificateContext(
X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, // The encoding type
cert, // The encoded data from
// the certificate retrieved
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");
return E_FAIL;
}
bool certIsValid = verifyCert(pCertContext,cstrCRL_base64);
if(certIsValid){
HCRYPTKEY hPubKey;
if(!CryptImportPublicKeyInfo(hProv, pCertContext->dwCertEncodingType, &pCertContext->pCertInfo->SubjectPublicKeyInfo, &hPubKey))
{
CryptDestroyKey(hPubKey);
CryptReleaseContext(hProv, 0);
return E_FAIL;
}
// 校验签名
/*
BOOL WINAPI CryptVerifySignature(
__in HCRYPTHASH hHash,
__in BYTE* pbSignature,
__in DWORD dwSigLen,
__in HCRYPTKEY hPubKey,
__in LPCTSTR sDescription,
__in DWORD dwFlags
);
*/
if(!CryptVerifySignature(hHash, signedData, len, hPubKey, NULL, 0))
{
*verifySuc=false;
return S_FALSE;
}
else
{
*verifySuc=true;
}
if(hPubKey != NULL)
{
CryptDestroyKey(hPubKey);
hPubKey = NULL;
}
}else{
*verifySuc=false;
}
// 释放获取的对象
if(hHash != NULL)
{
CryptDestroyHash(hHash);
hHash = NULL;
}
if(pCertContext != NULL)
{
CertFreeCertificateContext(pCertContext);
pCertContext = NULL;
}
if(hProv != NULL)
{
CryptReleaseContext(hProv, 0);
hProv = NULL;
}
return S_OK;
}
// 校验证书合法性
bool verifyCert(PCCERT_CONTEXT hCert,string CRL_base64)
{
/*
*获取CRLContext对象
*/
string CRL = base64_decode(CRL_base64);
BYTE *pbCRL = NULL;
pbCRL = new BYTE[CRL.size()];
for(int i=0;i<CRL.size();i++){
pbCRL[i]=(BYTE)CRL[i];
}
int cbCRL = CRL.size();
pbCRL[cbCRL]='\0';
PCCRL_CONTEXT hCRL = CertCreateCRLContext(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,pbCRL,cbCRL);
if(hCRL==NULL){
printf("未找到CRL");
}else{
printf("找到CRL");
}
/**//*
LONG WINAPI CertVerifyTimeValidity(
__in LPFILETIME pTimeToVerify,
__in PCERT_INFO pCertInfo
);
*/
// 校验证书日期
int nRetCode = CertVerifyTimeValidity(NULL, hCert->pCertInfo);
if(nRetCode < 0)
{
printf("Verify cert's date failed: BEFORE date after TODAY!\n");
return false;
}
if(nRetCode > 0)
{
printf("Verify cert's date failed: Cert has expired!\n");
return false;
}
if(nRetCode == 0)
{
printf("Verify cert's date succeed!\n");
}
// 校验签名者证书
HCERTSTORE hCertStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"ROOT");
if(hCertStore != NULL)
{
/**//*
PCCERT_CONTEXT WINAPI CertGetIssuerCertificateFromStore(
__in HCERTSTORE hCertStore,
__in PCCERT_CONTEXT pSubjectContext,
__in_opt PCCERT_CONTEXT pPrevIssuerContext,
__in_out DWORD* pdwFlags
);
*/
// 2.
DWORD dwFlags = CERT_STORE_SIGNATURE_FLAG;
PCCERT_CONTEXT hIssuserCert = CertGetIssuerCertificateFromStore(hCertStore, hCert, NULL, &dwFlags);
if(hIssuserCert != NULL)
{
BOOL bCheckOK = FALSE;
while(hIssuserCert != NULL)
{
/**//*
BOOL WINAPI CertVerifySubjectCertificateContext(
__in PCCERT_CONTEXT pSubject,
__in_opt PCCERT_CONTEXT pIssuer,
__in_out DWORD* pdwFlags
);
*/
// 校验证书签发者信息合法性
dwFlags = CERT_STORE_SIGNATURE_FLAG;
if(CertVerifySubjectCertificateContext(hCert, hIssuserCert, &dwFlags))
{
if(dwFlags == 0)
{
printf("Verify cert by issuser's cert succeed! \n");
bCheckOK = TRUE;
break;
}
}
else
{
printf("Verify cert by issuser's cert failed! \n");
return false;
break;
}
// Next ..
hIssuserCert = CertGetIssuerCertificateFromStore(hCertStore, hCert, hIssuserCert, &dwFlags);
}
if(!bCheckOK)
{
printf("Verify cert by issuser's cert failed! \n");
return false;
}
}
else
{
printf("Can not find cert issuser's cert!\n");
}
if(hIssuserCert != NULL)
{
CertFreeCertificateContext(hIssuserCert);
hIssuserCert = NULL;
}
}
else
{
printf("Open ROOT CertStore failed!\n");
return false;
}
if(hCertStore != NULL)
{
CertCloseStore(hCertStore, CERT_CLOSE_STORE_FORCE_FLAG);
hCertStore = NULL;
}
// 校验 CRL 列表
// 1.
//BYTE* pbCrlData = NULL;
//DWORD cbCrlData = 0;
//readFile("c:\\cfcaT.crl", NULL, cbCrlData);
//if(cbCrlData > 0)
//{
// pbCrlData = (BYTE*) new char[cbCrlData];
// readFile("c:\\cfcaT.crl", pbCrlData, cbCrlData);
//}
///**//*
// PCCRL_CONTEXT WINAPI CertCreateCRLContext(
// __in DWORD dwCertEncodingType,
// __in const BYTE* pbCrlEncoded,
// __in DWORD cbCrlEncoded
// );
// */
//// 2.转换CRL数据为CRL句柄
//PCCRL_CONTEXT hCRL = CertCreateCRLContext(MY_ENCODING_TYPE, pbCrlData, cbCrlData);
//delete [] pbCrlData;
if(hCRL != NULL)
{
/**//*
BOOL WINAPI CertIsValidCRLForCertificate(
__in PCCERT_CONTEXT pCert,
__in PCCRL_CONTEXT pCRL,
__in DWORD dwFlags,
__in void* pvReserved
*/
if(CertIsValidCRLForCertificate(hCert, hCRL, 0, NULL))
{
printf("CRL is valid for the cert!\n");
}
else
{
printf("CRL is invalid for the cert!!\n");
return false;
}
/**//*
BOOL WINAPI CertFindCertificateInCRL(
__in PCCERT_CONTEXT pCert,
__in PCCRL_CONTEXT pCrlContext,
__in DWORD dwFlags,
__in_opt void* pvReserved,
__out PCRL_ENTRY* pCrlEntry
);
*/
// Step 4: 检查CRL是否包含该证书
PCRL_ENTRY pCrlEntry = NULL;
if(CertFindCertificateInCRL(hCert, hCRL, 0, 0, &pCrlEntry))
{
if(pCrlEntry != NULL)
{
printf("Cert has been revoked!\n");
return false;
}
else
{
printf("Cert not be revoked!\n");
}
}
else
{
printf("Find cert in CRL failed!\n");
return false;
}
}
else
{
printf("Create CRL context failed!\n");
return false;
}
if(hCRL != NULL)
{
CertFreeCRLContext(hCRL);
}
}