将PFX证书导入USB-KEY

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值