如何将USBKey中的证书注册到Windows系统中、分享一个 证书 C++安装

USBKey 是一种 USB 接口的硬件设备。如坚石诚信的 ET199Auto ,内置 16 位国外进口高性能智能卡芯片,有一定的存储空间,可以存储用户的私钥以及数字证书,利用 USBKey内置的RSA 公私钥算法实现对用户身份的认证。由于用户私钥保存在 ET199Auto 中,同时智能卡可以很好的防止物理攻击 / 边频攻击等窃取手段,从而有效保证任何方式都无法读取 ET199Auto 中的私钥,因此保证了用户认证的安全性。

目前,USBKey已广泛应用在网上银行,网上办公,证券交易,网络游戏等众多系统中。那么USBKey又怎么与应用系统连接而进行身份认证的呢?实际上,USBKey中存储着代表用户身份的数字证书。

一张数字证书包括:证书信息+公钥+私钥,其中证书+公钥是可以公开的,私钥是在USBKey中,任何人都无法获取的。当USBKey插入计算机后,USBKey厂商提供的中间件程序会将证书信息注册到Windows系统中,应用系统中在认证时通过Windows系统找到用户证书该证书通过USBKey厂商的中间件找到USBKey中对应的私钥,然后在USBKey中使用私钥进行签名运算,将结果传给服务器认证。过程如下:

网银àWindows系统中用户证书àUSBKey中间件à私钥签名à服务器验证

本篇文章就介绍一下如何使用微软CAPI接口完成将USBKey中的证书注册到Windows系统中。


(1)        获取CSP句柄。

  1. CryptAcquireContext(  
  2. &hTokenProv,NULL,  
  3. “EnterSafe ET199Auto CSP V1.0”,   
  4. PROV_RSA_FULL,  
  5. NULL)  
CryptAcquireContext(
&hTokenProv,NULL,
“EnterSafe ET199Auto CSP V1.0”, 
PROV_RSA_FULL,
NULL)

(2)        获取USBKey内密钥句柄,这时要注意锁内密钥的类型是签名密钥(AT_SIGNATURE)或者交换密钥(AT_KEYEXCHANGE)。

  1. CryptGetUserKey(hTokenProv,AT_KEYEXCHANGE,&hKeyCAPI)  
CryptGetUserKey(hTokenProv,AT_KEYEXCHANGE,&hKeyCAPI)

(3)        获取证书数据(只是证书信息数据,不包括私钥),这时可以通过两次调用,先获取证书数据的长度,分配空间,然后再调用一次。

  1. CryptGetKeyParam(hKeyCAPI, KP_CERTIFICATE, pbCert, &dwCertLen, 0)  
CryptGetKeyParam(hKeyCAPI, KP_CERTIFICATE, pbCert, &dwCertLen, 0)

(4)        创建CERT_CONTEXT结构

  1. pCertContext = CertCreateCertificateContext(  
  2.                 PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,  
  3.                 pbCert,  
  4.                 dwCertLen)  
pCertContext = CertCreateCertificateContext(
                PKCS_7_ASN_ENCODING | X509_ASN_ENCODING,
                pbCert,
                dwCertLen)


  1. //+-------------------------------------------------------------------------  
  2. //  Certificate context.  
  3. //  
  4. //  A certificate context contains both the encoded and decoded representation  
  5. //  of a certificate. A certificate context returned by a cert store function  
  6. //  must be freed by calling the CertFreeCertificateContext function. The  
  7. //  CertDuplicateCertificateContext function can be called to make a duplicate  
  8. //  copy (which also must be freed by calling CertFreeCertificateContext).  
  9. //--------------------------------------------------------------------------  
  10. // certenrolls_begin -- CERT_CONTEXT  
  11. typedef struct _CERT_CONTEXT {  
  12.     DWORD                   dwCertEncodingType;  
  13.     BYTE                    *pbCertEncoded;  
  14.     DWORD                   cbCertEncoded;  
  15.     PCERT_INFO              pCertInfo;  
  16.     HCERTSTORE              hCertStore;  
  17. } CERT_CONTEXT, *PCERT_CONTEXT;  
  18. typedef const CERT_CONTEXT *PCCERT_CONTEXT;  
//+-------------------------------------------------------------------------
//  Certificate context.
//
//  A certificate context contains both the encoded and decoded representation
//  of a certificate. A certificate context returned by a cert store function
//  must be freed by calling the CertFreeCertificateContext function. The
//  CertDuplicateCertificateContext function can be called to make a duplicate
//  copy (which also must be freed by calling CertFreeCertificateContext).
//--------------------------------------------------------------------------
// certenrolls_begin -- CERT_CONTEXT
typedef struct _CERT_CONTEXT {
    DWORD                   dwCertEncodingType;
    BYTE                    *pbCertEncoded;
    DWORD                   cbCertEncoded;
    PCERT_INFO              pCertInfo;
    HCERTSTORE              hCertStore;
} CERT_CONTEXT, *PCERT_CONTEXT;
typedef const CERT_CONTEXT *PCCERT_CONTEXT;


(5)        打开MY存储区,这个就是Windows系统中“个人”证书存放的区域。

  1. hSysStore = CertOpenStore(  
  2. CERT_STORE_PROV_SYSTEM_REGISTRY,  
  3.         0,  
  4.         0,  
  5.         CERT_SYSTEM_STORE_CURRENT_USER,  
  6.         L"MY");  
hSysStore = CertOpenStore(
CERT_STORE_PROV_SYSTEM_REGISTRY,
        0,
        0,
        CERT_SYSTEM_STORE_CURRENT_USER,
        L"MY");

(6)        设置证书上下文属性。这时要先声明CRYPT_KEY_PROV_INFO结构

  1. CRYPT_KEY_PROV_INFO ckpi = {0};  
  2.   
  3.         ckpi.pwszProvName = L" EnterSafe ET199Auto CSP V1.0";  
  4.         ckpi.pwszContainerName = pbWideContainer;  
  5.         ckpi.dwProvType = PROV_RSA_FULL;  
  6.         ckpi.dwKeySpec = AT_KEYEXCHANGE;  
  7.         ckpi.dwFlags = CERT_KEY_CONTEXT_PROP_ID;  
  8.         ckpi.cProvParam = 0;  
  9.         ckpi.rgProvParam = NULL;  
  10.   
  11. CertSetCertificateContextProperty(  
  12. pCertContext,  
  13. CERT_KEY_PROV_INFO_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG,   
  14. &ckpi)  
CRYPT_KEY_PROV_INFO ckpi = {0};

        ckpi.pwszProvName = L" EnterSafe ET199Auto CSP V1.0";
        ckpi.pwszContainerName = pbWideContainer;
        ckpi.dwProvType = PROV_RSA_FULL;
        ckpi.dwKeySpec = AT_KEYEXCHANGE;
        ckpi.dwFlags = CERT_KEY_CONTEXT_PROP_ID;
        ckpi.cProvParam = 0;
        ckpi.rgProvParam = NULL;

CertSetCertificateContextProperty(
pCertContext,
CERT_KEY_PROV_INFO_PROP_ID, CERT_STORE_NO_CRYPT_RELEASE_FLAG, 
&ckpi)

(7)        将证书注册到Windows系统中。

  1. CertAddCertificateContextToStore(  
  2. hSysStore,  
  3.         pCertContext,  
  4.         CERT_STORE_ADD_REPLACE_EXISTING,  
  5.         NULL);  
CertAddCertificateContextToStore(
hSysStore,
        pCertContext,
        CERT_STORE_ADD_REPLACE_EXISTING,
        NULL);

(8)        释放CSP句柄。

  1. CryptReleaseContext(hTokenProv,0)  
CryptReleaseContext(hTokenProv,0)

通过上述步骤就可以将ET199Auto中的证书注册到Windows系统中了。我们可以在IEInternet选项内容证书个人下面查看到ET199Auto中的证书。

以上系转载,感谢原作者。


========================================================================

今天写了一个关于证书安装的程序,现在把主要代码分享出来!
注:
   在读取到证书文件,如果是 BASE64 文件,就需要通过 CryptStringToBinaryA 转化成 二进制,然后再CertCreateCertificateContext,才能成功,不然会 出现 CRYPT_E_ASN1_BADTAG 错误!

  1. #include "stdafx.h"  
  2. #include "CertImportx.h"  
  3.   
  4. #define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)  
  5.   
  6.   
  7. void CCertImport::PrintfError(DWORD err , LPCTSTR szError)  
  8. {  
  9.     if( err == 0 )  
  10.     {  
  11.         MessageBox(NULL,_T("安装成功!"),_T("证书安装"),MB_OK);  
  12.     }  
  13.     else  
  14.     {//  
  15.         MessageBox(NULL,_T("安装失败!"),_T("证书安装"),MB_OK);  
  16.     }  
  17. }  
  18.   
  19. // Global function for free handles...  
  20. void CCertImport::FreeHandles(HCERTSTORE hFileStore, PCCERT_CONTEXT pctx,     HCERTSTORE pfxStore, HCERTSTORE myStore )  
  21. {  
  22.   
  23.     if (myStore)  
  24.         CertCloseStore(myStore, 0);  
  25.   
  26.     if (pfxStore)  
  27.         CertCloseStore(pfxStore, CERT_CLOSE_STORE_FORCE_FLAG);  
  28.   
  29.     if(pctx)  
  30.         CertFreeCertificateContext(pctx);  
  31.   
  32.     if (hFileStore)  
  33.         CertCloseStore(hFileStore, 0);  
  34. }  
  35.   
  36. int CCertImport::ImportCACert()  
  37. {  
  38.     const char* pCert= "-----BEGIN CERTIFICATE-----\  
  39.                        MIIEXDCCA0SgAwIBAgIEOGO5ZjANBgkqhkiG9w0BAQUFADCBtDEUMBIGA1UEChML\  
  40.                        RW50cnVzdC5uZXQxQDA+BgNVBAsUN3d3dy5lbnRydXN0Lm5ldC9DUFNfMjA0OCBp\  
  41.                        bmNvcnAuIGJ5IHJlZi4gKGxpbWl0cyBsaWFiLikxJTAjBgNVBAsTHChjKSAxOTk5\  
  42.                        IEVudHJ1c3QubmV0IExpbWl0ZWQxMzAxBgNVBAMTKkVudHJ1c3QubmV0IENlcnRp\  
  43.                        ZmljYXRpb24gQXV0aG9yaXR5ICgyMDQ4KTAeFw05OTEyMjQxNzUwNTFaFw0xOTEy\  
  44.                        MjQxODIwNTFaMIG0MRQwEgYDVQQKEwtFbnRydXN0Lm5ldDFAMD4GA1UECxQ3d3d3\  
  45.                        LmVudHJ1c3QubmV0L0NQU18yMDQ4IGluY29ycC4gYnkgcmVmLiAobGltaXRzIGxp\  
  46.                        YWIuKTElMCMGA1UECxMcKGMpIDE5OTkgRW50cnVzdC5uZXQgTGltaXRlZDEzMDEG\  
  47.                        A1UEAxMqRW50cnVzdC5uZXQgQ2VydGlmaWNhdGlvbiBBdXRob3JpdHkgKDIwNDgp\  
  48.                        MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArU1LqRKGsuqjIAcVFmQq\  
  49.                        K0vRvwtKTY7tgHalZ7d4QMBzQshowNtTK91euHaYNZOLGp18EzoOH1u3Hs/lJBQe\  
  50.                        sYGpjX24zGtLA/ECDNyrpUAkAH90lKGdCCmziAv1h3edVc3kw37XamSrhRSGlVuX\  
  51.                        MlBvPci6Zgzj/L24ScF2iUkZ/cCovYmjZy/Gn7xxGWC4LeksyZB2ZnuU4q941mVT\  
  52.                        XTzWnLLPKQP5L6RQstRIzgUyVYr9smRMDuSYB3Xbf9+5CFVghTAp+XtIpGmG4zU/\  
  53.                        HoZdenoVve8AjhUiVBcAkCaTvA5JaJG/+EfTnZVCwQ5N328mz8MYIWJmQ3DW1cAH\  
  54.                        4QIDAQABo3QwcjARBglghkgBhvhCAQEEBAMCAAcwHwYDVR0jBBgwFoAUVeSB0RGA\  
  55.                        vtiJuQijMfmhJAkWuXAwHQYDVR0OBBYEFFXkgdERgL7YibkIozH5oSQJFrlwMB0G\  
  56.                        CSqGSIb2fQdBAAQQMA4bCFY1LjA6NC4wAwIEkDANBgkqhkiG9w0BAQUFAAOCAQEA\  
  57.                        WUesIYSKF8mciVMeuoCFGsY8Tj6xnLZ8xpJdGGQC49MGCBFhfGPjK50xA3B20qMo\  
  58.                        oPS7mmNz7W3lKtvtFKkrxjYR0CvrB4ul2p5cGZ1WEvVUKcgF7bISKo30Axv/55IQ\  
  59.                        h7A6tcOdBTcSo8f0FbnVpDkWm1M6I5HxqIKiaohowXkCIryqptau37AUX7iH0N18\  
  60.                        f3v/rxzP5tsHrV7bhZ3QKw0z2wTR5klAEyt2+z7pnIkPFc4YsIV4IU9rTw76NmfN\  
  61.                        B/L/CNDi3tm/Kq+4h4YhPATKt5Rof8886ZjXOP/swNlQ8C5LWK5Gb9Auw2DaclVy\  
  62.                        vUxFnmG6v4SBkgPR0ml8xQ==\  
  63.                        -----END CERTIFICATE-----";  
  64.   
  65.     BYTE pBinByte[8192]={0};  
  66.     unsigned long binBytes = 4096;  
  67.   
  68.     CryptStringToBinaryA( pCert , strlen(pCert) ,CRYPT_STRING_BASE64HEADER , pBinByte , &binBytes ,NULL,NULL);  
  69.   
  70.     return ImportCACert(pBinByte , binBytes );  
  71. }  
  72.   
  73. // This function imports a CA certificate...  
  74. int CCertImport::ImportCACert(LPCTSTR szFileName)  
  75. {  
  76.     HANDLE hfile = INVALID_HANDLE_VALUE;  
  77.   
  78.     BYTE pByte[4096] = {0} , pBinByte[8192]={0};  
  79.     unsigned long bytesRead = 0;  
  80.     unsigned long binBytes = 4096;  
  81.   
  82.     // Open it...  
  83.     hfile = CreateFile(szFileName, FILE_READ_DATA, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);  
  84.     if (INVALID_HANDLE_VALUE == hfile)  
  85.         return -1;  
  86.      
  87.     ReadFile( hfile , pByte, 4096, &bytesRead ,NULL );  
  88.     CloseHandle(hfile);  
  89.   
  90.     CryptStringToBinaryA( (LPCSTR)pByte , bytesRead ,CRYPT_STRING_BASE64HEADER , pBinByte , &binBytes ,NULL,NULL);  
  91.   
  92.     return ImportCACert(pBinByte , binBytes );  
  93. }  
  94.   
  95. int CCertImport::ImportCACert(BYTE* pBinByte , unsigned long binBytes)  
  96. {  
  97.     HCERTSTORE pfxStore = 0;  
  98.     HCERTSTORE myStore = 0;  
  99.     HCERTSTORE hFileStore = 0;  
  100.     PCCERT_CONTEXT pctx = NULL;  
  101.     DWORD err = 0;  
  102.   
  103.     pctx = CertCreateCertificateContext(MY_ENCODING_TYPE, (BYTE*)pBinByte , binBytes );  
  104.     if(pctx == NULL)  
  105.     {  
  106.         DWORD err = GetLastError();  
  107.         FreeHandles(hFileStore,pctx, pfxStore, myStore);     
  108.         PrintfError( err ,  _T("Error in 'CertCreateCertificateContext'") );  
  109.         return err;  
  110.     }  
  111.   
  112.     // we open the store for the CA  
  113.     hFileStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0, CERT_STORE_OPEN_EXISTING_FLAG | CERT_SYSTEM_STORE_LOCAL_MACHINE, L"Root" );  
  114.     if (!hFileStore)  
  115.     {  
  116.         DWORD err = GetLastError();  
  117.         FreeHandles(hFileStore,pctx, pfxStore, myStore);     
  118.         PrintfError( err ,  _T("Error in 'CertOpenStore'") );  
  119.         return err;  
  120.     }  
  121.   
  122.     if( !CertAddCertificateContextToStore(hFileStore, pctx, CERT_STORE_ADD_NEW, 0) )  
  123.     {  
  124.         err = GetLastError();  
  125.         if( CRYPT_E_EXISTS == err )  
  126.         {  
  127. //            if( AfxMessageBox("An equivalent previous personal certificate already exists. Overwrite ? (Yes/No)", MB_YESNO) == IDYES)  
  128.             {  
  129.                 if( !CertAddCertificateContextToStore(hFileStore, pctx , CERT_STORE_ADD_REPLACE_EXISTING, 0))  
  130.                 {  
  131.                     err = GetLastError();  
  132.                     FreeHandles(hFileStore,pctx, pfxStore, myStore);  
  133.                     PrintfError( err ,  _T("Error in 'CertAddCertificateContextToStore'") );                         
  134.                     return err;  
  135.                 }  
  136.             }  
  137.         }  
  138.         else  
  139.         {  
  140.             FreeHandles(hFileStore, pctx , pfxStore , myStore);  
  141.             PrintfError( err ,  _T("Error in 'CertAddCertificateContextToStore'") );  
  142.             return err;  
  143.         }  
  144.     }  
  145.     FreeHandles(hFileStore,pctx, pfxStore, myStore);  
  146.     PrintfError(0 , NULL) ;  
  147.     return 0;  
  148. }  
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值