Export Azure KeyVault Certificate with Private Key

Photo by Jason Pofahl / Unsplash

Last post we manage to extract certificate from Azure KeyVault. Thing is, using such method will only retrieve Public Key of certificate. It is not possible to retrieve Private Key from the method previous used.

Since we are aimimg Private Key, we need to change the way we retrieve certificate. From GetCertificateAsync to DownloadCertificateAsync, we can actually download certificate into our memory.

//var certificate = await client.GetCertificeAsync(certName);
var certificate = await client.DownloadCertificateAsync(certName);

But it does not work

Tricky part is, you can not extract Private Key from that.
Even when it shows HasPrivateKey = true.

When encounter this problem, the scenario is trying to convert the Private Key to AsymmetricKeyParameter. It supposed to sign my request to the APIs. Which need to do something like this:

Stream stream = new MemoryStream(certificate.Value.Export(X509ContentType.Pkcs12 , certPwd.ToCharArray()));
Pkcs12Store store = new(stream, certPwd.ToCharArray());
string pName = default;
foreach (string n in store.Aliases)
{
    if (store.IsKeyEntry(n))
    {
        pName = n;
        Console.WriteLine(n);
    }
}
Console.WriteLine(store.GetKey(pName).Key);

As you can see, it needs to store the certificate into Pkcs12Store which can only be created by using Stream. when X509ContentType is not defined when download the certificate, it will not allow you to do such thing. To solve this we need to add X509ContentType.Exportable into certificate's X509StorageFlags.

First I tried to add X509StorageFlags to X509Certificate2 After it's being downloaded, sadly it will not work this way.

The solution

After digging awhile I figure out DownloadCertificateAsync comes with an option called DownloadCertificateOptions. Which you can define X509StorageFlags before download the certificate. After a little bit modification, my code become like this:

DownloadCertificateOptions downloadOption = new(certificateName)
{
    KeyStorageFlags = X509KeyStorageFlags.MachineKeySet |
        X509KeyStorageFlags.Exportable
};
var certificate = await client.DownloadCertificateAsync(downloadOption);

With this modification, certificate can be exported with Pkcs12 format and convert it to AsymmetricKeyParameter without any problem.