Я поискал в Интернете, что означает это исключение по отношению к моей программе, но не могу найти решения или причины, по которой это происходит с моей конкретной программой. Я использовал пример, предоставленный моим msdn, для шифрования и дешифрования XmlDocument с использованием алгоритма Rijndael. Шифрование работает нормально, но когда я пытаюсь расшифровать, я получаю следующее исключение:
Заполнение недействительно и не может быть удалено
Может ли кто-нибудь сказать мне, что я могу сделать, чтобы решить эту проблему? В приведенном ниже коде я получаю ключ и другие данные. Если cryptoMode имеет значение false, он вызовет метод дешифрования, в котором возникает исключение:
public void Cryptography(XmlDocument doc, bool cryptographyMode)
{
RijndaelManaged key = null;
try
{
// Create a new Rijndael key.
key = new RijndaelManaged();
const string passwordBytes = "Password1234"; //password here
byte[] saltBytes = Encoding.UTF8.GetBytes("SaltBytes");
Rfc2898DeriveBytes p = new Rfc2898DeriveBytes(passwordBytes, saltBytes);
// sizes are devided by 8 because [ 1 byte = 8 bits ]
key.IV = p.GetBytes(key.BlockSize/8);
key.Key = p.GetBytes(key.KeySize/8);
if (cryptographyMode)
{
Ecrypt(doc, "Content", key);
}
else
{
Decrypt(doc, key);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Clear the key.
if (key != null)
{
key.Clear();
}
}
}
private void Decrypt(XmlDocument doc, SymmetricAlgorithm alg)
{
// Check the arguments.
if (doc == null)
throw new ArgumentNullException("Doc");
if (alg == null)
throw new ArgumentNullException("alg");
// Find the EncryptedData element in the XmlDocument.
XmlElement encryptedElement = doc.GetElementsByTagName("EncryptedData")[0] as XmlElement;
// If the EncryptedData element was not found, throw an exception.
if (encryptedElement == null)
{
throw new XmlException("The EncryptedData element was not found.");
}
// Create an EncryptedData object and populate it.
EncryptedData edElement = new EncryptedData();
edElement.LoadXml(encryptedElement);
// Create a new EncryptedXml object.
EncryptedXml exml = new EncryptedXml();
// Decrypt the element using the symmetric key.
byte[] rgbOutput = exml.DecryptData(edElement, alg); <---- I GET THE EXCEPTION HERE
// Replace the encryptedData element with the plaintext XML element.
exml.ReplaceData(encryptedElement, rgbOutput);
}
c#
cryptography
Коричневая любовь
источник
источник
Ответы:
Rijndael / AES - это блочный шифр. Он шифрует данные блоками по 128 бит (16 символов). Криптографическое заполнение используется, чтобы гарантировать, что последний блок сообщения всегда имеет правильный размер.
Ваш метод дешифрования ожидает заполнения по умолчанию и не находит его. Как говорит @NetSquirrel, вам необходимо явно установить заполнение как для шифрования, так и для дешифрования. Если у вас нет причин поступить иначе, используйте заполнение PKCS # 7.
источник
alg.Padding = PaddingMode.PKCS7;
Убедитесь, что ключи, которые вы используете для шифрования и дешифрования , одинаковы . Метод заполнения, даже если он не установлен явно, должен по-прежнему обеспечивать правильное дешифрование / шифрование (если не задано, они будут такими же). Однако , если вы по какой - то причине используют другой набор ключей для расшифровки , чем используемый для шифрования вы будете получать эту ошибку:
Если вы используете какой-либо алгоритм для динамической генерации ключей, это не сработает. Они должны быть одинаковыми как для шифрования, так и для дешифрования. Один из распространенных способов состоит в том, чтобы вызывающий объект предоставил ключи в конструкторе класса методов шифрования, чтобы предотвратить участие процесса шифрования / дешифрования в создании этих элементов. Он сосредоточен на задаче (шифрование и дешифрование данных) и требует
iv
иkey
должны быть предоставлена вызывающим.источник
В интересах поиска людей, возможно, стоит проверить расшифровку входных данных. В моем случае информация, отправляемая для дешифрования, была (ошибочно) введена как пустая строка. Это привело к ошибке заполнения.
Это может относиться к ответу Россума, но подумал, что стоит упомянуть.
источник
Если один и тот же ключ и вектор инициализации используются для кодирования и декодирования, эта проблема возникает не из-за декодирования данных, а из-за кодирования данных.
После того, как вы вызвали метод Write для объекта CryptoStream, вы должны ВСЕГДА вызывать метод FlushFinalBlock перед методом Close.
В документации MSDN по методу CryptoStream.FlushFinalBlock говорится:
« Вызов метода Close вызовет FlushFinalBlock ... »
https://msdn.microsoft.com/en-US/library/system.security.cryptography.cryptostream.flushfinalblock(v=vs .110) .aspx
Это неверно. Вызов метода Close просто закрывает CryptoStream и выходной поток.
Если вы не вызываете FlushFinalBlock перед Close после того, как вы записали данные для шифрования, при расшифровке данных вызов метода Read или CopyTo в вашем объекте CryptoStream вызовет исключение CryptographicException (сообщение: «Заполнение недопустимо и не может быть удалено»).
Это, вероятно, верно для всех алгоритмов шифрования, производных от SymmetricAlgorithm (Aes, DES, RC2, Rijndael, TripleDES), хотя я только что проверил это для AesManaged и MemoryStream в качестве выходного потока.
Итак, если вы получаете это исключение CryptographicException при расшифровке, прочтите значение свойства Output Stream Length после того, как вы записали данные для шифрования, затем вызовите FlushFinalBlock и снова прочитайте его значение. Если он изменился, вы знаете, что вызов FlushFinalBlock НЕ является необязательным.
И вам не нужно выполнять какие-либо дополнения программно или выбирать другое значение свойства Padding. Заполнение - это задание метода FlushFinalBlock.
.........
Дополнительное замечание для Кевина:
Да, CryptoStream вызывает FlushFinalBlock перед вызовом Close, но уже слишком поздно: когда вызывается метод CryptoStream Close, выходной поток также закрывается.
Если ваш выходной поток является MemoryStream, вы не можете прочитать его данные после его закрытия. Таким образом, вам нужно вызвать FlushFinalBlock в своем CryptoStream перед использованием зашифрованных данных, записанных в MemoryStream.
Если ваш выходной поток - FileStream, дела обстоят хуже, потому что запись буферизуется. В результате последние записанные байты могут не быть записаны в файл, если вы закроете выходной поток перед вызовом Flush для FileStream. Поэтому перед вызовом Close в CryptoStream вам сначала нужно вызвать FlushFinalBlock в своем CryptoStream, а затем вызвать Flush в своем FileStream.
источник
Stream.Close()
звонковthis.Dispose(true)
. Код дляCryptoStream.Dispose(bool)
:if (disposing) { if (!this._finalBlockTransformed) { this.FlushFinalBlock(); } this._stream.Close(); }
Сервал времен боев, я наконец решил проблему.
(Примечание: в качестве симметричного алгоритма я использую стандартный AES. Этот ответ может подойти не всем.)
RijndaelManaged
класс наAESManaged
один.KeySize
класс алгоритма, оставил их по умолчанию.(Это очень важный шаг. Я думаю, что в свойстве KeySize есть ошибка.)
Вот список, который вы хотите проверить, какой аргумент вы могли пропустить:
(байтовый массив, длина должна быть ровно одной из 16, 24, 32 байтов для разного размера ключа.)
(байтовый массив, 16 байт)
(один из CBC, CFB, CTS, ECB, OFB)
(один из ANSIX923, ISO10126, None, PKCS7, Zeros)
источник
KeySize
устранила это для меня. О причуды .NET :-(Моя проблема заключалась в том, что passPhrase для шифрования не соответствовал passPhrase для дешифрования ... поэтому он выдал эту ошибку ... немного вводит в заблуждение.
источник
Решение, исправившее мое, заключалось в том, что я случайно применил разные ключи к методам шифрования и дешифрования.
источник
Я столкнулся с этой ошибкой при попытке передать незашифрованный путь к файлу методу Decrypt. Решение заключалось в том, чтобы сначала проверить, зашифрован ли переданный файл, прежде чем пытаться расшифровать.
источник
Другой сценарий, опять же в интересах поиска людей.
Для меня эта ошибка возникла во время метода Dispose (), который замаскировал предыдущую ошибку, не связанную с шифрованием.
После исправления другого компонента это исключение исчезло.
источник
Я столкнулся с этой ошибкой заполнения, когда вручную редактировал зашифрованные строки в файле (используя блокнот), потому что хотел проверить, как будет вести себя функция дешифрования, если мой зашифрованный контент был изменен вручную.
Решением для меня было разместить
Как я уже сказал, моя ошибка заполнения была связана с тем, что я вручную набирал расшифрованный текст с помощью блокнота. Может быть, мой ответ поможет вам найти решение.
источник
У меня была такая же ошибка. В моем случае это произошло потому, что я сохранил зашифрованные данные в базе данных SQL. Таблица, в которой хранятся данные, имеет двоичный (1000) тип данных. При получении данных из базы данных он расшифровывает эти 1000 байтов, тогда как на самом деле там было 400 байтов. Таким образом, удаление конечных нулей (600) из результата решило проблему.
источник
У меня была эта ошибка, и я явно устанавливал размер блока:
aesManaged.BlockSize = 128;
Как только я удалил это, все заработало.
источник
У меня была такая же проблема при переносе программы Go на C #. Это означает, что с помощью программы Go уже было зашифровано много данных. Теперь эти данные необходимо расшифровать с помощью C #.
Окончательное решение было
PaddingMode.None
точнееPaddingMode.Zeros
.Криптографические методы в Go:
... и ...
Теперь расшифровка на C #:
Как можно объяснить проблему с заполнением? Непосредственно перед шифрованием программа Go проверяет заполнение:
Важная часть заключается в следующем:
Создается новый массив соответствующей длины, так что длина кратна размеру блока. Этот новый массив заполнен нулями. Затем метод копирования копирует в него существующие данные. Гарантируется, что новый массив больше существующих данных. Соответственно в конце массива стоят нули.
Таким образом, код C # может использовать
PaddingMode.Zeros
. АльтернативаPaddingMode.None
просто игнорирует любые отступы, что также работает. Надеюсь, этот ответ будет полезен всем, кому нужно переносить код с Go на C # и т. Д.источник
Клиент сообщил мне об этой же ошибке. Я лично не могу это воспроизвести. Если посмотреть на код методов Encrypt и Decrypt , у обоих Padding установлено значение PaddingMode.PKCS7 . Расшифровка выглядит так, и я не вижу в ней проблемы с « FlushFinalBlock ». Может кто-нибудь пролить свет на это?
источник
У меня была такая же ошибка. В моем случае данный пароль больше 16 означает, что он зашифрован, но при расшифровке я получаю эту ошибку. Шифрование:
Дешифрирование:
источник