Процедура шифрования не работает, не могу понять, в ней есть тонкая ошибка

#c# #.net #encryption #cryptography

Вопрос:

Все,

Пожалуйста, посмотрите на код ниже. Код шифрования и дешифрования работает неправильно. Когда я передаю строку «Привет, мир», я получаю ответ «Привет, во». Я всегда теряю байты и не могу понять, почему. Должна быть какая-то причина для этого, тонкая ошибка?

 private static void _TestEncryption2()
    {
        var testText = "Hello world";
        var plainBytes = Encoding.Unicode.GetBytes(testText);
        
        var cipher = Rijndael.Create();
        cipher.Padding = PaddingMode.PKCS7;
        //var _key = Convert.FromBase64String(KEY);
        //var _IV = Convert.FromBase64String(IV);
        var _key = cipher.Key;
        var _IV = cipher.IV;

        byte[] cipherBytes;
        byte[] decryptedBytes;


        var enc = cipher.CreateEncryptor(_key, _IV);
        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, enc, CryptoStreamMode.Write))
            {
                cryptoStream.Write(plainBytes, 0, plainBytes.Length);
            }
            cipherBytes = memoryStream.ToArray();
        }

        var dec = cipher.CreateDecryptor(_key, _IV);
        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, dec, CryptoStreamMode.Write))
            {
                cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);

                decryptedBytes = memoryStream.ToArray();
            }
        }

        var decryptedText = Encoding.Unicode.GetString(decryptedBytes);
    }
 

Ответ №1:

Избавьтесь от своего второго cryptoStream , прежде чем делать memoryStream.ToArray() :

         var dec = cipher.CreateDecryptor(_key, _IV);
        using (var memoryStream = new MemoryStream())
        {
            using (var cryptoStream = new CryptoStream(memoryStream, dec, CryptoStreamMode.Write))
            {
                cryptoStream.Write(cipherBytes, 0, cipherBytes.Length);
            }

            // Here
            decryptedBytes = memoryStream.ToArray();
        }
 

Проблема в том, что второй CryptoStream не был сброшен до того, как вы прочитали его вывод, и он все еще удерживает этот последний блок внутри.

Размер вашего блока составляет 16 байт, и вы используете UTF-16, который использует 2 байта на символ, поэтому тот факт, что вы получаете первый блок из 8 символов (16 байт), но не последний блок, имеет смысл здесь.


Кроме того, Encoding.Unicode это UTF-16, что является немного странным выбором в наши дни. По умолчанию должно быть Encoding.UTF8 .

Комментарии:

1. Вау, как я это пропустил 🙁 Спасибо!!! Мы выбрали UTF16, чтобы он соответствовал размеру строки Юникода в файле .net. Теперь, когда я думаю об этом, UTF8 был бы более эффективным, поскольку мы говорим о кодировании.

2. Все неправильно понимают порядок утилизации криптографических материалов. Я увидел название и заподозрил это; прочитал описание и знал наверняка, еще до того, как прочитал код. Ты в хорошей компании!