如何获取私钥,作为从天蓝色密钥存储库中获取的受密码保护的pfx的Byte [] [英] How to get private key as Byte[] of a password protected pfx fetched from azure key vault
问题描述
我正在使用GetSecretAsync()方法从Azure密钥保管库中获取证书,然后期望最终获得私钥的byte []和证书.
I am fetching my certificate from Azure Key Vault using GetSecretAsync() method and then I am expecting to get the byte[] of the private key and the certificate eventually.
我在.netcore3.1中有我的应用程序这就是我的代码的样子:
I have my application in .netcore3.1 This is how my code looks like :
var certWithPrivateKey = Client.GetSecretAsync(ConfigurationSettings.AppSettings["AKVEndpoint"], ConfigurationSettings.AppSettings["CertName"]).GetAwaiter().GetResult();
var privateKeyBytes = Convert.FromBase64String(certWithPrivateKey.Value);
X509Certificate2 x509Certificate = new X509Certificate2(privateKeyBytes);
var privateKey = x509Certificate.GetRSAPrivateKey() as RSA;
我得到了RSACng类型的有效privateKey,但是任何引发'privateKey.ExportRSAPrivateKey()"错误的操作(尝试ExportRSAPrivateKey())都引发了"Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException"类型的异常"和不支持请求的操作."
I get a valid privateKey of type RSACng, but any operation (tried ExportRSAPrivateKey()) on that throws an error of "'privateKey.ExportRSAPrivateKey()' threw an exception of type 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException'" and "The requested operation is not supported."
我不确定接下来如何获取私钥和证书的字节[].
I am not sure how to proceed next here to get the byte[] of the private key and certificate.
推荐答案
由于您实际上似乎确实需要导出:您当前的代码不会将私钥加载为可导出,因此无法导出.解决方法是断言可导出性:
Since you do actually seem to need to export: Your current code doesn't load the private key as exportable, so it can't be exported. The fix is to assert exportability:
X509Certificate2 x509Certificate =
new X509Certificate2(privateKeyBytes, "", X509KeyStorageFlags.Exportable);
如果这还不够,那么您将遇到CAPI可导出性和CNG可导出性之间的差异(Windows较新的加密库).如果来自PFX/PKCS#12的私钥被加载到CNG中,则它只是加密的可导出",而ExportParameters是纯文本导出.
If that's not enough, then you're encountering the difference between CAPI exportability and CNG exportability (Windows older, and newer, crypto libraries). If the private key from a PFX/PKCS#12 gets loaded into CNG it's only "encrypted exportable", but ExportParameters is plaintext-export.
有一种解决方法,尽管...将其导出加密,然后使用更灵活的导出策略将其导入其他地方,然后再次导出.
There's a workaround, though... export it encrypted, then import that somewhere else with a more flexible export policy, then export again.
此代码段使用.NET Core 3.0+ PemEncoding 类可简化将DER编码输出转换为PEM + DER输出的过程.如果您的出口商在.NET Framework上,则这是一个更复杂的问题.对于.NET Standard 2.0,实际上不是一个干净的解决方案(是否可以调用.NET Core/.NET 5的方法,否则可以使用Windows专用的.NET Framework版本?).
This snippet uses the .NET Core 3.0+ ExportPkcs8PrivateKey() method, since that's the format you want your data in, and new .NET 5 PemEncoding class to simplify turning the DER encoded output into PEM+DER output. If your exporter is on .NET Framework, this is a more complex problem. For .NET Standard 2.0 there's not really a clean solution (reflect call the methods for .NET Core/.NET 5, otherwise use the Windows-specific version for .NET Framework?).
byte[] pkcs8PrivateKey;
using (RSA privateKey = x509Certificate.GetRSAPrivateKey())
{
pkcs8PrivateKey = ExportPrivateKey(privateKey);
}
File.WriteAllText(
"tls.cer",
new string(PemEncoding.Write("CERTIFICATE", x509Certificate.RawData));
File.WriteAllText(
"tls.key",
new string(PemEncoding.Write("PRIVATE KEY", pkcs8PrivateKey));
...
private static byte[] ExportPrivateKey(RSA privateKey)
{
try
{
// If it's plaintext exportable, just do the easy thing.
return privateKey.ExportPkcs8PrivateKey();
}
catch (CryptographicException)
{
}
using (RSA exportRewriter = RSA.Create())
{
// Only one KDF iteration is being used here since it's immediately being
// imported again. Use more if you're actually exporting encrypted keys.
exportRewriter.ImportEncryptedPkcs8PrivateKey(
"password",
privateKey.ExportEncryptedPkcs8PrivateKey(
"password",
new PbeParameters(
PbeEncryptionAlgorithm.Aes128Cbc,
HashAlgorithmName.SHA256,
1)),
out _);
return exportRewriter.ExportPkcs8PrivateKey();
}
}
这篇关于如何获取私钥,作为从天蓝色密钥存储库中获取的受密码保护的pfx的Byte []的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!