C # - AESCng Почему шифровать / дешифровать байтовый массив больше 127 неправильно? - PullRequest
0 голосов
/ 05 июня 2018

когда я шифрую и дешифрую байт [128] {1, 2, ..., 126, 127} с помощью AES, все в порядке:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array 0-127
byte[] raw = new byte[128];
for (byte i = 0; i < 128; i++)
{
    raw[i] = i;
}

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

при расшифровке будет выводиться байт [128] {1, 2, ..., 126, 127}.но когда я заменяю raw на byte [127] {128, 129, ..., 253, 254} на ту же логику шифрования / дешифрования, результат становится байтом [381], внутри - циклы [239, 191, 189]:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array 128-254    
byte[] raw = new byte[127];
for (byte i = 128; i <= 254; i++)
{
    raw[i-128] = i;
}

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

теперь расшифрованный будет выводить байт [381] {239, 191, 189, ..., 239, 191, 189}

при запуске я думал, что более 127 отличаетсядо тех пор, пока я не обнаружил, что следующий байтовый массив также работает:

// Create Key & iv
byte[] key = GenerateKey();
byte[] iv = GenerateIV();

// Create raw byte array from Poruguese ÇÃ
string rawPortuguese = "ÇÃ";
byte[] raw = Encoding.UTF8.GetBytes(rawPortuguese);

теперь необработанным является байт [4] {195, 135, 195, 131}, каждая цифра больше 127.

// Encrypt
var encrypted = Encrypt(raw, key, iv);
// Decrypt
var decrypted = Decrypt(encrypted, key, iv);

но также может правильно расшифровываться, расшифровывается как байт [4] {195, 135, 195, 131}, теперь я совершенно запутался, почему байт необработанных данных [127] {128, 129, ..., 253,254} не может правильно расшифровать?

Ключ / IV / Шифрование / Код дешифрования:

static byte[] GenerateKey()
{
    using (AesCng cng = new AesCng())
    {
        cng.GenerateKey();
        return cng.Key;
    }
}

static byte[] GenerateIV()
{
    using (AesCng cng = new AesCng())
    {
        cng.GenerateIV();
        return cng.IV;
    }
}

static byte[] Encrypt(byte[] raw, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    byte[] encrypted;

    using (AesCng cng = new AesCng())
    {
        cng.Mode = mode;
        cng.Padding = padding;

        cng.Key = key;
        cng.IV = iv;

        using (ICryptoTransform encryptor = cng.CreateEncryptor())
        using (MemoryStream msEncrypt = new MemoryStream())
        {
            using (CryptoStream csEncrypt = new CryptoStream(msEncrypt, encryptor, CryptoStreamMode.Write))
            {
                csEncrypt.Write(raw, 0, raw.Length);
            }

            encrypted = msEncrypt.ToArray();
        }
    }

    return encrypted;
}

static byte[] Decrypt(byte[] encrypted, byte[] key, byte[] iv, CipherMode mode = CipherMode.CBC, PaddingMode padding = PaddingMode.PKCS7)
{
    byte[] decryptedData;
    string plaintext = null;
    byte[] plainData = null;

    using (AesCng cng = new AesCng())
    {
        cng.Mode = mode;
        cng.Padding = padding;

        cng.Key = key;
        decryptedData = encrypted;
        cng.IV = iv;

        using (ICryptoTransform decryptor = cng.CreateDecryptor())
        {
            using (MemoryStream msDecrypt = new MemoryStream(decryptedData))
            {
               using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
               {
                    using (StreamReader srDecrypt = new StreamReader(csDecrypt))
                    {
                        plaintext = srDecrypt.ReadToEnd();
                    }
                    plainData = Encoding.UTF8.GetBytes(plaintext);
                }
            }
        }
    }

    return plainData;
}

1 Ответ

0 голосов
/ 05 июня 2018

Это проблема:

using (StreamReader srDecrypt = new StreamReader(csDecrypt))
{
    plaintext = srDecrypt.ReadToEnd();
}
plainData = Encoding.UTF8.GetBytes(plaintext);

Вы обрабатываете текстовые данные как UTF-8, конвертируете их в строку, а затем конвертируете обратно в байты (используя UTF-8).снова).Это нормально, если текстовые данные на самом деле являются текстом в кодировке UTF-8 (как в вашем португальском примере), но это не относится к произвольному байтовому массиву.Последовательность байтов 0x80, 0x81, 0x82, 0x83 ... 0xff недопустима UTF-8.

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

Если вы просто хотите эффективно читать из произвольного потока и создавать из него массив, используйте другой MemoryStream, скопируйте в него данные, затем используйте MemoryStream.ToArray чтобы преобразовать его в byte[]:

using (CryptoStream csDecrypt = new CryptoStream(msDecrypt, decryptor, CryptoStreamMode.Read))
{
    using (var plainData = new MemoryStream())
    {
        csDescrypt.CopyTo(plainData);
        return plainData.ToArray();
    }
}
...