无法使用 RSACng 和 RsaParameter 导入前导出私钥

Cannot Export PrivateKey Before Import Using RSACng and RsaParameter

下一个单元测试导出私钥并使用rsa实例将其保存在字节数组中然后加密"hi"消息,这里一切正常,但是当它创建rsa2实例并导入前一个时出现问题RSAParameter中的privatekey,然后导入privatekey后可以解密消息,但是当你尝试导出rsa2的privatekey时抛出异常。

请你告诉我为什么它不能提取导入的私钥

    [TestMethod]
    public void TestRsa()
    {
        var rsa = new RSACng(2048);
        ///Export private key to arrays
        var rsaParam = rsa.ExportParameters(true);
        byte[] yQ = new byte[rsaParam.Q.Length];
        byte[] yP = new byte[rsaParam.P.Length];

        byte[] yInverseQ = new byte[rsaParam.InverseQ.Length];
        byte[] yDP = new byte[rsaParam.DP.Length];
        byte[] yDQ = new byte[rsaParam.DQ.Length];

        //Public Part Key
        byte[] yPm = new byte[rsaParam.Modulus.Length];
        byte[] yPe = new byte[rsaParam.Exponent.Length];
        byte[] yD = new byte[rsaParam.D.Length];

        rsaParam.Q.CopyTo(yQ, 0);
        rsaParam.P.CopyTo(yP, 0);
        rsaParam.InverseQ.CopyTo(yInverseQ, 0);
        rsaParam.DP.CopyTo(yDP, 0);
        rsaParam.DQ.CopyTo(yDQ, 0);
        rsaParam.Modulus.CopyTo(yPm, 0);
        rsaParam.Exponent.CopyTo(yPe, 0);
        rsaParam.D.CopyTo(yD, 0);

        var encrypt = rsa.Encrypt(Encoding.UTF8.GetBytes("hi"), RSAEncryptionPadding.Pkcs1);

        ///Importing private key in another instance of RSACng
        var rsa2 = new RSACng(2048);
        RSAParameters rsaParameters = new RSAParameters()
        {
            Q = yQ,
            P = yP,
            InverseQ = yInverseQ,
            DP = yDP,
            D = yD,
            DQ = yDQ,
            Exponent = yPe,
            Modulus = yPm
        };
        rsa2.ImportParameters(rsaParameters);
        var decryptData = rsa2.Decrypt(encrypt, RSAEncryptionPadding.Pkcs1);
        Assert.AreEqual(Encoding.UTF8.GetString(decryptData), "hi");

        rsa2.ExportParameters(true);///How can I prevent exception here
  }

谢谢大家!

在 .NET Core 中,当您使用 ImportParameters 时,RSACng 对象应该处于可导出状态,在 .NET Framework 4.7.2 中也应该如此。

只要在使用密钥之前更改导出策略(通过尝试调用导出或执行 sign/decrypt/encrypt/verify 操作),就可以将其置于可导出状态。例如,这有效:

using (RSA rsa1 = new RSACng(2048))
using (RSACng rsa2 = new RSACng())
{
    rsa2.ImportParameters(rsa1.ExportParameters(true));

    rsa2.Key.SetProperty(
        new CngProperty(
            "Export Policy",
            BitConverter.GetBytes((int)CngExportPolicies.AllowPlaintextExport),
            CngPropertyOptions.Persist));

    RSAParameters params2 = rsa2.ExportParameters(true);
    Console.WriteLine(params2.D.Length);
}

使用 https://msdn.microsoft.com/en-us/library/windows/desktop/aa376242(v=vs.85).aspx 中描述的 NCRYPT_EXPORT_POLICY_PROPERTY