使用Azure密钥保险库证书解密将返回错误

使用Azure密钥保险库证书解密将返回错误,azure,asp.net-core,cryptography,asp.net-core-webapi,azure-keyvault,Azure,Asp.net Core,Cryptography,Asp.net Core Webapi,Azure Keyvault,我有一个自我签名的2048位密钥,是我使用OpenSSL创建的。我已将从中创建的证书上载到Azure Key Vault,并打算访问它。我注意到,当从我的应用程序(asp.net 3.1;来自本地环境)指向Azure Key Vault调用时,它失败了!但是,如果我使用相同的证书指向我的本地驱动器,它就会工作 请注意,我只是在本地环境中运行,还没有在云中托管它,在本例中是Azure 我在decryptedResponseData=Encoding.UTF8.GetString(rsa.Decry

我有一个自我签名的2048位密钥,是我使用
OpenSSL
创建的。我已将从中创建的证书上载到Azure Key Vault,并打算访问它。我注意到,当从我的应用程序(asp.net 3.1;来自本地环境)指向Azure Key Vault调用时,它失败了!但是,如果我使用相同的证书指向我的本地驱动器,它就会工作

请注意,我只是在本地环境中运行,还没有在云中托管它,在本例中是Azure

我在
decryptedResponseData=Encoding.UTF8.GetString(rsa.Decrypt(Convert.FromBase64String,RSAEncryptionPadding.Pkcs1)),得到一个未设置为对象实例的
对象引用

此外,我在调试期间注意到,如果我从Azure密钥库获取证书,
PrivateKey
属性返回
null
,并且
HasPrivateKey
var rsa=(RSACng)cert.PrivateKey处设置为
false

如果我从本地驱动器访问同一证书,则此代码有效:

private static X509Certificate2 cert = new X509Certificate2(@"C:\<Dummy Path>\My.pfx", ""); //No password
        

        public static string Decrypt(this string s) 
        {
            if (string.IsNullOrWhiteSpace(s)) return "";

            //var cert = GetCertificate();
            var decryptedResponseData = string.Empty;
            var rsa = (RSACng)cert.PrivateKey;
            var raw = cert.RawData;
            
            decryptedResponseData = Encoding.UTF8.GetString( rsa.Decrypt(Convert.FromBase64String(s),RSAEncryptionPadding.Pkcs1));
            
            return decryptedResponseData;
        }
`


我做错什么了吗?请帮助我。

默认情况下,从密钥库下载的证书不包含私钥。您可以将证书作为机密下载并检索整个内容


有关如何将证书作为秘密下载,请参阅本博客文章的第2节。您可以转换为C:

从密钥库下载的证书默认情况下不包含私钥。您可以将证书作为机密下载并检索整个内容


有关如何将证书作为秘密下载,请参阅本博客文章的第2节。您可以转换为C:

以获取私钥,您需要将其作为机密下载

下面的代码显示了我如何从Azure key Vault下载带有私钥的证书

    /// <summary>
    /// Load a certificate (with private key) from Azure Key Vault
    ///
    /// Getting a certificate with private key is a bit of a pain, but the code below solves it.
    /// 
    /// Get the private key for Key Vault certificate
    /// https://github.com/heaths/azsdk-sample-getcert
    /// 
    /// See also these GitHub issues: 
    /// https://github.com/Azure/azure-sdk-for-net/issues/12742
    /// https://github.com/Azure/azure-sdk-for-net/issues/12083
    /// </summary>
    /// <param name="config"></param>
    /// <param name="certificateName"></param>
    /// <returns></returns>
    public static X509Certificate2 LoadCertificate(IConfiguration config, string certificateName)
    {
        string vaultUrl = config["Vault:Url"] ?? "";
        string clientId = config["Vault:ClientId"] ?? "";
        string tenantId = config["Vault:TenantId"] ?? "";
        string secret = config["Vault:Secret"] ?? "";

        Console.WriteLine($"Loading certificate '{certificateName}' from Azure Key Vault");

        var credentials = new ClientSecretCredential(tenantId: tenantId, clientId: clientId, clientSecret: secret);
        var certClient = new CertificateClient(new Uri(vaultUrl), credentials);
        var secretClient = new SecretClient(new Uri(vaultUrl), credentials);

        var cert = GetCertificateAsync(certClient, secretClient, certificateName);

        Console.WriteLine("Certificate loaded");
        return cert;
    }


    /// <summary>
    /// Helper method to get a certificate
    /// 
    /// Source https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
    /// </summary>
    /// <param name="certificateClient"></param>
    /// <param name="secretClient"></param>
    /// <param name="certificateName"></param>
    /// <returns></returns>
    private static X509Certificate2 GetCertificateAsync(CertificateClient certificateClient,
                                                            SecretClient secretClient,
                                                            string certificateName)
    {

        KeyVaultCertificateWithPolicy certificate = certificateClient.GetCertificate(certificateName);

        // Return a certificate with only the public key if the private key is not exportable.
        if (certificate.Policy?.Exportable != true)
        {
            return new X509Certificate2(certificate.Cer);
        }

        // Parse the secret ID and version to retrieve the private key.
        string[] segments = certificate.SecretId.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
        if (segments.Length != 3)
        {
            throw new InvalidOperationException($"Number of segments is incorrect: {segments.Length}, URI: {certificate.SecretId}");
        }

        string secretName = segments[1];
        string secretVersion = segments[2];

        KeyVaultSecret secret = secretClient.GetSecret(secretName, secretVersion);

        // For PEM, you'll need to extract the base64-encoded message body.
        // .NET 5.0 preview introduces the System.Security.Cryptography.PemEncoding class to make this easier.
        if ("application/x-pkcs12".Equals(secret.Properties.ContentType, StringComparison.InvariantCultureIgnoreCase))
        {
            byte[] pfx = Convert.FromBase64String(secret.Value);
            return new X509Certificate2(pfx);
        }

        throw new NotSupportedException($"Only PKCS#12 is supported. Found Content-Type: {secret.Properties.ContentType}");
    }
}
//
///从Azure密钥库加载证书(带私钥)
///
///获取带有私钥的证书有点困难,但下面的代码解决了这一问题。
/// 
///获取密钥库证书的私钥
/// https://github.com/heaths/azsdk-sample-getcert
/// 
///另请参见以下GitHub问题:
/// https://github.com/Azure/azure-sdk-for-net/issues/12742
/// https://github.com/Azure/azure-sdk-for-net/issues/12083
/// 
/// 
/// 
/// 
公共静态X509Certificate2加载证书(IConfiguration配置,字符串certificateName)
{
字符串vaultUrl=config[“Vault:Url”]??“”;
字符串clientId=config[“Vault:clientId”];
字符串tenantId=config[“Vault:tenantId”];
字符串secret=config[“Vault:secret”];
WriteLine($“正在从Azure密钥库加载证书“{certificateName}”);
var-credentials=new-ClientSecretCredential(tenantId:tenantId,clientId:clientId,clientSecret:secret);
var certClient=new CertificateClient(新Uri(Vault URL)、凭据);
var secretClient=新secretClient(新Uri(Vault URL)、凭据);
var cert=GetCertificateAsync(certClient、secretClient、certificateName);
Console.WriteLine(“已加载证书”);
返回证书;
}
/// 
///获取证书的助手方法
/// 
///来源https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
/// 
/// 
/// 
/// 
/// 
专用静态X509Certificate2 GetCertificateAsync(CertificateClient CertificateClient,
SecretClient SecretClient,
字符串(名称)
{
KeyVault CertificateWithPolicy certificate=certificateClient.GetCertificate(certificateName);
//如果私钥不可导出,则返回仅包含公钥的证书。
if(certificate.Policy?.Exportable!=true)
{
返回新的X509Certificate2(certificate.Cer);
}
//解析机密ID和版本以检索私钥。
string[]segments=certificate.SecretId.AbsolutePath.Split(“/”,StringSplitOptions.RemoveEmptyEntries);
如果(segments.Length!=3)
{
抛出新的InvalidOperationException($“段数不正确:{segments.Length},URI:{certificate.SecretId}”);
}
字符串secretName=段[1];
字符串secretVersion=段[2];
KeyVaultSecret-secret=secretClient.GetSecret(secretName,secretVersion);
//对于PEM,您需要提取base64编码的消息体。
//.NET 5.0预览版引入了System.Security.Cryptography.PemEncoding类以简化此操作。
if(“application/x-pkcs12”.Equals(secret.Properties.ContentType、StringComparison.InvariantCultureInogoreCase))
{
字节[]pfx=Convert.FromBase64String(secret.Value);
返回新的X509Certificate2(pfx);
}
抛出新的NotSupportedException($“仅支持PKCS#12。找到的内容类型:{secret.Properties.ContentType}”);
}
}

要获取私钥,您需要将其作为机密下载

下面的代码显示了我如何从Azure key Vault下载带有私钥的证书

    /// <summary>
    /// Load a certificate (with private key) from Azure Key Vault
    ///
    /// Getting a certificate with private key is a bit of a pain, but the code below solves it.
    /// 
    /// Get the private key for Key Vault certificate
    /// https://github.com/heaths/azsdk-sample-getcert
    /// 
    /// See also these GitHub issues: 
    /// https://github.com/Azure/azure-sdk-for-net/issues/12742
    /// https://github.com/Azure/azure-sdk-for-net/issues/12083
    /// </summary>
    /// <param name="config"></param>
    /// <param name="certificateName"></param>
    /// <returns></returns>
    public static X509Certificate2 LoadCertificate(IConfiguration config, string certificateName)
    {
        string vaultUrl = config["Vault:Url"] ?? "";
        string clientId = config["Vault:ClientId"] ?? "";
        string tenantId = config["Vault:TenantId"] ?? "";
        string secret = config["Vault:Secret"] ?? "";

        Console.WriteLine($"Loading certificate '{certificateName}' from Azure Key Vault");

        var credentials = new ClientSecretCredential(tenantId: tenantId, clientId: clientId, clientSecret: secret);
        var certClient = new CertificateClient(new Uri(vaultUrl), credentials);
        var secretClient = new SecretClient(new Uri(vaultUrl), credentials);

        var cert = GetCertificateAsync(certClient, secretClient, certificateName);

        Console.WriteLine("Certificate loaded");
        return cert;
    }


    /// <summary>
    /// Helper method to get a certificate
    /// 
    /// Source https://github.com/heaths/azsdk-sample-getcert/blob/master/Program.cs
    /// </summary>
    /// <param name="certificateClient"></param>
    /// <param name="secretClient"></param>
    /// <param name="certificateName"></param>
    /// <returns></returns>
    private static X509Certificate2 GetCertificateAsync(CertificateClient certificateClient,
                                                            SecretClient secretClient,
                                                            string certificateName)
    {

        KeyVaultCertificateWithPolicy certificate = certificateClient.GetCertificate(certificateName);

        // Return a certificate with only the public key if the private key is not exportable.
        if (certificate.Policy?.Exportable != true)
        {
            return new X509Certificate2(certificate.Cer);
        }

        // Parse the secret ID and version to retrieve the private key.
        string[] segments = certificate.SecretId.AbsolutePath.Split('/', StringSplitOptions.RemoveEmptyEntries);
        if (segments.Length != 3)
        {
            throw new InvalidOperationException($"Number of segments is incorrect: {segments.Length}, URI: {certificate.SecretId}");
        }

        string secretName = segments[1];
        string secretVersion = segments[2];

        KeyVaultSecret secret = secretClient.GetSecret(secretName, secretVersion);

        // For PEM, you'll need to extract the base64-encoded message body.
        // .NET 5.0 preview introduces the System.Security.Cryptography.PemEncoding class to make this easier.
        if ("application/x-pkcs12".Equals(secret.Properties.ContentType, StringComparison.InvariantCultureIgnoreCase))
        {
            byte[] pfx = Convert.FromBase64String(secret.Value);
            return new X509Certificate2(pfx);
        }

        throw new NotSupportedException($"Only PKCS#12 is supported. Found Content-Type: {secret.Properties.ContentType}");
    }
}
//
///从Azure密钥库加载证书(带私钥)
///
///获取带有私钥的证书有点困难,但下面的代码解决了这一问题。
/// 
///获取密钥库证书的私钥
/// https://github.com/heaths/azsdk-sample-getcert
/// 
///另请参见以下GitHub问题:
/// https://github.com/Azure/azure-sdk-for-net/issues/12742
/// https://github.com/Azure/azure-sdk-for-net/issues/12083
/// 
/// 
/// 
/// 
公共静态X509Certificate2加载证书(IConfiguration配置,字符串certificateName)
{