C# 通过IKeyVaultClient.GetCertificateAsync检索时,Azure Key Vault证书没有私钥

C# 通过IKeyVaultClient.GetCertificateAsync检索时,Azure Key Vault证书没有私钥,c#,ssl,azure-keyvault,x509certificate2,kestrel-http-server,C#,Ssl,Azure Keyvault,X509certificate2,Kestrel Http Server,我有两种方法来做同样的事情,但是Azure不推荐使用一种有效的方法,而另一种方法不起作用 有效但不受欢迎的方法: 我将我的PFX存储在Azure Key VaultSecrets中。(创建机密时,我看到一条警告,指出此功能已被弃用) 并使用以下代码检索它以创建我的证书: SecretBundle secret = await keyVaultClient.GetSecretAsync(keyVaultUrl, "MyCert-Secret"); X509Certi

我有两种方法来做同样的事情,但是Azure不推荐使用一种有效的方法,而另一种方法不起作用

有效但不受欢迎的方法:

我将我的PFX存储在Azure Key VaultSecrets中。(创建机密时,我看到一条警告,指出此功能已被弃用)

并使用以下代码检索它以创建我的证书:

        SecretBundle secret = await keyVaultClient.GetSecretAsync(keyVaultUrl, "MyCert-Secret");
        X509Certificate2Collection exportedCertCollection = new X509Certificate2Collection();
        exportedCertCollection.Import(Convert.FromBase64String(secret.Value));
        X509Certificate2 certFromSecret = exportedCertCollection.Cast<X509Certificate2>().Single(s => s.HasPrivateKey);
这种方法的问题是证书不包含私钥。i、 e.certFromCertificate.HasPrivateKey为false

我的问题

为什么certFromSecret有私钥,而certFromCertificate没有

我如何从密钥库中检索证书,在这里我可以创建一个X509Certificate2对象,用UseHttps在Kestrel中托管我的应用程序。

Adrian的第二部分很好地解释了Azure KV证书的概念,我已经更改了代码,如下所示,以获取完整的证书,包括私钥:

        SecretBundle secret = await kv.GetSecretAsync(keyVaultUrl, certName);
        X509Certificate2 certificate = 
                 new X509Certificate2(Convert.FromBase64String(secret.Value));
诀窍是使用
GetSecretAsync
而不是
GetCertificateAsync
。请参阅Adrian的,以了解为什么必须使用秘密来获取带有私钥的完整证书


请注意,您应该从Azure证书的属性页使用“证书标识符”属性(url带有“/secrets/”)。

@Adriano谢谢。你回答的第二部分帮助解决了我的问题。关键点在于AKV证书如何包含3个组件—密钥、机密和证书,以及您对每个组件中存储的内容的详细分析。我正在发布我对代码所做的更改,供其他人参考。你找到合适的解决方案了吗?@Davy发布的答案是我采用的方法。虽然建议的复制有很好的细节说明它为什么不起作用,但它确实没有显示C代码来这样做。看起来这本书实际上讲的是C版本,所以重新标记并投票重新打开。非常感谢你在这里发布这个答案。您引用的答案仅包含Power Shell代码,而这是在干净的C#中。Microsoft必须在文档中澄清GetCertificateAsync()方法没有从vault检索到有用的证书。我投票重新打开了这个问题,因为“副本”指的是PowerShell,而这个问题是关于C#。然而,由于我不能发布新的答案,我提供了一个更完整的工作方法来检索所有带有私钥的证书。
        SecretBundle secret = await kv.GetSecretAsync(keyVaultUrl, certName);
        X509Certificate2 certificate = 
                 new X509Certificate2(Convert.FromBase64String(secret.Value));