使用MS CryptoAPI保存/恢复证书会使附加的私钥无效

时间:2011-04-21 08:30:48

标签: windows winapi cryptography cryptoapi mscapi

我编写了一个程序,该程序应该使用Windows Crypto API保存和恢复用户证书。我的印象是它工作正常,但现在用户抱怨说,在证书恢复后,附加到证书的私钥无效。

我使用以下方式保存证书:

HCERTSTORE hCertStore =
    CertOpenStore(CERT_STORE_PROV_PHYSICAL_W,
    0,
    NULL,
    CERT_SYSTEM_STORE_CURRENT_USER |
    CERT_STORE_OPEN_EXISTING_FLAG |
    CERT_STORE_READONLY_FLAG |
    CERT_STORE_UPDATE_KEYID_FLAG,
    (PVOID) storeName.c_str());

然后是:

if (!CertSaveStore(hCertStore,
    0,
    CERT_STORE_SAVE_AS_STORE,
    CERT_STORE_SAVE_TO_FILENAME,
    (PVOID) saveFile.c_str(),
    0))

我知道CERT_STORE_SAVE_AS_STORE标志应该意味着整个证书应该被序列化,包括私钥。虽然我注意到MSDN说:

  

“CERT_KEY_CONTEXT_PROP_ID属性   和相关的   CERT_KEY_PROV_HANDLE_PROP_ID和   CERT_KEY_SPEC_PROP_ID值不是   保存到序列化商店。“

..我承认,我真的不明白。

当我恢复证书时,我使用CertFindCertificateInStore()来查看证书是否已经存在,并且只有在我不这样做时才会这样做:

bOK = CertAddCertificateContextToStore(
    hDestinationStore,
    pCertContext,
    CERT_STORE_ADD_USE_EXISTING,
    NULL);

要添加证书...所以我的问题是,为什么不能保留私钥?我错过了什么吗?

1 个答案:

答案 0 :(得分:4)

你使用错误的CryptoAPI。您应该使用PFXExportCertStoreExPFXImportCertStore代替。

更新:这些功能很常见。您无法从SmartCard导出证书或其他不可导出的证书。函数中的BLOG不再是PFX文件的包含。例如,从PFX文件导入证书应执行以下操作:

  1. 打开PFX文件并读取内存中的完整包含内容。您当然可以使用文件映射。
  2. 您可以选择使用PFXIsPFXBlob函数来验证文件是否确实包含与PFX文件相对应的文件。
  3. 您使用PFXImportCertStore打开BLOB(PFX)作为源证书存储区。
  4. 您可以使用CertOpenStore或其他功能打开要从PFX文件保存证书的目标证书存储区。
  5. 使用CertEnumCertificatesInStore枚举源证书存储区(PFX)中的证书,并使用所有证书使用CertAddCertificateContextToStore将证书从源证书存储区添加到目标证书存储区。具有私钥的证书将使用私钥导入。
  6. 您使用CertCloseStore关闭两个已打开的商店。