为什么证书库中的证书没有私钥 属性

Why cert in certificate store doesn't have private key property

我试图通过 CNG API 从证书库中的证书中获取 EC 私钥。首先,我调用 CertGetCertificateContextProperty()CERT_KEY_CONTEXT_PROP_ID 属性 获取私钥句柄,但它总是 return 错误。我确定证书有私钥。

代码:

    wchar_t                 wMY_CERT_NAME[100];
    HCERTSTORE              hCertStore = NULL;
    PCCERT_CONTEXT          pSignerCert = NULL;
    NCRYPT_KEY_HANDLE       hKey = NULL;
    const int buffsize = 4999;
    DWORD len = buffsize;
    char buff[buffsize];

    // Open the certificate store.
    if (!(hCertStore = CertOpenStore(
        CERT_STORE_PROV_SYSTEM,
        0,
        NULL,
        CERT_SYSTEM_STORE_CURRENT_USER,
        CERT_STORE_NAME)))
    {
        MyHandleError(const_cast<LPTSTR>("The MY store could not be opened."));
    }

    swprintf(wMY_CERT_NAME, 100, L"%hs", MY_CERT_NAME);

    if (pSignerCert = CertFindCertificateInStore(
        hCertStore,
        MY_ENCODING_TYPE,
        0,
        CERT_FIND_SUBJECT_STR,
        wMY_CERT_NAME,
        NULL))
    {
        //continue
    }

    if (CertGetCertificateContextProperty(
        pSignerCert,
        CERT_KEY_CONTEXT_PROP_ID,
        buff,
        &len))
    {
        auto ckc = (CERT_KEY_CONTEXT *)buff;
        hKey = ckc->hNCryptKey;
    }
    else {
        wprintf(L"**** GetCertContextProperty failed.\n");
    }

然后,我尝试执行相同的步骤,但从 this page 之类的 .pfx 文件中读取。 return true 成功获取私钥。为什么证书库中的证书没有 CERT_KEY_CONTEXT_PROP_ID 属性?

证书是签名的 public 密钥,它们不包含私钥。大多数混淆源于不正确理解密码学的人偶然误用和混淆术语和概念。

例如,.cert .cer .crt 可以包含 keys and/or certificates.但是,严格来说 certificate 签名的 public 密钥 .

根据我的经验,如果证书 UI 表明您有私钥,那么您应该能够打开并使用该密钥。它不算出口。你试过了吗CryptAcquireCertificatePrivateKey

正如 Woodstock 所写,私钥不是证书的一部分,甚至不与证书存储在一起。私钥存储在别处。然而,public密钥是证书的一部分,代码可以扫描本地密钥库寻找与证书具有相同算法的私钥,并且匹配证书中的 public 密钥。

其中的一个问题是 "strong key protection" 标志。如果已设置,任何尝试获取私钥的尝试都会弹出提示。这就是为什么 CryptAcquireCertificatePrivateKey 有一个父 window 句柄参数,还有一个 "silent" 标志。据我所知,除非重新创建密钥,否则无法删除它。