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

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

2012-07-20 10:11 302 查看
**************************************************************************************************

(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);  

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