2015-12-16 3 views
1

У меня есть код дешифрования, который ожидает, что Cipher.doFinal() будет генерировать исключение при использовании неправильного ключа/iv. Кажется, это не происходит. Ну, это происходит, но не всегда.Cipher.doFinal() не выбрасывает исключение, если используется недействительный ключ

Мое шифрование использует «секунды» текущего времени в качестве семени для класса Random(). Затем он использует 16 (псевдо) случайных значений по модулю 256 для генерации 16-байтового ключа. Он шифрует этот ключ. Он использует один и тот же массив байтов для IV. Я инициализации шифра следующим образом:

Cipher.getInstance("AES/CBC/ISO10126Padding"); 

Циклы дешифрования через все возможные 60 вторых значений (0 - 59), используя ту же логику для генерации ключа и IV. Для каждого ключа и IV он пытается расшифровать зашифрованное значение. Обычно я получаю некоторое количество исключений BadPaddingException, но большую часть времени он преуспевает на «втором» значении, которое является неправильным. Как и ожидалось, я возвращаю мусор. Я ожидал, что doFinal() всегда будет генерировать исключение, если используется неправильный ключ/iv. Есть ли причина, почему это не так?

В качестве примера:

Если ток второго равен 45, когда я зашифровать он будет использовать это значение для генерации ключа/IV. Когда я пытаюсь расшифровать, я сижу в цикле for от 0 до 59, пробуя каждое из этих значений до тех пор, пока doFinal() не удастся (например, не генерирует исключение). Обычно я вижу некоторое количество исключений BadPaddingException, но цикл заканчивается до 45, и я возвращаю мусор.

я нашел это:

Java AES decryption detect incorrect key

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

+0

Из моего расчета только 6% неправильных ключей должны производить мусор с ISO10126Padding. Другие 94% должны привести к исключению BadPaddingException. Это то, что вы видите или ваши результаты разные? –

ответ

3

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

Именно поэтому кроватка используется для шифрования перебора грубой силы, поэтому можно правильно исправить ошибки при некорректном шифровании, см., Как Bletchley Park сломал немецкое шифрование и необходимые шпаргалки. Шпаргалка - это способ определить, что дешифрование может быть правильным/неправильным.

Иногда, если заполнение используется, заполнение будет ошибочным, а некоторые, но все, реализация вернет ошибку. Это фактически нарушение безопасности, это утечка информации через прокладку. Это форма кроватки.

Если вы хотите проверить шифрование, вам необходимо предоставить другой метод, например, добавить хэш данных для проверки.

+1

Возможно также стоит упомянуть, что это метод, вызывающий катастрофически небезопасный метод генерации ключей. – pvg

+0

pvg: Я предположил, что существуют проблемы с шифрованием этого способа, но если у кого-то нет доступа к коду и поэтому он не может перепроектировать, вы говорите им будет проще дешифровать время, чем какой-либо другой 128-битный ключ? Если да, то почему? – nickdu

+0

Это ключевое поколение, которое действительно ужасно, Random(): «Если два экземпляра Random созданы с ** одним семенем **, и для каждой из них производится одна и та же последовательность вызовов методов, они будут генерировать и возвращать * * идентичные последовательности ** чисел ". Семя - это секунды, то есть всего 60 значений семян. Вместо этого просто получите 16 байтов от криптографически безопасного генератора случайных чисел, такого как SecureRandom. – zaph