您的位置:首页 > 编程语言 > C语言/C++

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

2011-06-20 16:41 411 查看
网上找到的代码貌似都不太靠谱,于是自己写了一个,下面只公布主要的函数

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