2013-03-02 2 views
2

Я пытаюсь проверить свой криптографический код и продолжать получать CyrptographicException «Заполнение недопустимы и не может быть удалено», когда когда-либо удаляется decrypt. Я получаю аналогичную ошибку, если попытаюсь прочитать за конец потока decrypt, хотя документация CryptoStream.Read указывает, что это не должно быть проблемой.Ошибка заполнения после частичного чтения финального блока

Упрощенный пример:

const int DATA_SET_SIZES = 102399; 

byte[] iv, 
     key, 
     startingData = new byte[DATA_SET_SIZES], 
     encryptedData = new byte[((DATA_SET_SIZES - 1)/16 + 2) * 16], 
     endingData = new byte[DATA_SET_SIZES];//[((DATA_SET_SIZES - 1)/16 + 1) * 16]; 
Random rand = new Random(); 

rand.NextBytes(startingData);  //Get test data. 

using (Rijndael cryptAlg = Rijndael.Create()) 
{ 
    cryptAlg.Mode = CipherMode.CBC; 
    cryptAlg.Padding = PaddingMode.ISO10126; 

    iv = cryptAlg.IV;    //Use random IV during test. 
    key = cryptAlg.Key;    //Use random Key during test. 
    using (CryptoStream encrypt = new CryptoStream(new MemoryStream(encryptedData), cryptAlg.CreateEncryptor(key, iv), CryptoStreamMode.Write)) 
    { 
     encrypt.Write(startingData, 0, startingData.Length); 
     encrypt.FlushFinalBlock(); 
    } 
    using (CryptoStream decrypt = new CryptoStream(new MemoryStream(encryptedData), cryptAlg.CreateDecryptor(key, iv), CryptoStreamMode.Read)) 
    { 
     int dataRecieved = decrypt.Read(endingData, 0, endingData.Length); 
    } 
} 

Если я одно из следующих действий, то исключение уходит:

  • Изменение cryptAlg.Padding = PaddingMode.None после выполнения шифрования, но перед созданием decrypt.
  • Изменить const int DATA_SET_SIZES = 102400 или любой другой кратный размер блока.
  • Не считывайте данные из последнего блока.

Выполняю ли я что-то неправильно или реализация .NET не распознает конец потока правильно?

Кроме того, кто-нибудь знает, почему зашифрованные данные на 1 блок больше, чем потребуется для хранения зашифрованных данных? Что в этом блоке?

ответ

2

Ваш буфер encryptedData слишком велик. Возьмите 15 байт, затем вы получите 32 блока буфера. Поскольку вы даете полный буфер конструктору MemoryStream, он будет считывать до конца потока. Блокировка дешифрования будет никогда сбой, поэтому единственное, что не получится, - это отступы. Последний блок, вероятно, содержит только нулевые значения, поэтому дешифрованное значение является случайным, а не соответствующим формату заполнения (большую часть времени).

Try: new byte[(DATA_SET_SIZES/16 +1) * 16]

+0

Я пытался, что раньше с 'DATA_SET_SIZES = 102400' и ​​получил' NotSupportedException' "поток памяти не расширяется.". Я просто попробовал снова с 'DATA_SET_SIZES = 102399' и' DATA_SET_SIZES = 102401', и он работал нормально. Я думаю, в буфере должен быть дополнительный байт для 'PaddingMode.ISO10126', чтобы указать, что конец был достигнут. Я обновил (удалил -1) и принял ваш ответ. Спасибо, я потратил на это несколько часов. – Trisped

+0

Ой, извините, забыли удалить -1. ISO 10126 (точно так же, как и почти одинаковое заполнение PKCS # 7) * всегда *, поэтому он добавляет полный блок, когда у вас есть 16 байтов текстовых данных. –