Can’t Get .pfx File to Work on Linux – Docker SSL Certificate Guide

dockerlinuxopensslssl-certificate

I am writing a C# program that has to call an API endpoint that requires authentication via certificates.

I have got a .pfx file, which I can import in Windows and everything works fine, however the app must run in a Linux environment in a Docker container.

I can import crt files into the /etc/ssl/certs folder in my Docker container just fine using the update-ca-certificates command.

I have tried the following:

  • Use openssl to to convert the pfx file into a crt/pem file that contains both the decrypted private key and the public key
-----BEGIN CERTIFICATE-----
abcd...
-----END CERTIFICATE-----
-----BEGIN RSA PRIVATE KEY-----
abcd...
-----END RSA PRIVATE KEY-----
  • Use openssl to split both keys into separate files and import those

  • Leave the bag attributes that openssl spits out in the files

Bag Attributes
    localKeyID: 01 00 00 00 
    friendlyName: XXX
subject=C = GB, O = 1111.1.1, O = XXX Limited, OU = devices, CN = XXX Limited

issuer=C = gb, O = 1111.1.1, O = YYY CAs, OU = YYY CA, OU = YYY Issuing CA

but the API always says I don't have a valid certificate.

Does anybody know what I'm doing wrong? Do the files have to be in a specific format? Perhaps in a different location?

My app finds the certificate just fine, so that's not the issue. The problem seems to be with the certificate itself.

Thanks in advance.

Best Answer

The certstore loader on Linux will never look at a private key attached on the bottom of a file in /etc/ssl/certs. (If you look at the cert object, you'll see HasPrivateKey is false).

If you want to use a cert with a private key you need to either load it directly from a PFX, load it from a PFX once to then add it to the CurrentUser\My X509Store and then can use it from there, or load it from a multi-PEM intentionally, such as by calling X509Certificate2.CreateFromPemFile(pathToPem) (or X509Certificate2.CreateFromPemFile(pathToCertPem, pathToKeyPem))

// One time, such as by running a standalone tool:

using (X509Certificate2 fromPfx = new X509Certificate2(pfxToLoad, pfxPwd, X509KeyStorageFlags.PersistKeySet))
using (X509Store store = new X509Store(StoreName.My, StoreLocation.CurrentUser, OpenFlags.ReadWrite))
{
    store.Add(fromPfx);
}

Then change your app to look in CurrentUser\My instead of LocalMachine\CA (or LocalMachine\Root, wherever you happen to be pointing it).