http://www.blogjava.net/sham2k/archive/2009/08/19/291745.html点击打开链接
本文是 MS CryptoAPI Samples 的姐妹篇,演示如何使用微软的CAPICOM组件。CAPICOM组件是建立在CryptoAPI基础上的ActiveX控件,供JavaScript、VBScript以及其他非C/C++语言使用。使用该组件,极大简化加密、签名应用程序的编写,但功能略受限制。
//
examCAPI.cpp : 定义控制台应用程序的入口点。
//
#include
"
stdafx.h
"
#include
<
ATLComTime.h
>
//
加载 CAPICOM 组件
#
import
"
capicom.dll
"
using namespace CAPICOM;
//
=========================================================
//
工具方法
//
=========================================================
//
暂停
void
pause()
{ _tprintf(_T( " \nPress ENTER key to continue \n " )); getchar(); }
//
错误报告
void
CancelByError(HRESULT errCode, TCHAR
*
errStr)
{ _tprintf(_T( " \nFAULT:\n " )); _tprintf(_T( " An error occurred in running the program. \n " )); _tprintf(_T( " %s \n " ), errStr); throw errCode; }
//
字节反序
void
reverse(BYTE
*
data,
int
nLen)
{ for ( int ii = 0 ; ii < nLen / 2 ; ii ++ ) { BYTE c = data[ii]; data[ii] = data[nLen - ii - 1 ]; data[nLen - ii - 1 ] = c; } }
//
输出文件
void
writeFile(
const
char
*
sFileName, BYTE
*
data, DWORD nSize)
{ FILE * fp = fopen(sFileName, " wb " ); if (fp == NULL) { CancelByError( 0 , _T( " Open file for write failed! " )); } if (fwrite(data, 1 , nSize, fp) != nSize) { fclose(fp); CancelByError( 0 , _T( " Write to file failed! " )); } fclose(fp); printf(" Write %d bytes to file '%s'! \n " , nSize, sFileName); }
//
读取文件(data = NULL for get file size ONLY)
void
readFile(
const
char
*
sFileName, BYTE
*
data, DWORD
&
nSize)
{ nSize = 0 ; FILE * fp = fopen(sFileName, " rb " ); if (fp == NULL) { CancelByError( 0 , _T( " Open file for read failed! " )); } fseek(fp, 0 , SEEK_END); nSize = ftell(fp); fseek(fp, 0 , SEEK_SET); if (data != NULL) { if (fread(data, 1 , nSize, fp) != nSize) { fclose(fp); CancelByError( 0 , _T( " Read from file failed! " )); } printf(" Read %d bytes from file '%s'! \n " , nSize, sFileName); } fclose(fp); }
//
显示HEX码
void
showData(BYTE
*
data, DWORD nSize)
{ printf( " \n****\n " ); for (DWORD ii = 0 ; ii < nSize; ii ++ ) { printf( " %02x " , data[ii]); if ((ii + 1 ) % 16 == 0 ) printf( " \n " ); } printf(" \n**** %d bytes\n " , nSize); }
//
准备数据(Auto new outData)
void
prepareData(BYTE
*
inData, DWORD inSize, LPCSTR inFileName, BYTE
*
&
outData, DWORD
&
outSize)
{ if (inData == NULL && inFileName != NULL) { // Read from file readFile(inFileName, NULL, outSize); if (outSize != 0 ) { outData = (BYTE * ) new char [outSize + 1 ]; memset(outData, 0 , outSize + 1 ); if (outData == NULL) CancelByError( 0 , _T( " Not enough memory. \n " )); readFile(inFileName, outData, outSize); } } else { // Read from buffer outSize = inSize; outData = (BYTE * ) new char [outSize]; if (outData == NULL) CancelByError( 0 , _T( " Not enough memory. \n " )); memcpy(outData, inData, outSize); } }
//
获取BSTR的长度及字节值
void
getBSTRByte(BSTR
&
bstr, BYTE
*
(
&
data), DWORD
&
nSize)
{ data = (BYTE * ) bstr; nSize = * ((DWORD * )bstr - 1 ); }
//
=========================================================
//
编码与解码
//
=========================================================
//
BASE64编码
void
Base64Encode(BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); // 注意: // 原始数据是二进制值,应使用原值,以避免转换为宽字符串参数时导致失真。 // SysAllocStringByteLen 会禁用多字节到宽字节的转换,因而可以保证内容无损地转换为宽字符串。 _bstr_t orgStr; BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); orgStr.Assign(orgBStr); SysFreeString(orgBStr); if (pbOrgData != NULL) delete [] pbOrgData; // 创建 Utilities 对象 IUtilitiesPtr pUtils(__uuidof(Utilities)); try { // 编码 _bstr_t encStr = pUtils -> Base64Encode(orgStr); // 输出 // 注意:编码输出转换为多字节不会导致失真,直接转换。 char * pEncStr = encStr; printf( " [%s]\n " , pEncStr); if (outFileName != NULL) { writeFile(outFileName, (BYTE * )pEncStr, strlen(pEncStr)); } } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pUtils.Release(); }
//
BASE64解码
void
Base64Decode(BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备编码数据 DWORD cbEncData = 0 ; BYTE * pbEncData = NULL; prepareData(inData, inSize, inFileName, pbEncData, cbEncData); // 创建 Utilities 对象 IUtilitiesPtr pUtils(__uuidof(Utilities)); try { // 解码 // 注意:编码数据转换为宽字符参数不会导致失真,因此直接转换。 _bstr_t orgStr = pUtils -> Base64Decode(( char * )pbEncData); // 从解码输出的宽字符串中获取原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; getBSTRByte(orgStr.GetBSTR(), pbOrgData, cbOrgData); // 输出 showData(pbOrgData, cbOrgData); if (outFileName != NULL) { writeFile(outFileName, pbOrgData, cbOrgData); } } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbEncData != NULL) delete [] pbEncData; pUtils.Release(); }
//
=========================================================
//
数字摘要
//
=========================================================
//
SHA1
void
hashSHA1(BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); _bstr_t orgStr; BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); orgStr.Assign(orgBStr); SysFreeString(orgBStr); if (pbOrgData != NULL) delete [] pbOrgData; // 创建 HashData 对象 IHashedDataPtr pHash(__uuidof(HashedData)); try { // 计算数字摘要 pHash -> Algorithm = CAPICOM_HASH_ALGORITHM_SHA1; pHash -> Hash(orgStr); _bstr_t outStr = pHash -> Value; const char * encStr = ( char * ) outStr; printf( " %s\n " , encStr); if (outFileName != NULL) { writeFile(outFileName, (BYTE * )encStr, strlen(encStr)); } } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT hr) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), hr); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pHash.Release(); }
//
===============================================================
//
对称加密
//
CAPICOM 加密使用非PKCS#7标准的格式,只能使用 CAPICOM 解密。
//
===============================================================
//
DES 加密
void
DESEncrypt(BYTE
*
key, BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); // 转换为宽字符串参数 _bstr_t orgStr; BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); orgStr.Assign(orgBStr); SysFreeString(orgBStr); if (pbOrgData != NULL) delete [] pbOrgData; // 创建加密对象 IEncryptedDataPtr pEncryptedData(__uuidof(EncryptedData)); try { // 加密 pEncryptedData -> Content = orgStr; pEncryptedData -> SetSecret(( char * )key, CAPICOM_SECRET_PASSWORD); pEncryptedData -> Algorithm -> Name = CAPICOM::CAPICOM_ENCRYPTION_ALGORITHM_DES; _bstr_t encStr = pEncryptedData -> Encrypt(CAPICOM_ENCODE_BASE64); // 输出加密结果 char * pEncStr = encStr; printf( " %s " , pEncStr); if (outFileName != NULL) { writeFile(outFileName, (BYTE * ) pEncStr, strlen(pEncStr)); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT retCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), retCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pEncryptedData.Release(); }
//
DES 解密
void
DESDecrypt(BYTE
*
key, BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备数据 DWORD cbEncData = 0 ; BYTE * pbEncData = NULL; prepareData(inData, inSize, inFileName, pbEncData, cbEncData); // 创建加密对象 IEncryptedDataPtr pEncryptedData(__uuidof(EncryptedData)); try { // 解密 pEncryptedData -> SetSecret(( char * )key, CAPICOM_SECRET_PASSWORD); pEncryptedData -> Algorithm -> Name = CAPICOM::CAPICOM_ENCRYPTION_ALGORITHM_DES; pEncryptedData -> Decrypt(( char * )pbEncData); // 获取原始数据 _bstr_t orgStr = pEncryptedData -> Content; BYTE * orgData = NULL; DWORD orgSize = 0 ; getBSTRByte(orgStr.GetBSTR(), orgData, orgSize); showData(orgData, orgSize); if (outFileName != NULL) { writeFile(outFileName, orgData, orgSize); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbEncData != NULL) delete [] pbEncData; pEncryptedData.Release(); }
//
DES 加密(bin)
void
DESEncryptBin(BYTE
*
key, BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); // 转换为宽字符参数 _bstr_t orgStr; BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); orgStr.Assign(orgBStr); SysFreeString(orgBStr); if (pbOrgData != NULL) delete [] pbOrgData; // 创建加密对象 IEncryptedDataPtr pEncryptedData(__uuidof(EncryptedData)); try { // 加密 pEncryptedData -> Content = orgStr; pEncryptedData -> SetSecret(( char * )key, CAPICOM_SECRET_PASSWORD); pEncryptedData -> Algorithm -> Name = CAPICOM::CAPICOM_ENCRYPTION_ALGORITHM_DES; _bstr_t encStr = pEncryptedData -> Encrypt(CAPICOM_ENCODE_BINARY); // 获取加密数据 DWORD cbEncData = 0 ; BYTE * pbEncData = NULL; getBSTRByte(encStr.GetBSTR(), pbEncData, cbEncData); // 输出 showData(pbEncData, cbEncData); if (outFileName != NULL) { writeFile(outFileName, pbEncData, cbEncData); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT retCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), retCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pEncryptedData.Release(); }
//
DES 解密(bin)
void
DESDecryptBin(BYTE
*
key, BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, LPCSTR outFileName
=
NULL)
{ // 准备数据 DWORD cbEncData = 0 ; BYTE * pbEncData = NULL; prepareData(inData, inSize, inFileName, pbEncData, cbEncData); // 转换为宽字符参数 _bstr_t encStr; BSTR encBStr = SysAllocStringByteLen((LPCSTR)pbEncData, cbEncData); encStr.Assign(encBStr); SysFreeString(encBStr); if (pbEncData != NULL) delete [] pbEncData; // 创建加密对象 IEncryptedDataPtr pEncryptedData(__uuidof(EncryptedData)); try { // 解密 pEncryptedData -> SetSecret(( char * )key, CAPICOM_SECRET_PASSWORD); pEncryptedData -> Algorithm -> Name = CAPICOM::CAPICOM_ENCRYPTION_ALGORITHM_DES; pEncryptedData -> Decrypt(encStr); // 获取原始数据 _bstr_t orgStr = pEncryptedData -> Content; BYTE * orgData = NULL; DWORD orgSize = 0 ; getBSTRByte(orgStr.GetBSTR(), orgData, orgSize); showData(orgData, orgSize); if (outFileName != NULL) { writeFile(outFileName, orgData, orgSize); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pEncryptedData.Release(); }
//
=========================================================
//
数字证书
//
=========================================================
//
显式证书信息
void
viewCertInfo(ICertificatePtr pCert)
{ COleDateTime timeFrom(pCert -> ValidFromDate); COleDateTime timeTo(pCert -> ValidToDate); _tprintf(_T( " Subject: %s\n " ), pCert -> SubjectName.GetBSTR()); _tprintf(_T( " SubjectCN: %s\n " ), pCert -> GetInfo(CAPICOM_CERT_INFO_SUBJECT_SIMPLE_NAME).GetBSTR()); _tprintf(_T( " Issuser: %s\n " ), pCert -> IssuerName.GetBSTR()); _tprintf(_T( " SerialNumber: %s\n " ), pCert -> SerialNumber.GetBSTR()); _tprintf(_T( " ValidDate: %s TO %s \n " ), timeFrom.Format(L " %Y-%m-%d %H:%M:%S " ), timeTo.Format(L " %Y-%m-%d %H:%M:%S " )); // Check Certificate ICertificateStatusPtr pStatus = pCert -> IsValid(); pStatus -> CheckFlag = CAPICOM_CHECK_TIME_VALIDITY; _tprintf(_T( " Check-Time: %s\n " ), (pStatus -> Result) ? L " Yes " : L " NO " ); pStatus -> CheckFlag = CAPICOM_CHECK_SIGNATURE_VALIDITY; _tprintf(_T( " Check-Sign: %s\n " ), (pStatus -> Result) ? L " Yes " : L " NO " ); pStatus -> CheckFlag = CAPICOM_CHECK_TRUSTED_ROOT; _tprintf(_T( " Check-CA: %s\n " ), (pStatus -> Result) ? L " Yes " : L " NO " ); pStatus -> CheckFlag = CAPICOM_CHECK_COMPLETE_CHAIN; _tprintf(_T( " Check-Chain: %s\n " ), (pStatus -> Result) ? L " Yes " : L " NO " ); }
//
系统证书库
void
viewSystemCertStore(LPCTSTR sCertName)
{ // 创建证书库对象 IStorePtr pStore(__uuidof(Store)); try { HRESULT retCode = pStore -> Open(CAPICOM_CURRENT_USER_STORE, sCertName, CAPICOM_STORE_OPEN_READ_ONLY); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not open certStore! " )); } ICertificatesPtr pCerts = pStore -> GetCertificates(); if (pCerts != NULL) { _tprintf(_T( " ======== L I S T C E R T I N S T O R E ============\n " )); for ( int ii = 0 ; ii < pCerts -> Count; ii ++ ) { _variant_t p = pCerts -> GetItem(ii + 1 ); ICertificatePtr pCert = p.pdispVal; if (pCert != NULL) { viewCertInfo(pCert); _tprintf(_T( " ----------------------------------------------------\n " )); } } _tprintf(_T(" ======== %d Certs ============\n " ), pCerts -> Count); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pStore.Release(); }
//
文件证书库(crt/p7b)
void
viewCrtCertStore(LPCSTR strCertFileName)
{ IStore2Ptr pStore(__uuidof(Store)); try { // 访问证书库 HRESULT retCode = pStore -> Open(CAPICOM_MEMORY_STORE, strCertFileName, CAPICOM_STORE_OPEN_READ_WRITE); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not open memory certStore! " )); } // 加载证书文件到证书库 retCode = pStore -> Load(( char * )strCertFileName, "" , CAPICOM_KEY_STORAGE_DEFAULT); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not load certFile! " )); } // 列出证书 ICertificatesPtr pCerts = pStore -> GetCertificates(); if (pCerts != NULL) { _tprintf(_T( " ======== L I S T C E R T I N S T O R E ============\n " )); for ( int ii = 0 ; ii < pCerts -> Count; ii ++ ) { _variant_t p = pCerts -> GetItem(ii + 1 ); ICertificatePtr pCert = p.pdispVal; if (pCert != NULL) { viewCertInfo(pCert); _tprintf(_T( " ----------------------------------------------------\n " )); } } _tprintf(_T(" ======== %d Certs ============\n " ), pCerts -> Count); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pStore.Release(); }
//
文件证书库(pfx)
void
viewPfxCertStore(LPCSTR sPfxFileName, LPCSTR sPfxPwd)
{ // 创建证书对象 ICertificate2Ptr pCert(__uuidof(Certificate)); try { HRESULT retCode = pCert -> Load(sPfxFileName, sPfxPwd, CAPICOM_KEY_STORAGE_DEFAULT, CAPICOM_CURRENT_USER_KEY); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not open certStore! " )); } viewCertInfo(pCert); } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pCert.Release(); }
//
=========================================================
//
数字签名
//
=========================================================
//
数字签名
void
callSignedData(BYTE
*
inData,
int
inSize, LPCSTR inFileName
=
NULL, BOOL bDetached
=
FALSE, LPCSTR outFileName
=
NULL)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); _bstr_t orgStr; BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); orgStr.Assign(orgBStr); if (pbOrgData != NULL) delete [] pbOrgData; SysFreeString(orgBStr); // 创建对象 IStorePtr pStore(__uuidof(Store)); // 证书库对象 ISignerPtr pSigner(__uuidof(Signer)); // 签名者对象 ISignedDataPtr pSignedData(__uuidof(SignedData)); // 签名数据对象 try { // 设置原始数据 pSignedData -> Content = orgStr; // 访问证书库 HRESULT retCode = pStore -> Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not open certStore! " )); } // 设置签名者证书 ICertificates2Ptr pSignerCerts = ((ICertificates2Ptr) pStore -> Certificates) -> Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, L " lny " , FALSE); if (pSignerCerts == NULL || pSignerCerts -> Count < 1 ) { CancelByError( 0 , _T( " Can not find signer certificate! " )); } pSigner-> Certificate = (ICertificatePtr) pSignerCerts -> GetItem( 1 ).pdispVal; viewCertInfo(pSigner -> Certificate); // 签名者签名 _bstr_t strSignedStr = pSignedData -> Sign(pSigner, bDetached, CAPICOM_ENCODE_BASE64); /* =============== 多签名者签名 ======================================== ISignerPtr pCoSigner(__uuidof(Signer)); // 协助签名者对象 // 设置协助签名者证书 ICertificates2Ptr pCoSignerCerts = ((ICertificates2Ptr) pStore->Certificates)->Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, L"041@3BNKICNSZXXX@test9@00000001", FALSE); if(pCoSignerCerts == NULL || pCoSignerCerts->Count < 1) { CancelByError(0, _T("Can not find CoSigner certificate! ")); } pCoSigner->Certificate = (ICertificatePtr) pCoSignerCerts->GetItem(1).pdispVal; viewCertInfo(pCoSigner->Certificate); // 协助签名者签名 strSignedStr = pSignedData->CoSign(pCoSigner, CAPICOM_ENCODE_BASE64); ========================================================================= */ // 输出 _tprintf(_T( " %s\n " ), strSignedStr.GetBSTR()); char * pOutStr = strSignedStr; if (outFileName != NULL) { writeFile(outFileName, (BYTE * )pOutStr, strlen(( char * )pOutStr)); } } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 pStore.Release(); pSigner.Release(); pSignedData.Release(); }
//
核验带原文的数字签名
void
VerifySignedData(LPCSTR inFileName)
{ // 准备签名数据 DWORD cbSigData = 0 ; BYTE * pbSigData = NULL; prepareData(NULL, 0 , inFileName, pbSigData, cbSigData); // 创建签名数据对象 ISignedDataPtr pSignedData(__uuidof(SignedData)); try { // 校验数字签名 HRESULT retCode = pSignedData -> Verify(( char * )pbSigData, FALSE, CAPICOM_VERIFY_SIGNATURE_ONLY); if (FAILED(retCode)) { CancelByError(retCode, _T( " 校验数字签名失败! " )); } // 获取原文 BYTE * orgStr = NULL; DWORD orgSize = 0 ; getBSTRByte(pSignedData -> Content.GetBSTR(), orgStr, orgSize); printf( " %s\n " , orgStr); // 显式签名者证书信息 _tprintf(_T( " ======== L I S T C E R T I N S T O R E ============\n " )); for ( int ii = 0 ; ii < pSignedData -> Certificates -> Count; ii ++ ) { viewCertInfo(pSignedData -> Certificates -> GetItem(ii + 1 )); _tprintf(_T( " ----------------------------------------------------\n " )); } _tprintf(_T(" ======== %d Certs ============\n " ), pSignedData -> Certificates -> Count); } catch (_com_error e) { _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbSigData != NULL) delete [] pbSigData; pSignedData.Release(); }
//
核验无原文的数字签名
void
VerifyDetachedSignedData(BYTE
*
inData,
int
inSize, LPCSTR inFileName, LPCSTR outFileName)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); // 准备签名数据 DWORD cbSigData = 0 ; BYTE * pbSigData = NULL; prepareData(NULL, 0 , outFileName, pbSigData, cbSigData); // 创建签名者对象 ISignerPtr pSigner(__uuidof(Signer)); // 创建签名数据对象 ISignedDataPtr pSignedData(__uuidof(SignedData)); try { // 设置原始数据 _bstr_t inStr; inStr.Assign(orgBStr); pSignedData -> Content = inStr; // 校验数字签名 HRESULT retCode = pSignedData -> Verify(( char * )pbSigData, TRUE, CAPICOM_VERIFY_SIGNATURE_ONLY); if (FAILED(retCode)) { CancelByError(retCode, _T( " 校验数字签名失败! " )); } // 显式签名者证书信息 _tprintf(_T( " ======== L I S T C E R T I N S T O R E ============\n " )); for ( int ii = 0 ; ii < pSignedData -> Certificates -> Count; ii ++ ) { viewCertInfo(pSignedData -> Certificates -> GetItem(ii + 1 )); _tprintf(_T( " ----------------------------------------------------\n " )); } _tprintf(_T(" ======== %d Certs ============\n " ), pSignedData -> Certificates -> Count); } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbOrgData != NULL) delete [] pbOrgData; if (pbSigData != NULL) delete [] pbSigData; SysFreeString(orgBStr); pSigner.Release(); pSignedData.Release(); }
//
=========================================================
//
数字信封(证书加密与解密)
//
=========================================================
//
证书加密
void
CertEncryptData(BYTE
*
inData,
int
inSize, LPCSTR inFileName, LPCSTR outFileName)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(inData, inSize, inFileName, pbOrgData, cbOrgData); BSTR orgBStr = SysAllocStringByteLen((LPCSTR)pbOrgData, cbOrgData); // 创建证书库对象 IStorePtr pStore(__uuidof(Store)); // 创建签名数据对象 IEnvelopedDataPtr pEnvelopedData(__uuidof(EnvelopedData)); try { // 设置原始数据 _bstr_t inStr; inStr.Assign(orgBStr); pEnvelopedData -> Content = inStr; // 设置加密算法 pEnvelopedData -> Algorithm -> Name = CAPICOM_ENCRYPTION_ALGORITHM_3DES; pEnvelopedData -> Algorithm -> KeyLength = CAPICOM_ENCRYPTION_KEY_LENGTH_MAXIMUM; // 设置接收者证书(公钥) // 1.访问证书库 HRESULT retCode = pStore -> Open(CAPICOM_CURRENT_USER_STORE, CAPICOM_MY_STORE, CAPICOM_STORE_OPEN_READ_ONLY); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not open certStore! " )); } // 2.获取接收者证书 ICertificates2Ptr pReceiverCerts = ((ICertificates2Ptr) pStore -> Certificates) -> Find(CAPICOM_CERTIFICATE_FIND_SUBJECT_NAME, L " lny " , FALSE); if (pReceiverCerts == NULL || pReceiverCerts -> Count < 1 ) { CancelByError( 0 , _T( " Can not find receiver certificate! " )); } pEnvelopedData-> Recipients -> Add((ICertificatePtr) pReceiverCerts -> GetItem( 1 ).pdispVal); // 证书加密 _bstr_t strCryptedStr = pEnvelopedData -> Encrypt(CAPICOM_ENCODE_BINARY); // 获取密文数据 BSTR encBStr = strCryptedStr.GetBSTR(); BYTE * encStr = NULL; DWORD encSize = 0 ; getBSTRByte(encBStr, encStr, encSize); SysFreeString(encBStr); // 输出 showData(encStr, encSize); if (outFileName != NULL) { writeFile(outFileName, encStr, encSize); } } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbOrgData != NULL) delete [] pbOrgData; SysFreeString(orgBStr); pStore.Release(); pEnvelopedData.Release(); }
//
证书解密
void
CertDecryptData(LPCSTR inFileName, LPCSTR outFileName)
{ // 准备原始数据 DWORD cbOrgData = 0 ; BYTE * pbOrgData = NULL; prepareData(NULL, 0 , inFileName, pbOrgData, cbOrgData); // 创建签名数据对象 IEnvelopedDataPtr pEnvelopedData(__uuidof(EnvelopedData)); try { // 证书解密 HRESULT retCode = pEnvelopedData -> Decrypt(( char * )pbOrgData); if (FAILED(retCode)) { CancelByError(retCode, _T( " Can not decrypt data! " )); } // 获取原文数据 BSTR orgBStr = pEnvelopedData -> Content.GetBSTR(); BYTE * orgStr = NULL; DWORD orgSize = 0 ; getBSTRByte(orgBStr, orgStr, orgSize); SysFreeString(orgBStr); // 输出 showData(orgStr, orgSize); if (outFileName != NULL) { writeFile(outFileName, orgStr, orgSize); } } catch (_com_error e) { // 转换宽字符错误信息为多字节错误信息串 _bstr_t strErrMesg(e.ErrorMessage()); printf( " [%#x]:COM:%s.\n " , e.Error(), ( char * )strErrMesg); } catch (HRESULT errCode) { _tprintf(_T( " [%#x]:CAPICOM error. \n " ), errCode); } catch ( ) { _tprintf(_T( " Unknown error. \n " )); } // 清理 if (pbOrgData != NULL) delete [] pbOrgData; pEnvelopedData.Release(); }
int
_tmain(
int
argc, _TCHAR
*
argv[])
{ CoInitialize( 0 ); // BASE64 // Base64Encode((BYTE*)"123456789012345678", 15, NULL, "c:\\li.base64"); // Base64Decode(NULL, 0, "c:\\li.base64", "c:\\li.org"); // HASH // hashSHA1((BYTE*)"1234567890", 10, NULL, "c:\\li.sha1"); // hashSHA1(NULL, 0, "c:\\li.txt", "c:\\li.sha1"); // Encrypt & Decrypt // DESEncrypt((BYTE*)"12345678", (BYTE*)"1234567890\x00 12345", 15, NULL, "c:\\li.des"); // DESDecrypt((BYTE*)"12345678", NULL, 0, "c:\\li.des", "c:\\1.org"); // DESEncryptBin((BYTE*)"12345678", (BYTE*)"123456789012345", 15, NULL, "c:\\li.des"); // DESDecryptBin((BYTE*)"12345678", NULL, 0, "c:\\li.des", "c:\\1.org"); // CertStore & Cert // viewSystemCertStore(L"MY"); // CAPICOM_MY_STORE // viewSystemCertStore(L"CA"); // CAPICOM_CA_STORE // viewSystemCertStore(L"ROOT"); // CAPICOM_ROOT_STORE // viewSystemCertStore(L"AddressBook"); // CAPICOM_OTHER_STORE // viewCrtCertStore("c:\\cfcaT.p7b"); // viewCrtCertStore("c:\\ca\\certs\\lny.crt"); // viewPfxCertStore("c:\\ca\\lny.pfx", "welcome2008"); // TACHED SignData // callSignedData((BYTE*)"123456789012345", 15, NULL, FALSE, "c:\\li.tch.sig"); // VerifySignedData("c:\\li.tch.sig"); // DETACHED SignData // callSignedData((BYTE*)"1234567890", 10, NULL, TRUE, "c:\\li.detch.sig"); // VerifyDetachedSignedData((BYTE*) "1234567890", 10, NULL, "c:\\li.detch.sig"); // Cert Encrypt & Decrypt // CertEncryptData((BYTE*)"1234567890", 10, NULL, "c:\\li.enc"); // CertDecryptData("c:\\li.enc", "c:\\li.org"); CoUninitialize(); pause(); return 0 ; }
/** ================================================================================ About BSTR BSTR是"Basic STRing"的简称,是微软在COM/OLE中定义的标准字符串数据类型。 定义在wtypes.h文件中: typedef wchar_t WCHAR; typedef WCHAR OLECHAR; typedef OLECHAR __RPC_FAR * BSTR; COM字符(wchar_t)使用16bit,因此可以支持各种code pages,包括Unicode。 Windows系统可以简单理解为OLECHAR使用的就是Unicode 。 OLECHAR串与单字节字符串很类似,是一个以NULL(\x0\x0)结尾的buffer。 使用以NULL结尾字符串在COM component间传递不太方便, 因此,标准的BSTR是一个有长度前缀和NULL结束符的OLECHAR数组。 BSTR的前4字节是一个表示字符串长度的前缀,其值是不含NULL的字符串字节数。 BSTR和OLECHAR的交换可以使用COM提供了两个BSTR分配用的API: SysAllocString / SysReallocString。 函数返回的指针指向BSTR的第一个字符,而不是BSTR在内存的第一个字节,即去掉前缀。 使用BSTR一定要注意释放该对象。SysFreeString() _bstr_t是C++对BSTR的封装,VC中是为了兼容BSTR类型而增加的,也为实现LPCSTR与BSTR转换。 ================================================== BSTR转换成char* 方法一,使用ConvertBSTRToString。 #pragma comment(lib, 'comsupp.lib') BSTR bstrText = ::SysAllocString(L"Test"); char* p = _com_util::ConvertBSTRToString(bstrText); SysFreeString(bstrText); // 用完释放 delete[] lpszText2; 方法二,使用_bstr_t的赋值运算符重载。 _bstr_t b = bstrText; char* lpszText2 = b; ------------------------- char*转换成BSTR 方法一,使用SysAllocString等API函数。 BSTR bstrText = ::SysAllocString(L'Test'); BSTR bstrText = ::SysAllocStringLen(L'Test',4); BSTR bstrText = ::SysAllocStringByteLen('Test',4); 方法二,使用COleVariant或_variant_t。 COleVariant strVar('This is a test'); _variant_t strVar('This is a test'); BSTR bstrText = strVar.bstrVal; 方法三,使用_bstr_t,这是一种最简单的方法。 BSTR bstrText = _bstr_t('This is a test'); 方法四,使用CComBSTR。例如: BSTR bstrText = CComBSTR('This is a test'); 或 CComBSTR bstr('This is a test'); BSTR bstrText = bstr.m_str; 方法五,使用ConvertStringToBSTR。例如: char* lpszText = 'Test'; BSTR bstrText = _com_util::ConvertStringToBSTR(lpszText); ===================================================================================* */