如何从 .NET 标准中的 PEM 文件加载带有私钥的证书

Nir*_* B. 5 x509certificate .net-standard

我正在尝试从 .NET 标准库中的 PEM 文件加载 X509Certificate2。

我使用 openssl 创建了一个自签名证书,如下所示:

openssl req -x509 -newkey rsa:4096 -keyout key.pem -out cert.pem -nodes -subj /CN=localhost -days 365
Run Code Online (Sandbox Code Playgroud)

我将生成的 PEM 文件加载到项目中的嵌入字符串资源中,并尝试使用以下代码加载它们:

private X509Certificate2 GetCertificate()
{
    try
    {
        byte[] pubPem = System.Text.Encoding.UTF8.GetBytes(Properties.Resources.DefaultPublicPem.Trim());
        var cert = new X509Certificate2(pubPem);
        var rsa = GetRSAFromPem(Properties.Resources.DefaultPrivatePem.Trim());
        cert.PrivateKey = rsa;
        return cert;
    }

    catch (Exception ex)
    {
        // ignore errors
        return null;
    }
}

public static RSA GetRSAFromPem(String pemstr)
{
    RSA rsaKey = RSA.Create();
    Func<RSA, RsaKeyParameters, RSA> MakePublicRCSP = (RSA rcsp, RsaKeyParameters rkp) =>
    {
        RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp);
        rcsp.ImportParameters(rsaParameters);
        return rsaKey;
    };

    Func<RSA, RsaPrivateCrtKeyParameters, RSA> MakePrivateRCSP = (RSA rcsp, RsaPrivateCrtKeyParameters rkp) =>
    {
        RSAParameters rsaParameters = DotNetUtilities.ToRSAParameters(rkp);
        rcsp.ImportParameters(rsaParameters);
        return rsaKey;
    };

    PemReader reader = new PemReader(new StringReader(pemstr));
    object kp = reader.ReadObject();

    // If object has Private/Public property, we have a Private PEM
    var hasPrivate = kp.GetType().GetProperty("Private") != null;
    var isPrivate = kp is RsaPrivateCrtKeyParameters;
    return isPrivate ? MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)kp) : hasPrivate ? MakePrivateRCSP(rsaKey, (RsaPrivateCrtKeyParameters)(((AsymmetricCipherKeyPair)kp).Private)) : MakePublicRCSP(rsaKey, (RsaKeyParameters)kp);
}
Run Code Online (Sandbox Code Playgroud)

我在 Android 上对其进行了测试,效果很好。

在 iOS 上我还没有测试过,但在 UWP 上它失败了,我在尝试设置证书上的 PrivateKey 时遇到 PlatformNotSupported 异常。

所以我想知道什么不受支持,以及我是否做得不对。

Cry*_*t32 2

相反,RSACryptoServiceProvider您应该使用基RSA类。在 Windows 上的 .NET Standard 和 .NET Core 中,RSA 私钥被解析为RSACng,而不是旧版RSACryptoServiceProvider

有关更多详细信息,请参阅此线程:X509AmetrySecurityKey.GetAmetryAlgorithm returns null after .Net 4.7.2 Upgrade