如何获取先前导入到 windows Cert: store(在 Delphi 中)的 public 证书的 CNG 密钥句柄?

How to get a CNG key handle to a public certificate previously imported to windows Cert: store (in Delphi)?

我需要使用 CNG 验证消息签名 (RSA)。唯一的问题是如果我有public 证书存储在 windows certs (Cert:\CurrentUser\My)。 我正在使用

NCryptOpenStorageProvider({out}hProv, MS_KEY_STORAGE_PROVIDER, 0)

我尝试使用

获取public键句柄
NCryptOpenKey(hProv, {out}hKey, PWideChar('my.test.com'), AT_KEYEXCHANGE, 0) 

但似乎 NCryptOpenKey() 只能打开也有 私钥.

的证书

我也在看 BCryptImportKeyPair() 但这需要在 BCRYPT_RSAKEY_BLOB[=42= 中有 public 键] 我不知道如何实现的结构。

我看到的最后一个函数是 NCryptImportKey() 但这又只适用于 私钥.

有人知道如何使用 CNG 获取 public 密钥句柄吗? 我在文件 (cer/pem) 中有 public 密钥,我将它导入到 windows Cert: 商店,但如果你知道如何直接从文件加载它到 CNG 密钥handle我也很高兴

NCrypt* 函数使用存储在密钥存储提供程序中的持久密钥对。如果您在证书存储中导入证书并且此证书不包含私钥,则 public 密钥将不会保存在 KSP 中。
您可以使用函数 CryptImportPublicKeyInfoEx2 获取 BCRYPT_KEY_HANDLE.
C 中的示例代码:

HCERTSTORE hStore = nullptr;
    PCCERT_CONTEXT pCert = nullptr;
    BCRYPT_KEY_HANDLE hKey = nullptr;

    /* Open MY certificate store */
    hStore = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, NULL, CERT_SYSTEM_STORE_CURRENT_USER, L"MY");
    if (!hStore) {
        goto Exit;
    }

    /* Find your certificate in store. For example search by subject name */
    pCert = CertFindCertificateInStore(hStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_SUBJECT_STR, L"subject name", nullptr);
    if (!pCert) {
        goto Exit;
    }

    /* Or if you want to load certificate from file (assuming you read file to cert_data): 

        pCert = CertCreateCertificateContext(X509_ASN_ENCODING, cert_data, cert_size);

    */

    /* Now you can create BCRYPTKEY_HANDLE from your public key */
    if (!CryptImportPublicKeyInfoEx2(X509_ASN_ENCODING, &pCert->pCertInfo->SubjectPublicKeyInfo, 0, nullptr, &hKey)) {
        goto Exit;
    }

    /* Now you can verify signature with BCryptVerifySignature(hKey...) */


Exit:
    /* Don't forget to free handle after use */
    if (hKey) {
        BCryptDestroyKey(hKey);
    }
    if (pCert) {
        CertFreeCertificateContext(pCert);
    }
    if (hStore) {
        CertCloseStore(hStore, 0);
    }
    return 0;