C # Aes byte [] Encrypt / Decrypt: не полный блок - PullRequest
0 голосов
/ 13 мая 2018

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

= byte [] plain => MyEnc (plain) => byte [] encrypted => MyDec (encrypt) => byte [] plain

Простые и зашифрованные имеют одинаковую длину.

Это мой код шифрования:

public static byte[] MyEnc(byte[] Input)
    {
        byte[] inputencdec = Input;
        byte[] encrypted;
        using (MemoryStream mstream = new MemoryStream())
        {
            using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
            {
                encdec.BlockSize = 128;
                encdec.KeySize = 256;
                encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
                encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
                ICryptoTransform icrypt = encdec.CreateEncryptor(encdec.Key, encdec.IV);

                using (CryptoStream cryptoStream = new CryptoStream(mstream,
                    icrypt, CryptoStreamMode.Write))
                {
                    cryptoStream.Write(inputencdec, 0, inputencdec.Length);
                }

            }
            encrypted = mstream.ToArray();
        }

        return encrypted;
    }

это мой код расшифровки:

public static byte[] MyDec(byte[] Input)
    {
        byte[] inputencdec = Input;
        byte[] buffer = new byte[Input.Length];
        int totalRead = 0;
        byte[] plain;

        MemoryStream plainStream = new MemoryStream();

        using (MemoryStream mStream = new MemoryStream(inputencdec))
        {
            using (AesCryptoServiceProvider encdec = new AesCryptoServiceProvider())
            {
                encdec.BlockSize = 128;
                encdec.KeySize = 256;
                encdec.Key = ASCIIEncoding.ASCII.GetBytes(Key);
                encdec.IV = ASCIIEncoding.ASCII.GetBytes(IV);
                ICryptoTransform icrypt = encdec.CreateDecryptor(encdec.Key, encdec.IV);

                using (CryptoStream cryptoStream = new CryptoStream(mStream, icrypt, CryptoStreamMode.Read))
                {
                    while (true)
                    {
                        int read = cryptoStream.Read(buffer, 0, inputencdec.Length);

                        if (read == 0)
                            break;
                        else
                            plainStream.Write(buffer, totalRead, read);

                        totalRead += read;
                    }

                }
            }

            plain = plainStream.ToArray();
        }

        return plain;
    }

1 Ответ

0 голосов
/ 13 мая 2018

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

Режимы потоковой передачи не нужнырасширять зашифрованный текст, так как они не требуют заполнения.К сожалению, Microsoft решила не включать режим счетчика в .NET.Вы можете использовать режим CFB.

Вы также можете решить внедрить режим счетчика с использованием ECB, если вам требуется параллельное шифрование (в комментариях под вопросом).Обычно AES настолько быстр, что параллелизм не требуется.Реализация счетчика статического размера и буфера CTR должна побледнеть по сравнению с созданием многопоточного кода.


Это неверно и может вызвать проблему:

int read = cryptoStream.Read(buffer, 0, inputencdec.Length);

Вы, конечно, должны поставитьв buffer.length, а не inputencdec.length.Использование буфера для хранения данных в буфере путем считывания до buffer.length байтов за цикл.

Это также неверно:

plainStream.Write(buffer, totalRead, read);

проблема в том, чтоtotalRead должно быть смещением в buffer, а не смещением в потоке .Вы читаете в смещение 0 буфера, поэтому вы должны начать запись также со смещения 0.


Вы также можете создать MemoryStream для открытого текста, обернуть его CryptoStreamиспользуя расшифровщик, а затем напишите зашифрованный текст все за один раз.Насколько я вижу, для шифрования / дешифрования нет необходимости использовать другую схему.Кажется, вы все равно сохраняете весь открытый / зашифрованный текст в памяти.


Примечания:

  • для режима CBC IV должен быть случайным;он часто добавляется к зашифрованному тексту и удаляется и используется расшифровщиком; ключи
  • и IV должны состоять из случайных байтов;они должны не быть строками.
...