Microsoft CNG - 使用 BCrypt 函数在内存中创建自签名证书

Microsoft CNG - Create a self signed certificate in memory using BCrypt functions

我正在使用 Microsoft CNG 密码术 API 并且正在尝试创建自签名证书。

我们有使用 CertCreateSelfSignCertificate method, combined with NCryptOpenStorageProvider and NCryptCreatePersistedKey 创建密钥对的现有代码。

我现在面临的问题是,上述组合创建了一个密钥,该密钥最终出现在 windows 加密存储中。我明确不想在那里存储密钥,我希望证书和私钥都在内存中,因为我计划将它们写入我们自己选择的 encrypted/protected 存储。

据我所知,BCrypt 函数系列是为内存使用而设计的,实际上我可以使用 BCryptGenerateKeyPair 来执行此操作,但是 CertCreateSelfSignCertificate无法正常工作,因为它需要一个密钥存储提供程序。

有什么办法可以解决吗?我在想要么尝试以某种方式创建一个临时的内存中密钥存储提供程序,要么以困难的方式进行操作并使用对 CryptEncodeObjectEx 的复杂调用链自己构建整个 X509 证书 blob。 Documentation/reference 这类东西的示例代码很糟糕,尽管进行了广泛的谷歌搜索,我还是很难找到任何东西:-(

任何对可能有用的不同想法或示例代码的帮助将不胜感激

以下代码是我制作的一个应用程序中的确切代码(代码中对应用程序名称的一些更改除外。)

它在内存中创建一个自签名证书并将其添加到本地系统存储。进行一些调整,您可以获得证书上下文本身。它使用 CNG Next Generation API 来保持现代。

bool GenerateSelfSignedCertificate()
{
    auto result{ false };
    CERT_NAME_BLOB nameBlob{ 0 };
    CERT_EXTENSIONS certExtensions{ 0 };
    NCRYPT_PROV_HANDLE providerHandle{ 0 };
    NCRYPT_KEY_HANDLE keyHandle{ 0 };
    PCCERT_CONTEXT certContext{ nullptr };
    HCERTSTORE certStore{ nullptr };
    CRYPT_KEY_PROV_INFO keyProvInfo{
        const_cast<LPWSTR>(L"MyService_Key"), const_cast<LPWSTR>(MS_KEY_STORAGE_PROVIDER),
        0, NCRYPT_SILENT_FLAG, 0, nullptr, AT_KEYEXCHANGE
    };

    if (!CertStrToNameW(X509_ASN_ENCODING, L"CN=MyService", 0, nullptr, nameBlob.pbData,
        &nameBlob.cbData, nullptr))
        goto fail;
    nameBlob.pbData = new UCHAR[nameBlob.cbData];
    if (!CertStrToNameW(X509_ASN_ENCODING, L"CN=MyService", 0, nullptr, nameBlob.pbData,
        &nameBlob.cbData, nullptr))
        goto fail;
    if (NCryptOpenStorageProvider(&providerHandle, MS_KEY_STORAGE_PROVIDER, 0) != ERROR_SUCCESS)
        goto fail;
    if (NCryptCreatePersistedKey(providerHandle, &keyHandle, BCRYPT_RSA_ALGORITHM, L"MyService_Key",
        AT_KEYEXCHANGE, 0) != ERROR_SUCCESS)
        goto fail;
    if (NCryptFinalizeKey(keyHandle, NCRYPT_SILENT_FLAG) != ERROR_SUCCESS)
        goto fail;
    certContext = CertCreateSelfSignCertificate(keyHandle, &nameBlob, 0, &keyProvInfo, nullptr,
        nullptr, nullptr, &certExtensions);
    if (!certContext)
        goto fail;
    certStore = CertOpenSystemStoreW(NULL, L"MY");
    if (!certStore)
        goto fail;
    if (!CertAddCertificateContextToStore(certStore, certContext, CERT_STORE_ADD_REPLACE_EXISTING, nullptr))
        goto fail;
    result = true;

fail:
    delete[] nameBlob.pbData;
    if (keyHandle)
        OutputDebugStringW(L"NCryptFinalizeKey successfully finalized the key for use in the certificate.\r\n");
    if (providerHandle)
        NCryptFreeObject(providerHandle);
    if (certStore)
        CertCloseStore(certStore, 0);
    if (certContext)
        CertFreeCertificateContext(certContext);
    return result;
}

如果对您有帮助,请告诉我。谢谢