Почему неверный пароль, потому что "обивка является недействительным и не может быть удален, и"?

Мне нужно простое шифрование строк, поэтому я написал следующий код (с большим-то "Вдохновение" От здесь):

    // create and initialize a crypto algorithm
    private static SymmetricAlgorithm getAlgorithm(string password) {
        SymmetricAlgorithm algorithm = Rijndael.Create();
        Rfc2898DeriveBytes rdb = new Rfc2898DeriveBytes(
            password, new byte[] {
            0x53,0x6f,0x64,0x69,0x75,0x6d,0x20,             // salty goodness
            0x43,0x68,0x6c,0x6f,0x72,0x69,0x64,0x65
        }
        );
        algorithm.Padding = PaddingMode.ISO10126;
        algorithm.Key = rdb.GetBytes(32);
        algorithm.IV = rdb.GetBytes(16);
        return algorithm;
    }

    /* 
     * encryptString
     * provides simple encryption of a string, with a given password
     */
    public static string encryptString(string clearText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] clearBytes = System.Text.Encoding.Unicode.GetBytes(clearText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateEncryptor(), CryptoStreamMode.Write);
        cs.Write(clearBytes, 0, clearBytes.Length);
        cs.Close();
        return Convert.ToBase64String(ms.ToArray());
    }

    /*
     * decryptString
     * provides simple decryption of a string, with a given password
     */
    public static string decryptString(string cipherText, string password) {
        SymmetricAlgorithm algorithm = getAlgorithm(password);
        byte[] cipherBytes = Convert.FromBase64String(cipherText);
        MemoryStream ms = new MemoryStream();
        CryptoStream cs = new CryptoStream(ms, algorithm.CreateDecryptor(), CryptoStreamMode.Write);
        cs.Write(cipherBytes, 0, cipherBytes.Length);
        cs.Close();            
        return System.Text.Encoding.Unicode.GetString(ms.ToArray());
    }

Код, кажется, работает нормально, за исключением того, что при расшифровке данных с <у>неправильные</п> ключ, я получаю CryptographicException - то "обивка является недействительным и не может быть удален, то" - на КС.Рядом (линия) в decryptString.

пример кода:

    string password1 = "password";
    string password2 = "letmein";
    string startClearText = "The quick brown fox jumps over the lazy dog";
    string cipherText = encryptString(startClearText, password1);
    string endClearText = decryptString(cipherText, password2);     // exception thrown

На мой вопрос, это можно ожидать? Я бы подумал, что расшифровки с неправильным паролем будет просто результат глупости, а не исключение.

Комментарии к вопросу (1)
Решение

Хотя это уже ответил, Я думаю, что это будет хорошая идея, чтобы объяснить, почему следует ожидать.

Схемы заполнения обычно применяется потому, что большинство криптографических фильтры не семантически безопасной и предотвратить некоторые формы cryptoatacks. Например, обычно в ОГА УАМИАЭ используется схема, которая предотвращает некоторые виды атак (например, выбранного открытого текста атака или ослепление).

Схема обивка добавляет некоторые (как правило) случайного мусора на сообщение м перед отправкой сообщения. В методе УАМИАЭ, например, два слова используются (это упрощенное объяснение):

  1. Учитывая размер модуля вы падд К1 биты с 0 и К0 биты случайного числа.
  2. Затем, применяя некоторые преобразования на сообщение, вы получаете мягкий которым сообщение шифруется и отправляется.

Что предоставляет вам рандомизации сообщений и проверить, если сообщение является мусором или нет. Как прокладывать схема является обратимой, когда вы расшифровать сообщение, в то время как вы можете'т сказать ничего про целостность самого сообщения Вы можете, на самом деле, сделать какое-то утверждение о заполнение и, таким образом, вы можете знать, если сообщение было правильно расшифровать или вы'вновь что-то делаю неправильно (я.е изменения сообщения или вы're, используя неправильный ключ)

Комментарии (4)

Я пережил похожую на "обивка является недействительным и не может быть удален.&я исключение, но в моем случае ключ IV и обивка были правильными.

Оказалось, что топить крипто поток все, что не хватало.

Как это:

            MemoryStream msr3 = new MemoryStream();
            CryptoStream encStream = new CryptoStream(msr3, RijndaelAlg.CreateEncryptor(), CryptoStreamMode.Write);
            encStream.Write(bar2, 0, bar2.Length);
            // unless we flush the stream we would get "Padding is invalid and cannot be removed." exception when decoding
            encStream.FlushFinalBlock();
            byte[] bar3 = msr3.ToArray();
Комментарии (5)

Если вы хотите, чтобы ваш использование, чтобы быть правильным, Вы должны добавить проверка подлинности в свой текст, так что вы можете убедитесь, что это правильный пароль или что шифротекст не'т быть изменены. Прокладки вы используете ISO10126 будет только выдать исключение, если последний байт не'т расшифровать как один из 16 допустимых значений для заполнения (0х01-0х10). Поэтому у вас есть шанс 1/16 это не бросать исключение с неправильным паролем, если вы проверить его подлинность вы детерминированный способ сказать, если ваш расшифровки действует.

Используя крипто АПИ's хотя, казалось бы, простой, на самом деле довольно легко сделать ошибки. Например, можно использовать фиксированный соль Для для вас ключ и IV деривации, это означает, что каждый шифротекст зашифрованный пароль будет повторно использовать это'с IV с помощью этого ключа, что нарушает смысловое безопасности в режиме CBC, на ИВ должен быть непредсказуемым и уникальным для данного ключа.

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

Современные примеры симметричных аутентифицированного шифрования строки c#.

Если вы используете его'ы `AESThenHMAC.AesSimpleDecryptWithPassword(шифр, пароль) при неправильном вводе пароля используется значение null возвращается, если шифротекст или IV был изменен после шифрования значение null возвращается, вы никогда не получите ненужных данных, или прокладка исключение.

Комментарии (0)

Если вы'ве исключено, ключ-несоответствие, то кроме FlushFinalBlock () (см. Янив&#39;ы ответ), вызываю метод close() на `поток cryptostream также будет достаточно.

Если вы не убираю строго ресурсов с использованием блоков, убедитесь, что гнездо в блоке для самого поток cryptostream:

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
{
  using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
  {
    encStream.Write(bar2, 0, bar2.Length);
  } // implicit close
  byte[] encArray = ms.ToArray();
}

Я'вэ укусила этот (или подобный):

using (MemoryStream ms = new MemoryStream())
using (var enc = RijndaelAlg.CreateEncryptor())
using (CryptoStream encStream = new CryptoStream(ms, enc, CryptoStreamMode.Write))
{
  encStream.Write(bar2, 0, bar2.Length);
  byte[] encArray = ms.ToArray();
} // implicit close -- too late!
Комментарии (2)

Еще одной причиной исключения могут быть состязания между несколькими потоками с помощью расшифровки логики - нативные реализации ICryptoTransform не потокобезопасными (например, класс symmetricalgorithm), поэтому она должна быть положена в эксклюзивный раздел, например с помощью замок. Пожалуйста, см. здесь для более подробной информации: http://www.make-awesome.com/2011/07/system-security-cryptography-and-thread-safety/

Комментарии (0)

Да, этого следовало ожидать, или, по крайней мере, его именно так и происходит, когда наши процедуры крипто вам не decryptable данных

Комментарии (0)

Причин может быть несколько непрочитанных байтов в поток cryptostream. Закрытия перед прочтением поток полностью вызывает ошибку в моей программе.

Комментарии (0)

У меня была похожая проблема, вопрос в расшифровке метод инициализации пустой поток памяти. когда он работал, когда я инициализировать его с зашифрованным текстом байтовый массив такой:

MemoryStream ms = new MemoryStream(cipherText)
Комментарии (0)

Ответ обновлена пользователем "и atconway" не работал для меня.

Проблема была не с балластом, но ключ, который отличается во время шифрования и дешифрования. Ключ и IV должны быть одинаковыми во encypting и расшифровки то же значение.

Комментарии (0)