Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm using the Microsoft CNG Cryptography API and I'm trying to create a self signed certificate.

We have existing code which uses the CertCreateSelfSignCertificate method, combined with NCryptOpenStorageProvider and NCryptCreatePersistedKey to create the key pair.

The problem I'm facing now, is that the above combination creates a key which ends up in the windows crypto store. I explicitly don't want to store keys there, I want the certificate and private key to both be in-memory as I plan to then write them to encrypted/protected storage of our own choosing.

From what I've been able to tell, the BCrypt family of functions is designed for in-memory use, and indeed I can use BCryptGenerateKeyPair to do this, but then the CertCreateSelfSignCertificate doesn't work as it expects a key storage provider.

Is there any way to solve this? I was thinking either to try make a tempory in-memory key storage provider somehow, or else to do it the hard way and build the entire X509 certificate blob myself using a complex chain of calls to CryptEncodeObjectEx. Documentation/reference and example code on this kind of stuff is terrible and I've struggled to find anything despite extensive googling :-(

Any help for different ideas or example code that might work would be much appreciated

like image 506
Orion Edwards Avatar asked Apr 24 '26 14:04

Orion Edwards


1 Answers

The following code is the exact code from one of my applications that I make (except a few changes to the app name in the code.)

It creates a self signed certificate in memory and adds it to the local system store. A few tweaks and you can get the certificate context itself. It uses the CNG Next Generation API to stay modern.

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;
}

Please let me know if this helps you. Thanks.

like image 145
Arush Agarampur Avatar answered Apr 26 '26 05:04

Arush Agarampur



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!