问题 如何在Azure Key Vault中序列化和反序列化PFX证书?


我有一堆字符串和pfx证书,我想存储在Azure Key保险库中,只允许用户/应用程序获取它们。将字符串存储为Secret是不难的,但是如何以一种我可以检索它的方式序列化证书并将其反序列化为 X509Certificate2 C#中的对象?

我试着将它存储为钥匙。这是Azure powershell代码

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

但是,当我试图得到它 GetKeyAsync 方法,我无法使用它。


5801
2017-11-16 03:48


起源



答案:


这是适合您的PowerShell脚本。替换文件路径,密码,保管库名称,密码名称。

$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

这是一个常见的问题,因此我们将对此进行改进并作为帮助者发布。

上面的脚本剥离了密码,因为密码保护PFX没有价值,然后将密码存储在旁边。


12
2017-12-09 18:56



$ clearBytes = $ collection.Export($ pkcs12ContentType)似乎不会导出私钥。使用$ collection.Export($ pkcs12ContentType,$ pwd)方法允许我使用密码将证书导入为X509Certificate2(c#)。 - Trey
@Sumedh您指的是新Key Key证书的功能吗? docs.microsoft.com/en-us/rest/api/keyvault/... 谢谢 - H Boyce
@HBoyce确实是的。这是证书功能的教程。现在比上面的脚本简洁得多,您的证书也会自动更新。 blogs.technet.microsoft.com/kv/2016/09/26/...  (谢谢你复活这个帖子。) - Sumedh Barde
Downvote,向人们展示如何在不展示检索的情况下存储东西并没有多大意义。问题还在于关于C#和检索 x509Certificate2 前面的评论显示的对象并不简单。 - McGuireV10
如果到这里来的人和我一样困惑。事实证明你需要将.pfx上传到 secrets Keyvault的部分而不是 keys 部分 - ElFik


答案:


这是适合您的PowerShell脚本。替换文件路径,密码,保管库名称,密码名称。

$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

这是一个常见的问题,因此我们将对此进行改进并作为帮助者发布。

上面的脚本剥离了密码,因为密码保护PFX没有价值,然后将密码存储在旁边。


12
2017-12-09 18:56



$ clearBytes = $ collection.Export($ pkcs12ContentType)似乎不会导出私钥。使用$ collection.Export($ pkcs12ContentType,$ pwd)方法允许我使用密码将证书导入为X509Certificate2(c#)。 - Trey
@Sumedh您指的是新Key Key证书的功能吗? docs.microsoft.com/en-us/rest/api/keyvault/... 谢谢 - H Boyce
@HBoyce确实是的。这是证书功能的教程。现在比上面的脚本简洁得多,您的证书也会自动更新。 blogs.technet.microsoft.com/kv/2016/09/26/...  (谢谢你复活这个帖子。) - Sumedh Barde
Downvote,向人们展示如何在不展示检索的情况下存储东西并没有多大意义。问题还在于关于C#和检索 x509Certificate2 前面的评论显示的对象并不简单。 - McGuireV10
如果到这里来的人和我一样困惑。事实证明你需要将.pfx上传到 secrets Keyvault的部分而不是 keys 部分 - ElFik


原始问题询问如何检索存储的PFX作为 X509Certificate2 目的。使用类似于Sumedh Barde上面发布的Base64进程(具有剥离密码的优点),以下代码将返回X509对象。在一个真实的应用程序中, KeyVaultClient 如果你要检索多个秘密,应该缓存,并且还应该缓存个人机密。

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

3
2018-01-10 16:38



这是完全正确的。请记住,您需要将密钥保存在 secrets 你的keyvault部分而不是 keys 你的钥匙圈 - ElFik
他们真的应该将密钥部分命名为更好地澄清它对于自动公钥共享和轮换的意义,与通用密钥存储相比...... - McGuireV10
想要使用这个和类似的解决方案,但与.Net Core 2.1,VS 2017 + Azure SDK获取: 'KeyVaultClient' does not contain a definition for 'GetSecretAsync'。 - ttugates
@ttugates我不是我可以检查代码的地方,但我认为它在扩展包中,你需要引用或者你只需​​要一个 using 声明。 - McGuireV10
@ McGuireV10,找到了引用的扩展包 ASP.NET Core中的Azure Key Vault配置提供程序 - ttugates


这是使用azure cli在python中上传pfx证书的脚本

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

在python中获取PFX文件的内容

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()

0
2018-01-09 19:57



Downvote。问题是关于检索作为一个 x509Certificate2 使用C#的对象。 - McGuireV10