Невозможно экспортировать PrivateKey перед импортом с помощью RSACng и RsaParameter

следующий модульный тест экспортирует закрытый ключ и сохраняет его в массивах байтов с использованием экземпляра rsa, затем зашифрует сообщение «привет», здесь все в порядке, но проблема возникает, когда он создает экземпляр rsa2 и импортирует предыдущий закрытый ключ в RSAParameter, тогда сообщение может будет расшифрован после импорта приватного ключа, но выдает исключение, когда вы пытаетесь экспортировать приватный ключ rsa2.

Скажите, пожалуйста, почему он не может извлечь импортированный закрытый ключ?

    [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
  }

Спасибо всем!


person Juan Pablo    schedule 06.02.2018    source источник
comment
Что делать, если вы используете rsa2.ImportParameters (rsaParam)?   -  person Jeroen Heier    schedule 06.02.2018
comment
Я не могу, потому что мой закрытый ключ хранится в массиве байтов, поэтому в реальной жизни у него нет объекта rsaParam, резюмировал я, чтобы сделать его более понятным   -  person Juan Pablo    schedule 06.02.2018
comment
В любом случае, когда назначается rsaParam, он также вызывает исключение.   -  person Juan Pablo    schedule 06.02.2018
comment
Я считаю, что это исправлено в net472. blogs.msdn.microsoft.com/dotnet/2018/02/05/   -  person bartonjs    schedule 06.02.2018


Ответы (1)


В .NET Core объект RSACng должен находиться в экспортируемом состоянии при использовании ImportParameters, как и в .NET Framework 4.7.2.

Вы можете перейти в экспортируемое состояние, если измените политику экспорта перед использованием ключа (путем попытки вызвать Export или выполнить операцию подписи / дешифрования / шифрования / проверки). Например, это работает:

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);
}

Используя NCRYPT_EXPORT_POLICY_PROPERTY, описанный на https://msdn.microsoft.com/en-us/library/windows/desktop/aa376242(v=vs.85).aspx.

person bartonjs    schedule 06.02.2018