KeyVault 生成的带有可导出私钥的证书
KeyVault generated certificate with exportable private key
我正在尝试使用 "Self" 颁发者在 KeyVault 中创建自签名证书。
$policy = New-AzureKeyVaultCertificatePolicy -SubjectName "CN=$($certificateName)" -IssuerName "Self" -ValidityInMonths 12
$policy.Exportable = $true
Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy
但是,当取回证书时,它似乎没有私钥。
直接在 KeyVault 中创建证书似乎并没有在网上大量介绍,在深入研究了 powershell cmdlet 的其余 API 文档和源代码之后,我感到很困惑。
我希望这是我错过的简单内容,因为我希望避免在本地创建证书..
如果您想检索证书及其私钥,则可以通过以下方式将其导出到磁盘上的 PFX 文件(密码为空):
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
[IO.File]::WriteAllBytes($pfxPath, $pfxUnprotectedBytes)
如果您只想在内存中查看私钥本身而不写入磁盘,请尝试:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfx.PrivateKey.ExportParameters($true)
除指数和模数外,还将显示私有参数。
如果您想使用自己的密码保护磁盘上的 PFX 文件(根据 this blog post 中的 "Retrieve pfx file & add password back" 说明),请尝试:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$password = "my-password"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxProtectedBytes = $pfx.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
[IO.File]::WriteAllBytes($pfxPath, $pfxProtectedBytes)
如 REST API 文档 here and here 中所述,Azure Key Vault (AKV) 通过三个相互关联的资源表示给定的 X.509 证书:AKV 证书、AKV 密钥、和一个 AKV 秘密。这三个将共享相同的名称和相同的版本 - 要验证这一点,请检查来自 Get-AzureKeyVaultCertificate
.[=24 的响应中的 Id
、KeyId
和 SecretId
属性=]
这 3 个资源中的每一个都提供了查看给定 X.509 证书的不同视角:
- AKV 证书提供 X.509 证书的 public 密钥和证书元数据。它包含 public 密钥的模数和指数(
n
和 e
),以及其他证书元数据(指纹、到期日期、主题名称等)。在 PowerShell 中,您可以通过以下方式获取:
(Get-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName).Certificate
- AKV 密钥提供 X.509 证书的私钥。如果相应的证书被标记为不可导出,则它对于执行加密操作(例如签名)很有用。在 PowerShell 中,您只能通过以下方式获取此私钥的 public 部分:
(Get-AzureKeyVaultKey -VaultName $vaultName -Name $certificateName).Key
- AKV-secret 提供了一种方法来导出完整的 X.509 证书,包括它的私钥(如果它的策略允许私钥导出)。如上所示,可以通过以下方式在 PowerShell 中获取当前的 base64 编码证书:
(Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName).SecretValueText
以下是 C# 代码,用于检索证书的所有版本,包括它们的私钥,从最新到最旧,给定证书名称和 KeyVault 连接信息。它使用新的 Azure.Core
、Azure.Identity
和 Azure.Security.KeyVault.[Certificates|Secrets]
SDK 包。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Certificates;
using Azure.Security.KeyVault.Secrets;
public static class CertTools
{
public static void MyMethod(string tenantId, string clientId, string clientSecret, Uri keyVaultUri)
{
var cred = new ClientSecretCredential(tenantId, clientId, clientSecret); // or any other means of obtaining Azure credential
var certs = GetAllCertificateVersions(keyVaultUri, cred, "MyCert");
}
public static List<X509Certificate2> GetAllCertificateVersions(Uri keyVaultUri, TokenCredential credential,
string certificateName)
{
var certClient = new CertificateClient(keyVaultUri, credential);
var secretClient = new SecretClient(keyVaultUri, credential);
var now = DateTimeOffset.UtcNow;
var certs = new List<X509Certificate2>();
foreach (var cert in certClient.GetPropertiesOfCertificateVersions(certificateName)
.OrderByDescending(x => x.CreatedOn)
// fetch all enabled, non-expired certificates. adjust this predicate if desired.
.Where(x => x.ExpiresOn >= now && (x.Enabled ?? false)))
{
var secret = secretClient.GetSecret(certificateName, cert.Version).Value;
certs.Add(new X509Certificate2(Convert.FromBase64String(secret.Value)));
}
return certs;
}
}
感谢 为我指明了使用 SecretClient 而不是 CertificateClient 的正确方向,但是 post 被标记为重复,因此 post 在此处输入此扩展代码.
我正在尝试使用 "Self" 颁发者在 KeyVault 中创建自签名证书。
$policy = New-AzureKeyVaultCertificatePolicy -SubjectName "CN=$($certificateName)" -IssuerName "Self" -ValidityInMonths 12
$policy.Exportable = $true
Add-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName -CertificatePolicy $policy
但是,当取回证书时,它似乎没有私钥。
直接在 KeyVault 中创建证书似乎并没有在网上大量介绍,在深入研究了 powershell cmdlet 的其余 API 文档和源代码之后,我感到很困惑。
我希望这是我错过的简单内容,因为我希望避免在本地创建证书..
如果您想检索证书及其私钥,则可以通过以下方式将其导出到磁盘上的 PFX 文件(密码为空):
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
[IO.File]::WriteAllBytes($pfxPath, $pfxUnprotectedBytes)
如果您只想在内存中查看私钥本身而不写入磁盘,请尝试:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfx.PrivateKey.ExportParameters($true)
除指数和模数外,还将显示私有参数。
如果您想使用自己的密码保护磁盘上的 PFX 文件(根据 this blog post 中的 "Retrieve pfx file & add password back" 说明),请尝试:
$vaultName = "my-vault-name"
$certificateName = "my-cert-name"
$pfxPath = [Environment]::GetFolderPath("Desktop") + "$certificateName.pfx"
$password = "my-password"
$pfxSecret = Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName
$pfxUnprotectedBytes = [Convert]::FromBase64String($pfxSecret.SecretValueText)
$pfx = New-Object Security.Cryptography.X509Certificates.X509Certificate2
$pfx.Import($pfxUnprotectedBytes, $null, [Security.Cryptography.X509Certificates.X509KeyStorageFlags]::Exportable)
$pfxProtectedBytes = $pfx.Export([Security.Cryptography.X509Certificates.X509ContentType]::Pkcs12, $password)
[IO.File]::WriteAllBytes($pfxPath, $pfxProtectedBytes)
如 REST API 文档 here and here 中所述,Azure Key Vault (AKV) 通过三个相互关联的资源表示给定的 X.509 证书:AKV 证书、AKV 密钥、和一个 AKV 秘密。这三个将共享相同的名称和相同的版本 - 要验证这一点,请检查来自 Get-AzureKeyVaultCertificate
.[=24 的响应中的 Id
、KeyId
和 SecretId
属性=]
这 3 个资源中的每一个都提供了查看给定 X.509 证书的不同视角:
- AKV 证书提供 X.509 证书的 public 密钥和证书元数据。它包含 public 密钥的模数和指数(
n
和e
),以及其他证书元数据(指纹、到期日期、主题名称等)。在 PowerShell 中,您可以通过以下方式获取:
(Get-AzureKeyVaultCertificate -VaultName $vaultName -Name $certificateName).Certificate
- AKV 密钥提供 X.509 证书的私钥。如果相应的证书被标记为不可导出,则它对于执行加密操作(例如签名)很有用。在 PowerShell 中,您只能通过以下方式获取此私钥的 public 部分:
(Get-AzureKeyVaultKey -VaultName $vaultName -Name $certificateName).Key
- AKV-secret 提供了一种方法来导出完整的 X.509 证书,包括它的私钥(如果它的策略允许私钥导出)。如上所示,可以通过以下方式在 PowerShell 中获取当前的 base64 编码证书:
(Get-AzureKeyVaultSecret -VaultName $vaultName -Name $certificateName).SecretValueText
以下是 C# 代码,用于检索证书的所有版本,包括它们的私钥,从最新到最旧,给定证书名称和 KeyVault 连接信息。它使用新的 Azure.Core
、Azure.Identity
和 Azure.Security.KeyVault.[Certificates|Secrets]
SDK 包。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using Azure.Core;
using Azure.Identity;
using Azure.Security.KeyVault.Certificates;
using Azure.Security.KeyVault.Secrets;
public static class CertTools
{
public static void MyMethod(string tenantId, string clientId, string clientSecret, Uri keyVaultUri)
{
var cred = new ClientSecretCredential(tenantId, clientId, clientSecret); // or any other means of obtaining Azure credential
var certs = GetAllCertificateVersions(keyVaultUri, cred, "MyCert");
}
public static List<X509Certificate2> GetAllCertificateVersions(Uri keyVaultUri, TokenCredential credential,
string certificateName)
{
var certClient = new CertificateClient(keyVaultUri, credential);
var secretClient = new SecretClient(keyVaultUri, credential);
var now = DateTimeOffset.UtcNow;
var certs = new List<X509Certificate2>();
foreach (var cert in certClient.GetPropertiesOfCertificateVersions(certificateName)
.OrderByDescending(x => x.CreatedOn)
// fetch all enabled, non-expired certificates. adjust this predicate if desired.
.Where(x => x.ExpiresOn >= now && (x.Enabled ?? false)))
{
var secret = secretClient.GetSecret(certificateName, cert.Version).Value;
certs.Add(new X509Certificate2(Convert.FromBase64String(secret.Value)));
}
return certs;
}
}
感谢