Нужно решение для неправильной длины IV в AES - PullRequest
5 голосов
/ 18 июля 2011

Я пытаюсь реализовать AES в Java, и этот код я использую:

 byte[] sessionKey = {00000000000000000000000000000000};
 byte[] iv = {00000000000000000000000000000000};
 byte[] plaintext = "6a84867cd77e12ad07ea1be895c53fa3".getBytes();
 Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

 cipher.init(Cipher.ENCRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
 byte[] ciphertext = cipher.doFinal(plaintext);

 cipher.init(Cipher.DECRYPT_MODE, new SecretKeySpec(sessionKey, "AES"), new IvParameterSpec(iv));
 byte[] deciphertext = cipher.doFinal(ciphertext);

Мне нужен этот фиксированный ключ и IV для целей тестирования, но я получаю следующее исключение:

Exception in thread "main"
java.security.InvalidAlgorithmParameterException: 
  Wrong IV length: must be 16 bytes long    at
com.sun.crypto.provider.SunJCE_h.a(DashoA12275)     at
com.sun.crypto.provider.AESCipher.engineInit(DashoA12275)   at
javax.crypto.Cipher.a(DashoA12275)  at
javax.crypto.Cipher.a(DashoA12275)  at
javax.crypto.Cipher.init(DashoA12275)   at
javax.crypto.Cipher.init(DashoA12275)

Как я могу использовать этот фиксированный IV с этой реализацией AES?Есть ли способ?

Ответы [ 5 ]

38 голосов
/ 18 июля 2011

Во-первых,

byte[] iv = {00000000000000000000000000000000};

создает байтовый массив размера 1, а не байтовый массив размера 32 (если это ваше намерение).

Во-вторых, размер IV AES должен составлять 16 байтов или 128 бит (это размер блока AES-128). Если вы используете AES-256, размер IV должен быть 128-битным, так как стандарт AES допускает только 128-битные размеры блоков. Исходный алгоритм Rijndael допускал другие размеры блока, включая размер блока 256 бит.

В-третьих, если вы намереваетесь использовать AES-256, это не из коробки. Вам необходимо загрузить и установить Файлы политики неограниченной юрисдикции JCE (прокрутите страницу вниз); Я также рекомендовал бы прочитать прилагаемую лицензию.

Это приведет к следующему изменению вашего кода:

byte[] iv = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

Наконец, вектор инициализации должен быть уникальным и непредсказуемым. Последовательность из 16 байтов, каждый из которых представлен значением 0, не является подходящим кандидатом для IV. Если это производственный код, попробуйте получить помощь.

14 голосов
/ 18 июля 2011

Из Расширенный стандарт шифрования :

Стандарт включает в себя три блочных шифра, AES-128, AES-192 и AES-256, взятые из более крупной коллекции, первоначально опубликованной какRijndael. Каждый из этих шифров имеет 128-битный размер блока , с размерами ключей 128, 192 и 256 бит соответственно

(выделение добавлено)

От Вектор инициализации :

Для режимов работы блочного шифра IV обычно равен размеру блока шифра

Объедините эти двафакторы вместе, и вы получите, что IV всегда для 128 AES для AES, независимо от размера ключа.

2 голосов
/ 26 июня 2014

Почему бы просто не использовать что-то подобное вместо использования "магических чисел":

SecureRandom random = new SecureRandom();
byte[] iv = random.generateSeed(16);

Таким образом, вы получите 16 случайных байтов для вашего iv.

2 голосов
/ 18 июля 2011

AES, вероятно, здесь AES-128, а не AES-256. Вы должны включить дополнительный jar, если хотите включить AES-256, так как существуют политики контроля экспорта. Так что сначала проверьте это. В большинстве случаев достаточно AES-128.

Ваш IV не может быть больше 128 бит, т.е. 16 байтов, когда это AES-128. Так что измените длину вектора инициализации.

Это должно сработать. Также прочитайте это http://en.wikipedia.org/wiki/Initialization_vector

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

0 голосов
/ 27 апреля 2019

Причина, по которой у меня возникла эта проблема, заключалась в том, что я читал IV как строку и неправильно преобразовывал его в байтовый массив.

Правильный путь:

Hex.decodeHex(initializationVector.toCharArray()

с использованием org.apache.commons.codec.binary.Hex

Неправильный путь:

initializationVector.getBytes()

Причина, по которой это было неправильно, заключается в том, что когда вы вызываете getBytes(), он просто берет все биты, которые представляют строку, и разбивает их на байты. Таким образом, 0 заканчивается записью в виде битов, составляющих индекс 0 в таблице Unicode, который не 0, а 30, и который будет записан в 2 байта.

И наоборот, здесь вы на самом деле хотите, чтобы 0 был представлен в виде байта 00000000.

...