**************************************************************************************************
(1) 利用PFXImportCertStore函数将P12结构证书导入一个临时的内存型证书库,注意要用
CRYPT_EXPORTABLE 标志,获得该库的句柄hImportStore。
(3) 利用CertFindCertificateInSto
(4) 利用上面得到的证书上文pCertContext,通过CryptAcquireCertificateP
(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标志将证书写进对应的密钥容器。
**************************************************************************************************
网上找到的代码貌似都不太靠谱,于是自己写了一个,下面只公布主要的函数
- void
CImportPFXDlg::ImportPFX(LPCTSTR PFX_FILE, LPCTSTR PFX_PASS) - {
-
//打开文件 -
HANDLE hFile = NULL; -
hFile = ::CreateFile(PFX_FILE, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); -
if (hFile == INVALID_HANDLE_VALUE) -
{ -
::AfxMessageBox(_T("CreateFile Fail!")); -
return; -
} -
-
//分配内存 -
DWORD dwSize = ::GetFileSize(hFile, NULL); -
BYTE *pP12 = NULL; -
if (!(pP12 = new BYTE[dwSize])) -
{ -
::CloseHandle(hFile); -
::AfxMessageBox(_T("new pP12 Fail!")); -
return; -
} -
-
//读取证书内容 -
DWORD dwRead = 0; -
if (!::ReadFile(hFile, pP12, dwSize, &dwRead, NULL)) -
{ -
::CloseHandle(hFile); -
::AfxMessageBox(_T("ReadFile Fail!")); -
return; -
} -
-
//关闭文件 -
::CloseHandle(hFile); -
-
//生成结构体 -
CRYPT_DATA_BLOB CDB; -
CDB.cbData = dwSize; -
CDB.pbData = pP12; -
-
//将证书导入临时证书库 -
HCERTSTORE hStore = NULL; -
if (!(hStore = PFXImportCertStore(&CDB, PFX_PASS, CRYPT_EXPORTABLE))) -
{ -
delete pP12; pP12 = NULL; -
::AfxMessageBox(_T("PFXImportCertStore Fail!")); -
return; -
} -
delete pP12; pP12 = NULL; -
-
//枚举临时证书库中导入的证书 -
PCCERT_CONTEXT pCertContext = NULL; -
HCRYPTPROV hCertProv = NULL; -
HCRYPTKEY hKey = NULL; -
BYTE *pPK = NULL; -
HCRYPTKEY hPrvKey = NULL; -
HCRYPTPROV hProv = NULL; -
while (pCertContext = CertEnumCertificatesInSt ore(hStore, pCertContext)) -
{ -
//对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书) -
//if (!CertCompareCertificateNa me(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, -
// &pCertContext->pCertInfo->Issuer, -
// &pCertContext->pCertInfo->Subject)) -
{ -
//获取私钥临时 CSP 句柄 -
DWORD dwKeySpec = 0; -
if (!CryptAcquireCertificateP rivateKey(pCertContext, -
CRYPT_ACQUIRE_COMPARE_KEY_FLAG, -
NULL, -
&hCertProv, -
&dwKeySpec, -
NULL)) -
{ -
DWORD dwRet = GetLastError(); -
::AfxMessageBox(_T("CryptAcquireCertificateP rivateKey Fail!")); -
goto cleanup; -
} -
-
//获取密钥对 -
if (!CryptGetUserKey(hCertProv, ((m_cmbCertType.GetCurSel() == 0) ? AT_KEYEXCHANGE : AT_SIGNATURE), &hKey)) -
{ -
DWORD dwRet = GetLastError(); -
::AfxMessageBox(_T("CryptGetUserKey Fail!")); -
goto cleanup; -
} -
-
//获取私钥长度 -
DWORD dwPKSize = 0; -
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, NULL, &dwPKSize)) -
{ -
DWORD dwRet = GetLastError(); -
::AfxMessageBox(_T("CryptExportKey dwPKSize Fail!")); -
goto cleanup; -
} -
-
//分配内存 -
if (!(pPK = new BYTE[dwPKSize])) -
{ -
DWORD dwRet = GetLastError(); -
::AfxMessageBox(_T("new pPK Fail!")); -
goto cleanup; -
} -
-
//导出私钥 -
if (!CryptExportKey(hKey, NULL, PRIVATEKEYBLOB, 0, pPK, &dwPKSize)) -
{ -
DWORD dwRet = GetLastError(); -
::AfxMessageBox(_T("CryptExportKey pPK Fail!")); -
goto cleanup; -
} -
-
//获取 UKEY 的 CSP 句柄 -
-
//获取密钥容器名称 -
CString csContainer; -
if (m_cmbContainer.GetCurSel() == 0) //新建密钥容器 -
{ -
m_edtContainer.GetWindowText(csContainer); -
if (!CryptAcquireContext(&hProv, (LPCTSTR)csContainer, CSP_NAME, PROV_RSA_FULL, CRYPT_NEWKEYSET)) -
{ -
DWORD dwRst = ::GetLastError(); -
::AfxMessageBox(_T("CryptAcquireContext m_edtContainer Fail!")); -
goto cleanup; -
} -
} -
else //证书导入现有容器 -
{ -
m_cmbContainer.GetWindowText(csContainer); -
if (!CryptAcquireContext(&hProv, (LPCTSTR)csContainer, CSP_NAME, PROV_RSA_FULL, 0)) -
{ -
DWORD dwRst = ::GetLastError(); -
::AfxMessageBox(_T("CryptAcquireContext m_cmbContainer Fail!")); -
goto cleanup; -
} -
} -
-
//将私钥导入到 CSP,并获取其句柄 -
if (!CryptImportKey(hProv, pPK, dwPKSize, NULL, 0, &hPrvKey)) -
{ -
DWORD dwRst = ::GetLastError(); -
::AfxMessageBox(_T("CryptImportKey Fail!")); -
goto cleanup; -
} -
-
//将证书导入到密钥容器 -
if (!CryptSetKeyParam(hPrvKey, KP_CERTIFICATE, pCertContext->pbCertEncoded, 0)) -
{ -
DWORD dwRst = ::GetLastError(); -
::AfxMessageBox(_T("CryptSetKeyParam Fail!")); -
goto cleanup; -
} -
-
break; -
} -
} -
- cleanup:
-
-
//销毁私钥句柄 -
CryptDestroyKey(hPrvKey); -
-
//关闭 UKEY 的 CSP 句柄 -
CryptReleaseContext(hProv, 0); -
-
//释放私钥内存 -
delete pPK; pPK = NULL; -
-
//销毁密钥对句柄 -
CryptDestroyKey(hKey); -
-
//释放证书句柄 -
CertFreeCertificateConte xt(pCertContext); -
-
//关闭临时证书库 -
CertCloseStore(hStore, 0); - }