简体   繁体   English

如何从 Azure Key Vault KeyBundle 创建 X509Certificate2 对象

[英]How can I create an X509Certificate2 object from an Azure Key Vault KeyBundle

I am using Azure Key Vault to protect our keys and secrets, but I am unsure how I can use the KeyBundle I retrieve using the .net SDK.我正在使用 Azure Key Vault 来保护我们的密钥和机密,但我不确定如何使用我使用 .net SDK 检索到的 KeyBundle。 How can I create an X509Certificate2 object?如何创建 X509Certificate2 对象?

When you import / create a certificate in KeyVault, 3 entities are created:在 KeyVault 中导入/创建证书时,会创建 3 个实体:

  • Certificate - contains all the relevant details about the certificate, including its public part (ie public key, validity period, thumbprint etc.)证书 - 包含有关证书的所有相关详细信息,包括其公共部分(即公钥、有效期、指纹等)

  • Secret - contains the private key (which is the private part of the certificate) in base64 Secret - 包含 base64 中的私钥(这是证书的私有部分)

  • Key - I don't know, but irrelevant for this thread.关键 - 我不知道,但与此线程无关。

You could create X509Certificate2 object with either the Certificate object or the Secret object.您可以使用 Certificate 对象或 Secret 对象创建X509Certificate2对象。

In case you want the X509Certificate2 to contain the private key, then of course you would need to fetch the Secret entity's value and do the following:如果您希望X509Certificate2包含私钥,那么您当然需要获取 Secret 实体的值并执行以下操作:

SecretBundle certificatePrivateKeySecretBundle =
    await keyVaultClient.GetSecretAsync(certificateIdentifierSecretPart);

byte[] privateKeyBytes = Convert.FromBase64String(certificatePrivateKeySecretBundle.Value);
X509Certificate2 certificateWithPrivateKey = new X509Certificate2(privateKeyBytes, (string) null, X509KeyStorageFlags.MachineKeySet);

The certificateIdentifierSecretPart equals the certificate's secret part path: https://<vault name>.vaults.azure.net/secrets/<certificate name> certificateIdentifierSecretPart等于证书的秘密部分路径: https://<vault name>.vaults.azure.net/secrets/<certificate name>

Note the /secrets/ path.注意/secrets/路径。

November 2020 Update: 2020 年 11 月更新:

In the current version of Azure Key Vault, Certificates are a first class concept rather than a type of Secret.在当前版本的 Azure Key Vault 中, 证书是一流的概念,而不是一种机密。

If your Key Vault instance already has a certificate with an exportable private key, you'd fetch it and hydrate an X509Certificate2 as follows:如果您的 Key Vault 实例已经有一个带有可导出私钥的证书,您将获取它并按如下方式添加X509Certificate2

Create the required clients using a DefaultAzureCredential使用DefaultAzureCredential创建所需的客户端

var certClient = new CertificateClient(new Uri("https://yourKeyVault.vault.azure.net/"), new DefaultAzureCredential());
var secretClient = new SecretClient(new Uri("https://yourKeyVault.vault.azure.net/"), new DefaultAzureCredential());

Get the certificate, which includes a link to the private key secret.获取证书,其中包含指向私钥机密的链接。

Note: The latest (4.2.0 beta) version of the Key Vault Secrets library includes a helper class called KeyVaultSecretIdentifier that does this parsing for you.注意:Key Vault Secrets 库的最新 (4.2.0 beta) 版本包括一个名为KeyVaultSecretIdentifier的帮助程序类,它会为您进行解析。

Response<KeyVaultCertificateWithPolicy> certResponse = await certClient.GetCertificateAsync("testCert");

// If using client version 4.2.0 or later
KeyVaultSecretIdentifier identifier = new KeyVaultSecretIdentifier(certResponse.Value.SecretId);

// Else, Get the secretId and parse out the parts needed to fetch the secret.
Uri secretId = certResponse.Value.SecretId;
var segments = secretId.Segments;
string secretName = segments[2].Trim('/');
string version = segments[3].TrimEnd('/');

Get the secret for the certificate and use it to construct a new X509Certificate2 .获取证书的秘密并使用它来构造一个新的X509Certificate2

// If using client version 4.2.0 or later
Response<KeyVaultSecret> secretResponse = await secretClient.GetSecretAsync(identifier.Name, identifier.Version);

// else
Response<KeyVaultSecret> secretResponse = await secretClient.GetSecretAsync(secretName, version);

KeyVaultSecret secret = secretResponse.Value;
byte[] privateKeyBytes = Convert.FromBase64String(secret.Value);

var cert = new X509Certificate2(privateKeyBytes);

For more information about the latest Key Vault Certificate and Secret clients, see their respective README docs here:有关最新的 Key Vault 证书和 Secret 客户端的更多信息,请在此处查看它们各自的 README 文档:

Azure.Security.KeyVault.Certificates ( migration guide from the old version ) Azure.Security.KeyVault.Certificates从旧版本迁移指南

Azure.Security.KeyVault.Secrets ( migration guide from the old version ) Azure.Security.KeyVault.Secrets从旧版本迁移指南

You cannot use the KeyBundle result as an X509Certificate2 object because it simply represents the public key portion of a key pair here (no issuer).您不能将 KeyBundle 结果用作 X509Certificate2 对象,因为它在这里仅表示密钥对的公钥部分(无发行者)。 See the methods in KeyVaultClientExtensions for functions to encrypt data, verify signatures, etc. using this KeyBundle object.有关使用此 KeyBundle 对象加密数据、验证签名等的函数,请参阅KeyVaultClientExtensions 中的方法。

When using the new Azure.Security.KeyVault.* libraries and to build on what Christopher Scott has answered, you can load all active and non-expired versions and skip the GetCertificate and parsing step with the following:使用新的 Azure.Security.KeyVault.* 库并以Christopher Scott 的回答为基础时,您可以加载所有活动和未过期版本,并跳过 GetCertificate 和解析步骤,如下所示:

public static IEnumerable<X509Certificate2> LoadCertificateVerisons(
    string keyVaultName,
    string certificateName)
{
    var keyVaultUrl = new Uri($"https://{keyVaultName}.vault.azure.net");
    var certificateClient = new CertificateClient(keyVaultUrl, new AzureCliCredential());
    var secretClient = new SecretClient(keyVaultUrl, new AzureCliCredential());

    var versions = certificateClient.GetPropertiesOfCertificateVersions(certificateName).ToArray();

    foreach (var certificate in versions)
    {
        if (!certificate.Enabled.GetValueOrDefault(false) ||
            certificate.ExpiresOn <= DateTimeOffset.UtcNow) continue;

        var certificateSecret = secretClient.GetSecret(certificate.Name, certificate.Version).Value;
        var privateKey = Convert.FromBase64String(certificateSecret.Value);
        yield return new X509Certificate2(privateKey, (string) null, X509KeyStorageFlags.MachineKeySet);
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM