如何获取私钥作为从 azure 密钥库中获取的受密码保护的 pfx 的 Byte[] [英] How to get private key as Byte[] of a password protected pfx fetched from azure key vault

查看:40
本文介绍了如何获取私钥作为从 azure 密钥库中获取的受密码保护的 pfx 的 Byte[]的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 GetSecretAsync() 方法从 Azure Key Vault 获取我的证书,然后我希望最终获得私钥的字节 [] 和证书.

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 类型的有效私钥,但是任何操作(尝试过 ExportRSAPrivateKey())都会引发'privateKey.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+ ExportPkcs8PrivateKey() 方法,因为这是您希望数据采用的格式,以及新的 .NET 5 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();
    }
}

这篇关于如何获取私钥作为从 azure 密钥库中获取的受密码保护的 pfx 的 Byte[]的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆