将PFX证书导入USB-KEY

来源:互联网 发布:网络暴力 电影 2011 编辑:程序博客网 时间:2024/06/03 23:42

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

(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(LPCTSTRPFX_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("CreateFileFail!"));
  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("newpP12 Fail!"));
  18. return;
  19. }
  20. //读取证书内容
  21. DWORD dwRead = 0;
  22. if (!::ReadFile(hFile,pP12, dwSize, &dwRead, NULL))
  23. {
  24. ::CloseHandle(hFile);
  25. ::AfxMessageBox(_T("ReadFileFail!"));
  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. deletepP12; pP12 = NULL;
  39. ::AfxMessageBox(_T("PFXImportCertStoreFail!"));
  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. DWORDdwKeySpec = 0;
  59. if(!CryptAcquireCertificatePrivateKey(pCertContext,
  60. CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
  61. NULL,
  62. &hCertProv,
  63. &dwKeySpec,
  64. NULL))
  65. {
  66. DWORDdwRet = GetLastError();
  67. ::AfxMessageBox(_T("CryptAcquireCertificatePrivateKeyFail!"));
  68. gotocleanup;
  69. }
  70. //获取密钥对
  71. if(!CryptGetUserKey(hCertProv, ((m_cmbCertType.GetCurSel() == 0)? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey))
  72. {
  73. DWORDdwRet = GetLastError();
  74. ::AfxMessageBox(_T("CryptGetUserKeyFail!"));
  75. gotocleanup;
  76. }
  77. //获取私钥长度
  78. DWORDdwPKSize = 0;
  79. if(!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize))
  80. {
  81. DWORDdwRet = GetLastError();
  82. ::AfxMessageBox(_T("CryptExportKeydwPKSize Fail!"));
  83. gotocleanup;
  84. }
  85. //分配内存
  86. if(!(pPK = new BYTE[dwPKSize]))
  87. {
  88. DWORDdwRet = GetLastError();
  89. ::AfxMessageBox(_T("newpPK Fail!"));
  90. gotocleanup;
  91. }
  92. //导出私钥
  93. if(!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize))
  94. {
  95. DWORDdwRet = GetLastError();
  96. ::AfxMessageBox(_T("CryptExportKeypPK Fail!"));
  97. gotocleanup;
  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. DWORDdwRst = ::GetLastError();
  108. ::AfxMessageBox(_T("CryptAcquireContextm_edtContainer Fail!"));
  109. gotocleanup;
  110. }
  111. }
  112. else//证书导入现有容器
  113. {
  114. m_cmbContainer.GetWindowText(csContainer);
  115. if(!CryptAcquireContext(&hProv, (LPCTSTR)csContainer,CSP_NAME, PROV_RSA_FULL, 0))
  116. {
  117. DWORDdwRst = ::GetLastError();
  118. ::AfxMessageBox(_T("CryptAcquireContextm_cmbContainer Fail!"));
  119. gotocleanup;
  120. }
  121. }
  122. //将私钥导入到CSP,并获取其句柄
  123. if(!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey))
  124. {
  125. DWORDdwRst = ::GetLastError();
  126. ::AfxMessageBox(_T("CryptImportKeyFail!"));
  127. gotocleanup;
  128. }
  129. //将证书导入到密钥容器
  130. if(!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded,0))
  131. {
  132. DWORDdwRst = ::GetLastError();
  133. ::AfxMessageBox(_T("CryptSetKeyParamFail!"));
  134. gotocleanup;
  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. }