[C++]将PFX证书导入USB-KEY

8 篇文章 0 订阅

**************************************************************************************************

(1) 利用PFXImportCertStore函数将P12结构证书导入一个临时的内存型证书库,注意要用

CRYPT_EXPORTABLE 标志,获得该库的句柄hImportStore。
(3) 利用CertFindCertificateInStore函数获得hImportStore证书库中的证书上下文pCertContext。
(4) 利用上面得到的证书上文pCertContext,通过CryptAcquireCertificatePrivateKey函数获得临时CSP句柄 hCryptProv,证书对应私钥的类型dwKeySpec。
(5) 利用临时CSP句柄hCryptProv,私钥的类型dwKeySpec,通过CryptGetUserKey获得证书对应的私钥句柄hUserKey。
(6) 利用私钥句柄hUserKey,通过CryptExportKey将私钥以PRIVATEKEYBLOB的形式导出来,获得私钥的blob和长度。
(7) 通过CryptAcquireContext函数,创建密钥容器并获得USBKey CSP的句柄hProv。
(8) 利用获得hProv和上面获得的私钥blob和长度,通过CryptImportKey函数将私钥导进USBKey CSP中,并返回私钥句柄hKey。
(9) 利用私钥句柄hKey,和前面获得的证书上下文pCertContext的内容,通过CryptSetKeyParam函 数,KP_CERTIFICATE标志将证书写进对应的密钥容器。

 

**************************************************************************************************

网上找到的代码貌似都不太靠谱,于是自己写了一个,下面只公布主要的函数

 

 
  1. void CImportPFXDlg::ImportPFX(LPCTSTR PFX_FILE, LPCTSTR PFX_PASS)  
  2.  
  3.     //打开文件   
  4.     HANDLE hFile NULL;  
  5.     hFile ::CreateFile(PFX_FILE, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);  
  6.     if (hFile == INVALID_HANDLE_VALUE)  
  7.      
  8.         ::AfxMessageBox(_T("CreateFile Fail!"));  
  9.         return 
  10.      
  11.   
  12.     //分配内存   
  13.     DWORD dwSize ::GetFileSize(hFile, NULL);  
  14.     BYTE *pP12 NULL;  
  15.     if (!(pP12 new BYTE[dwSize]))  
  16.      
  17.         ::CloseHandle(hFile);  
  18.         ::AfxMessageBox(_T("new pP12 Fail!"));  
  19.         return 
  20.      
  21.   
  22.     //读取证书内容   
  23.     DWORD dwRead 0;  
  24.     if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL))  
  25.      
  26.         ::CloseHandle(hFile);  
  27.         ::AfxMessageBox(_T("ReadFile Fail!"));  
  28.         return 
  29.      
  30.   
  31.     //关闭文件   
  32.     ::CloseHandle(hFile);  
  33.   
  34.     //生成结构体   
  35.     CRYPT_DATA_BLOB CDB;  
  36.     CDB.cbData dwSize;  
  37.     CDB.pbData pP12;  
  38.   
  39.     //将证书导入临时证书库   
  40.     HCERTSTORE hStore NULL;  
  41.     if (!(hStore PFXImportCertStore(&CDB, PFX_PASS, CRYPT_EXPORTABLE)))  
  42.      
  43.         delete pP12; pP12 NULL;  
  44.         ::AfxMessageBox(_T("PFXImportCertStore Fail!"));  
  45.         return 
  46.      
  47.     delete pP12; pP12 NULL;  
  48.   
  49.     //枚举临时证书库中导入的证书   
  50.     PCCERT_CONTEXT pCertContext NULL;  
  51.     HCRYPTPROV hCertProv NULL;  
  52.     HCRYPTKEY hKey NULL;  
  53.     BYTE *pPK NULL;  
  54.     HCRYPTKEY hPrvKey NULL;  
  55.     HCRYPTPROV hProv NULL;  
  56.     while (pCertContext CertEnumCertificatesInStore(hStore, pCertContext))  
  57.      
  58.         //对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)   
  59.         //if (!CertCompareCertificateName(X509_ASN_ENCODING PKCS_7_ASN_ENCODING,   
  60.         //                              &pCertContext->pCertInfo->Issuer,   
  61.         //                              &pCertContext->pCertInfo->Subject))   
  62.          
  63.             //获取私钥临时 CSP 句柄   
  64.             DWORD dwKeySpec 0;  
  65.             if (!CryptAcquireCertificatePrivateKey(pCertContext,  
  66.                                                    CRYPT_ACQUIRE_COMPARE_KEY_FLAG,  
  67.                                                    NULL,  
  68.                                                    &hCertProv,  
  69.                                                    &dwKeySpec,  
  70.                                                    NULL))  
  71.              
  72.                 DWORD dwRet GetLastError();  
  73.                 ::AfxMessageBox(_T("CryptAcquireCertificatePrivateKey Fail!"));  
  74.                 goto cleanup;  
  75.              
  76.   
  77.             //获取密钥对   
  78.             if (!CryptGetUserKey(hCertProv, ((m_cmbCertType.GetCurSel() == 0) AT_KEYEXCHANGE AT_SIGNATURE), &hKey))  
  79.              
  80.                 DWORD dwRet GetLastError();  
  81.                 ::AfxMessageBox(_T("CryptGetUserKey Fail!"));  
  82.                 goto cleanup;  
  83.              
  84.   
  85.             //获取私钥长度   
  86.             DWORD dwPKSize 0;  
  87.             if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize))  
  88.              
  89.                 DWORD dwRet GetLastError();  
  90.                 ::AfxMessageBox(_T("CryptExportKey dwPKSize Fail!"));  
  91.                 goto cleanup;  
  92.              
  93.   
  94.             //分配内存   
  95.             if (!(pPK new BYTE[dwPKSize]))  
  96.              
  97.                 DWORD dwRet GetLastError();  
  98.                 ::AfxMessageBox(_T("new pPK Fail!"));  
  99.                 goto cleanup;  
  100.              
  101.   
  102.             //导出私钥   
  103.             if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize))  
  104.              
  105.                 DWORD dwRet GetLastError();  
  106.                 ::AfxMessageBox(_T("CryptExportKey pPK Fail!"));  
  107.                 goto cleanup;  
  108.              
  109.   
  110.             //获取 UKEY 的 CSP 句柄   
  111.               
  112.             //获取密钥容器名称   
  113.             CString csContainer;  
  114.             if (m_cmbContainer.GetCurSel() == 0) //新建密钥容器   
  115.              
  116.                 m_edtContainer.GetWindowText(csContainer);  
  117.                 if (!CryptAcquireContext(&hProv, (LPCTSTR)csContainer, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET))  
  118.                  
  119.                     DWORD dwRst ::GetLastError();  
  120.                     ::AfxMessageBox(_T("CryptAcquireContext m_edtContainer Fail!"));  
  121.                     goto cleanup;  
  122.                  
  123.              
  124.             else //证书导入现有容器   
  125.              
  126.                 m_cmbContainer.GetWindowText(csContainer);  
  127.                 if (!CryptAcquireContext(&hProv, (LPCTSTR)csContainer, CSP_NAME, PROV_RSA_FULL, 0))  
  128.                  
  129.                     DWORD dwRst ::GetLastError();  
  130.                     ::AfxMessageBox(_T("CryptAcquireContext m_cmbContainer Fail!"));  
  131.                     goto cleanup;  
  132.                  
  133.              
  134.   
  135.             //将私钥导入到 CSP,并获取其句柄   
  136.             if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey))  
  137.              
  138.                 DWORD dwRst ::GetLastError();  
  139.                 ::AfxMessageBox(_T("CryptImportKey Fail!"));  
  140.                 goto cleanup;  
  141.              
  142.   
  143.             //将证书导入到密钥容器   
  144.             if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0))  
  145.              
  146.                 DWORD dwRst ::GetLastError();  
  147.                 ::AfxMessageBox(_T("CryptSetKeyParam Fail!"));  
  148.                 goto cleanup;  
  149.              
  150.   
  151.             break 
  152.          
  153.      
  154.   
  155. cleanup:  
  156.   
  157.     //销毁私钥句柄   
  158.     CryptDestroyKey(hPrvKey);  
  159.   
  160.     //关闭 UKEY 的 CSP 句柄   
  161.     CryptReleaseContext(hProv, 0);  
  162.   
  163.     //释放私钥内存   
  164.     delete pPK; pPK NULL;  
  165.   
  166.     //销毁密钥对句柄   
  167.     CryptDestroyKey(hKey);  
  168.   
  169.     //释放证书句柄   
  170.     CertFreeCertificateContext(pCertContext);  
  171.   
  172.     //关闭临时证书库   
  173.     CertCloseStore(hStore, 0);  
  174.  
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值