如何将私钥作为从 azure key vault 中获取的受密码保护的 pfx 的 Byte[]
How to get private key as Byte[] of a password protected pfx fetched from azure key vault
我正在使用 GetSecretAsync() 方法从 Azure Key Vault 获取我的证书,然后我期望最终获得私钥的 byte[] 和证书。
我在 .netcore3.1 中有我的应用程序
这就是我的代码的样子:
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 类型的私钥,但是任何操作(试过 ExportRSAPrivateKey())都会抛出错误“'privateKey.ExportRSAPrivateKey()' 抛出了 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException' 类型的异常”和“请求的不支持操作。"
我不知道下一步如何获取私钥和证书的byte[]。
由于您确实似乎确实需要导出:您当前的代码没有将私钥加载为可导出的,因此无法导出。解决方法是断言可导出性:
X509Certificate2 x509Certificate =
new X509Certificate2(privateKeyBytes, "", X509KeyStorageFlags.Exportable);
如果这还不够,那么您将遇到 CAPI 可导出性和 CNG 可导出性之间的差异(Windows 较旧和较新的加密库)。如果来自 PFX/PKCS#12 的私钥被加载到 CNG 中,它只是“加密可导出”,但 ExportParameters 是 plaintext-export.
虽然有一个解决方法...将其加密导出,然后将其导入到具有更灵活导出策略的其他地方,然后再次导出。
此代码段使用 .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 。对于 .NET Standard 2.0,并没有真正干净的解决方案(反映调用 .NET Core/.NET 5 的方法,否则使用 .NET Framework 的 Windows-specific 版本?)。
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();
}
}
我正在使用 GetSecretAsync() 方法从 Azure Key Vault 获取我的证书,然后我期望最终获得私钥的 byte[] 和证书。
我在 .netcore3.1 中有我的应用程序 这就是我的代码的样子:
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 类型的私钥,但是任何操作(试过 ExportRSAPrivateKey())都会抛出错误“'privateKey.ExportRSAPrivateKey()' 抛出了 'Internal.Cryptography.CryptoThrowHelper.WindowsCryptographicException' 类型的异常”和“请求的不支持操作。"
我不知道下一步如何获取私钥和证书的byte[]。
由于您确实似乎确实需要导出:您当前的代码没有将私钥加载为可导出的,因此无法导出。解决方法是断言可导出性:
X509Certificate2 x509Certificate =
new X509Certificate2(privateKeyBytes, "", X509KeyStorageFlags.Exportable);
如果这还不够,那么您将遇到 CAPI 可导出性和 CNG 可导出性之间的差异(Windows 较旧和较新的加密库)。如果来自 PFX/PKCS#12 的私钥被加载到 CNG 中,它只是“加密可导出”,但 ExportParameters 是 plaintext-export.
虽然有一个解决方法...将其加密导出,然后将其导入到具有更灵活导出策略的其他地方,然后再次导出。
此代码段使用 .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
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();
}
}