.NET - RSA не может декодировать

78
29 октября 2021, 13:30
    static string Encrypt(string str)
    {
        var bytes = Encoding.Default.GetBytes(str);
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        return Convert.ToBase64String(RSA.Encrypt(bytes, true));
    }
    static string Decrypt(string str)
    {
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        return Encoding.Default.GetString(RSA.Decrypt(Convert.FromBase64String(str), true));
    }

Ошибка идёт при RSA.Decrypt

Answer 1

Вы создаёте в двух методах два разных экземпляра RSACryptoServiceProvider. У них, вполне естественно, разные внутренние ключи.

Кроме того, вы используете Encoding.Default. Кодировка по умолчанию разная на разных машинах. Никогда не используйте в своём коде Default-кодировку!

Если в обоих методах использовать один и тот же экземпляр крипто-провайдера и какую-нибудь юникодную кодировку, то код работает:

// поле класса
static RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
static string Encrypt(string str)
{
    var bytes = Encoding.UTF8.GetBytes(str);
    return Convert.ToBase64String(RSA.Encrypt(bytes, true));
}
static string Decrypt(string str)
{
    return Encoding.UTF8.GetString(RSA.Decrypt(Convert.FromBase64String(str), true));
}

var source = "Привет";
var encrypted = Encrypt(source);
var decrypted = Decrypt(encrypted);
Console.WriteLine(source);
Console.WriteLine(decrypted);
Console.WriteLine(decrypted == source); // True

Смысл шифрования в том, чтобы передавать данные из одного места в другое, с одного компьютера на другой, например, по сети. Экземпляр класса передать нельзя. А вот ключи - можно.

В документации RSACryptoServiceProvider есть пример, как экспортировать и импортировать параметры провайдера.

Например, можно сделать так:

static (string, RSAParameters) Encrypt(string str)
{
    using (var rsa = new RSACryptoServiceProvider())
    {
        var parameters = rsa.ExportParameters(true);
        var bytes = Encoding.UTF8.GetBytes(str);
        var data = rsa.Encrypt(bytes, true);
        var encrypted = Convert.ToBase64String(data);
        return (encrypted, parameters);
    }
}
static string Decrypt(string str, RSAParameters parameters)
{
    using (var rsa = new RSACryptoServiceProvider())
    {
        rsa.ImportParameters(parameters);
        var data = Convert.FromBase64String(str);
        var bytes = rsa.Decrypt(data, true);
        return Encoding.UTF8.GetString(bytes);
    }
}
var source = "Привет";
var (encrypted, parameters) = Encrypt(source);
var decrypted = Decrypt(encrypted, parameters);
Console.WriteLine(source);
Console.WriteLine(decrypted);
Console.WriteLine(decrypted == source); // True

Из метода Encrypt возвращаем зашифрованную строку и параметры провайдера в виде кортежа.

В метод Decrypt, соответственно, тоже нужно передавать эти параметры.

Этот ключ, по идее, нужно сгенерировать один раз и где-то надёжно хранить.

READ ALSO
Записание в TextBox несколько раз подряд

Записание в TextBox несколько раз подряд

Возникла проблема, пишу программу на WPF и мне нужно заполнять TextBox Дело в том, что я заполняю TextBox последовательно после проверки разных условий

161
Style из ResourceDictionary в UserControl

Style из ResourceDictionary в UserControl

Создал проект следующего содержания:

121
Как добавить описание метода, доступное к просмотру через IntelliSense?

Как добавить описание метода, доступное к просмотру через IntelliSense?

Как можно написать свой метод и добавить описание? Использовали эту функцию IntelliSense, которая показывает описание методов?

194