您的位置:首页 > 其它

将PFX证书导入USB-KEY

2014-09-23 14:52 549 查看
**************************************************************************************************

(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标志将证书写进对应的密钥容器。

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

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



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 = CertEnumCertificatesInStore(hStore, pCertContext))
{
//对比“颁发给”和“颁发者”是否一致(对于根证书是一致的,不要导入根证书)
//if (!CertCompareCertificateName(X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
// &pCertContext->pCertInfo->Issuer,
// &pCertContext->pCertInfo->Subject))
{
//获取私钥临时 CSP 句柄
DWORD dwKeySpec = 0;
if (!CryptAcquireCertificatePrivateKey(pCertContext,
CRYPT_ACQUIRE_COMPARE_KEY_FLAG,
NULL,
&hCertProv,
&dwKeySpec,
NULL))
{
DWORD dwRet = GetLastError();
::AfxMessageBox(_T("CryptAcquireCertificatePrivateKey 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);

//释放证书句柄
CertFreeCertificateContext(pCertContext);

//关闭临时证书库
CertCloseStore(hStore, 0);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: