RSA шифрование на C#

721
04 мая 2017, 11:13

Хочу сделать простую шифровку алгоритмом RSA встроенными в .Net средствами. Как я это вижу:

  1. Создаем объект RSA.
  2. Из него получаем открытый и приватный ключи, сохраняем их.
  3. Зашифровываем сообщение при помощи открытого ключа.
  4. Зашифрованное в п.3 сообщение можем расшифровать при помощи приватного ключа.

Набросал по-быстрому демо для этого, в нем в textBox1 находится текст, который я хочу зашифровать, по клику на button1 происходит шифрование и результат помещается в textBox2; в textBox3, соответственно, мы можем поместить зашифрованное сообщение, а по нажатию на button2 расшифровать его и увидеть результат в textBox4.

Исходный код (методы RSAEn(-De)crypt взял с сайта MSDN):

public partial class Form1 : Form
    {
        RSAParameters privateKey;
        RSAParameters publicKey;
        public Form1()
        {
            InitializeComponent();
            //Пункт 1
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            //Пункт 2
            privateKey = RSA.ExportParameters(true);
            publicKey = RSA.ExportParameters(false);
        }
        private void button1_Click(object sender, EventArgs e)
        {
            UnicodeEncoding byteConverter = new UnicodeEncoding();
            byte[] input = byteConverter.GetBytes(textBox1.Text);
            byte[] output;
            //Пункт 3
            output = RSAEncrypt(input, publicKey, false);
            textBox2.Text = byteConverter.GetString(output);
        }
        private void button2_Click(object sender, EventArgs e)
        {
            UnicodeEncoding byteConverter = new UnicodeEncoding();
            byte[] input = byteConverter.GetBytes(textBox3.Text);
            byte[] output;
            //Пункт 4
            output = RSADecrypt(input, privateKey, false);
            textBox4.Text = byteConverter.GetString(output);
        }
        static public byte[] RSAEncrypt(byte[] DataToEncrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
        {
                //Create a new instance of RSACryptoServiceProvider.
                RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
                //Import the RSA Key information. This only needs
                //toinclude the public key information.
                RSA.ImportParameters(RSAKeyInfo);
                //Encrypt the passed byte array and specify OAEP padding.  
                //OAEP padding is only available on Microsoft Windows XP or
                //later.  
                return RSA.Encrypt(DataToEncrypt, DoOAEPPadding);
        }
        static public byte[] RSADecrypt(byte[] DataToDecrypt, RSAParameters RSAKeyInfo, bool DoOAEPPadding)
        {
            //Create a new instance of RSACryptoServiceProvider.
            RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
            //Import the RSA Key information. This needs
            //to include the private key information.
            RSA.ImportParameters(RSAKeyInfo);
            //Decrypt the passed byte array and specify OAEP padding.  
            //OAEP padding is only available on Microsoft Windows XP or
            //later.  
            return RSA.Decrypt(DataToDecrypt, DoOAEPPadding);
        }
    }

Шифрует он всё нормально, но при дешифровке выдает CryptographicException, "Дополнительные сведения: Параметр задан неверно." Гугление ошибки результатов не дало. Что я делаю не так?

Answer 1

Ошибка находится в byteConverter, ошибка возникает из-за того, что конвертер преобразуя в строку и обратно изменяет количество байт.

Для того, чтобы избежать эту ошибку используйте лучше Base64String:

Convert.ToBase64String();
Convert.FromBase64String();

Это гарантирует сохранность байт.

Вот пример консольного приложения для проверки:

    static void Main(string[] args)
    {
        RSACryptoServiceProvider RSA = new RSACryptoServiceProvider();
        //Пункт 2
        privateKey = RSA.ExportParameters(true);
        publicKey = RSA.ExportParameters(false);
        UnicodeEncoding byteConverter = new UnicodeEncoding();
        string toEncrypt = "Hello, world";
        Console.WriteLine($"To encode: {toEncrypt}");
        byte[] encBytes = RSAEncrypt(byteConverter.GetBytes(toEncrypt), publicKey, false);
        string encrypt = byteConverter.GetString(encBytes);
        Console.WriteLine("Encrypt str: " + encrypt);
        Console.WriteLine("Encrypt bytes: " + string.Join(", ", encBytes));
        byte[] decBytes = RSADecrypt(encBytes, privateKey, false);
        Console.WriteLine("Decrypt str: " + byteConverter.GetString(decBytes));
        Console.WriteLine("Decrypt bytes: " + string.Join(", ", byteConverter.GetBytes(encrypt)));
        Console.ReadKey();
    }
READ ALSO
Преобразование JSON в XML

Преобразование JSON в XML

ЗдравствуйтеЕсть сайт http://www

459
Почему не выводит имя объекта через foreach?

Почему не выводит имя объекта через foreach?

Данные получаю с формыПочему не выводится имя ?

295
Как получать значение города из строки?

Как получать значение города из строки?

Пытаюсь работать с Callback VKХотелось бы сделать простенький прогноз, но для этого пользователю нужно указать город

306