How to serialize and deserialize a PFX certificate

2019-01-09 06:52发布

I have a bunch of strings and pfx certificates, which I want to store in Azure Key vault, where only allowed users/apps will be able to get them. It is not hard to do store a string as a Secret, but how can I serialize a certificate in such way that I could retrieve it and deserialize as an X509Certificate2 object in C#?

I tried to store it as a key. Here is the Azure powershell code

$securepfxpwd = ConvertTo-SecureString -String 'superSecurePassword' -AsPlainText -Force
$key = Add-AzureKeyVaultKey -VaultName 'UltraVault' -Name 'MyCertificate' -KeyFilePath 'D:\Certificates\BlaBla.pfx' -KeyFilePassword $securepfxpwd

But when I tried to get it with GetKeyAsync method, I couldn't use it.

3条回答
SAY GOODBYE
2楼-- · 2019-01-09 07:29

The original question asked how to retrieve the stored PFX as an X509Certificate2 object. Using a Base64 process similar to that posted by Sumedh Barde above (which has the advantage of stripping the password), the following code will return a X509 object. In a real application, the KeyVaultClient should be cached if you're retrieving multiple secrets, and the individual secrets should also be cached.

public static async Task<X509Certificate2> GetSecretCertificateAsync(string secretName)
{
    string baseUri = @"https://xxxxxxxx.vault.azure.net/secrets/";

    var provider = new AzureServiceTokenProvider();
    var client =  new KeyVaultClient(new KeyVaultClient.AuthenticationCallback(provider.KeyVaultTokenCallback));
    var secretBundle = await KeyVaultClient.GetSecretAsync($"{baseUri}{secretName}").ConfigureAwait(false);
    string pfx = secretBundle.Value;

    var bytes = Convert.FromBase64String(pfx);
    var coll = new X509Certificate2Collection();
    coll.Import(bytes, null, X509KeyStorageFlags.Exportable);
    return coll[0];
}
查看更多
Rolldiameter
3楼-- · 2019-01-09 07:44

Here's a PowerShell script for you. Replace the file path, password, vault name, secret name.

$pfxFilePath = 'C:\mycert.pfx'
$pwd = '123'
$flag = [System.Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable
$collection = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2Collection 
$collection.Import($pfxFilePath, $pwd, $flag)
$pkcs12ContentType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12
$clearBytes = $collection.Export($pkcs12ContentType)
$fileContentEncoded = [System.Convert]::ToBase64String($clearBytes)
$secret = ConvertTo-SecureString -String $fileContentEncoded -AsPlainText –Force
$secretContentType = 'application/x-pkcs12'
Set-AzureKeyVaultSecret -VaultName 'myVaultName' -Name 'mySecretName' -SecretValue $Secret -ContentType $secretContentType

This is a common question, so we are going to polish this up and release as a helper.

The script above strips the password because there's no value in having a password protected PFX and then storing the password next to it.

查看更多
放我归山
4楼-- · 2019-01-09 07:48

Here is the script for uploading pfx certificate in python using azure cli

azure keyvault secret set --vault-name <Valut name> --secret-name <Secret Name> --value <Content of PFX file>

Getting the content of PFX file in python

fh = open(self.getPfxFilePath(), 'rb')
    try:
        ba = bytearray(fh.read())
        cert_base64_str = base64.b64encode(ba)
        password = self.getPassword()
        json_blob = {
            'data': cert_base64_str,
            'dataType': 'pfx',
            'password': password
        }
        blob_data= json.dumps(json_blob)
        content_bytes= bytearray(blob_data)
        content = base64.b64encode(content_bytes)
        return content
    finally:
        fh.close
    fh.close()
查看更多
登录 后发表回答