Rijndael encrypter: получение пустого байта [].Ничего не шифруя - PullRequest
0 голосов
/ 10 июня 2019

Добрый вечер!

Я пытаюсь реализовать шифратор, используя алгоритм Rijndael и класс Rijndael в c #. Я пытался следовать (не делая точно такой же код) по ссылке ниже, но проблема в том, что в зашифрованной строке я не получаю никакого результата. Я тоже не получаю никаких сообщений об ошибках.

https://docs.microsoft.com/pt-br/dotnet/api/system.security.cryptography.rijndael?view=netframework-4.8

CryptDecrypt.cs

using System;
using System.IO;
using System.Security.Cryptography;
using System.Text;

namespace RijndaelAlgorithm {
    public class CryptDecrypt {
        private Byte[] iv;
        private Byte[] key; 

        public CryptDecrypt(String key) {
            iv = new Byte[] {21, 10, 21, 251, 132, 76, 121, 27, 210, 81, 215, 99, 14, 235, 11, 75};
            this.key = Encoding.ASCII.GetBytes(key);
        }

        public String encryptMsg(String originalMsg) {
            byte[] encryptedMsg;

            Rijndael rijAlg = Rijndael.Create();
            rijAlg.Key = formatKey();
            rijAlg.IV = iv;

            MemoryStream msEncrypt = new MemoryStream();
            ICryptoTransform encryptor = rijAlg.CreateEncryptor(rijAlg.Key, rijAlg.IV);
            CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write);

            StreamWriter swEncrypt = new StreamWriter(csEncrypt);
            swEncrypt.Write(originalMsg);

            encryptedMsg = msEncrypt.ToArray();
            Console.WriteLine("encryptedMsg.Length: " + encryptedMsg.Length);

            return Convert.ToBase64String(encryptedMsg, 0, encryptedMsg.Length);
        }

        private Byte[] formatKey() {
            int len = key.Length;

            String strKey = System.Text.Encoding.UTF8.GetString(key);
            String fillKey = "";
            String strFormatedKey = "";

            Byte[] formatedKeyByte;

            if (len < 16)
                fillKey = new String('X',(16 - len));

            strFormatedKey = String.Concat(strKey, fillKey);
            formatedKeyByte = Encoding.ASCII.GetBytes(strFormatedKey);

            return formatedKeyByte;
        }
    }
}

Menu.cs

using System;

namespace RijndaelAlgorithm {
    public class Menu {
        private CryptDecrypt r;

        public Menu() {
            r = new CryptDecrypt("123654");
        }

        public void showMenu() {
            Console.WriteLine("the encrypted message is: " + r.encryptMsg("isjustatest"));
        }
    }
}

1 Ответ

0 голосов
/ 12 июня 2019

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

Параметр

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

Этот сервис возвращает разные результаты при каждом нажатии клавиши, даже если вы используете один и тот же ввод.

Однако, если вы обычно берете разные зашифрованные результаты и расшифровываете их с помощью одного и того же ключа, вы получите исходные байты обратно.

Следующая проблема при тестировании с этой конкретной службой состоит в том, что они доставляют всегдатот же префикс последовательности base64 'U2FsdGVkX1'.Это не стандартный вывод AES (если вы декодируете эту последовательность base64, вы получаете 'Salted_P').Поэтому имеет смысл использовать другой онлайн-сервис для тестов.

Так что, если две реализации кодирования AES-256 используют одинаковые параметры, мы получим одинаковый кодированный результат.Нам нужно для этого:

  • Ключ (32 байта, а не 16 для AES-256)
  • IV (16 байтов)

Говоря о длине ключа: Как уже упоминалось в комментариях, вы не должны просто добавлять «X» или что-то подобное, а использовать стандартный криптографический механизм для получения хорошего ключа.

Для тестов удобны методы, которые преобразуют шестнадцатеричные строки в байтовые массивы.и обратно, например, посмотрите методы StringToByteArray и ByteArrayToString в этом классном ответе: https://stackoverflow.com/a/311179

Давайте попробуем.Если мы возьмем ваше сообщение «isjustatest» с шестнадцатеричной строкой «69736a7573746174657374374», нам понадобится 32-байтовый ключ для AES-256 и 16 байтов IV.

Как уже упоминалось в комментариях, вам нужно очиститьи закройте поток (или, что еще лучше, используйте оператор «using»).

Взяв свой код, измените назначение ключа и iv и выведите зашифрованное сообщение на консоль:

rijAlg.Key = StringToByteArray("519C7C3402A943D8AF83746C1548E475319EBDA6A38046059F83B21709BD6A5B"); //32 bytes
rijAlg.IV =  StringToByteArray("0D024CF947CE4C288880D0B34D29BFA5"); // 16 bytes
...
swEncrypt.Write(originalMsg);
swEncrypt.Flush();
swEncrypt.Close();
...
Console.WriteLine("encrypted bytes: '" + ByteArrayToString(encryptedMsg) + "'");

Это приводит к выводу «419536f27da3406625b2d07f43833aab» в консоли отладки.

Так что теперь мы можем использовать онлайн-сервис, например, https://cryptii.com/pipes/aes-encryption, где мы можем вводить входные данные, выбирать алгоритм шифрования, предоставлятьключевые и IV байты, а затем мы получаем тот же результат, что и в вашей программе, см. скриншот здесь:

enter image description here

Как упоминалось выше, не забудьтеиспользовать разные случайные IV при использовании его в реальном приложении.

...