AES кодирование Java, рубиновое декодирование

Я пробую к AES, кодируют данные в Java, отправляют его по сети и декодируют его в рубине.

Хорошо работает с основными строками, но после того как длина строки составляет 16 байтов или больше, у меня есть мусор при кодировании декодируемой рубиновой строки. Я предполагаю, что это имеет отношение к дополнению (не уверенный, хотя, так как это влияет даже на строки с точным размером 16),

Я пытался использовать PKCS или просто добавить пробел в конце моей строки для соответствия точной длине без удачи

Также кто-либо может объяснить, почему я должен сделать "aes-256-cbc" в рубине, зная, что мой Java кодирует aes 128 использования? попытка aes-128-cbc в рубине не работает ни на какую строку

Любая справка значительно ценится

Вот мой абсолютный код

Java

byte[] raw = key.getBytes();
SecretKeySpec skeySpec = new SecretKeySpec(raw, "AES");
Cipher cipher = Cipher.getInstance("AES");
cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
byte[] encrypted = cipher.doFinal(str.getBytes());
return new BASE64Encoder().encode(encrypted);

Ruby

def aes_decrypt(key, encrypted)
decipher =OpenSSL::Cipher::Cipher.new("aes-256-cbc")
decipher.decrypt
decipher.padding = 0
decipher.key = key
d = decipher.update(encrypted)
d << decipher.final
logger.debug "email  #{d.to_s}"
return d.to_s
end
7
задан pompon_vdp 24 March 2010 в 09:34
поделиться

2 ответа

Есть заполнение и есть связывание . Сначала вы должны правильно построить цепочку.

AES шифрует блоки по 16 байт, не больше и не меньше. Если вы хотите зашифровать сообщение, длина которого потенциально превышает 16 байт, вы должны решить, как данные разбиваются на блоки и затем собираются заново. Базовый алгоритм разделения называется ECB : это «просто разбиение» на блоки, зашифрованные индивидуально. Известно, что ECB плохо справляется с реальными данными, поскольку из-за утечки информации о том, какие блоки открытого текста равны друг другу (они будут зашифрованы одинаково), и такая избыточность часто возникает в «обычных» данных.

Таким образом, необходимо каким-то образом «рандомизировать» блоки данных, чтобы скрыть избыточность данных. В режиме CBC это выполняется посредством «цепочки»: обработка блока зависит от результата шифрования предыдущего блока. А именно, блок открытого текста для шифрования комбинируется (с побитовым XOR) с выходом предыдущего блочного шифрования.

Важным моментом здесь является то, что первый блок для шифрования (первые 16 байтов данных) не имеет «предыдущего блока», поэтому выполнять операцию XOR не с чем. Это решается путем выбора «случайного IV», то есть последовательности из 16 случайных байтов, которая будет использоваться как «блок -1» для шага XORing. IV должен быть известен дешифрующей стороне (иначе она не будет знать, с чем выполнить XOR дешифрованного блока, и первые 16 байтов данных не будут понятны).Хорошая сторона в том, что капельница не должна быть секретной; он ДОЛЖЕН выбираться единообразно (это не может быть счетчик, увеличиваемый для каждого сообщения), но он может передаваться «в открытом виде», обычно вместе с самим зашифрованным сообщением.

Так что вам нужно немного побеспокоиться о IV, а я ничего не вижу об этом ни в коде Java, ни в коде Ruby. Обычно Java по умолчанию использует ECB (следовательно, IV вообще не используется). Если Ruby по умолчанию использует «нулевой IV» в CBC (что концептуально небезопасно), то это нормально, что вы можете расшифровать первый блок (запишите его, он «просто работает»), но это также нормально. что это не работает для последующих блоков.

Поэтому я предлагаю вам явно использовать CBC (в Java используйте «AES / CBC / PKCS5Padding» в качестве имени алгоритма, а не «AES» ) и управлять IV (который затем должны быть переданы; вы можете принять соглашение о конкатенации IV прямо перед зашифрованным сообщением).

Несколько других примечаний:

  • Заполнение касается добавления некоторых данных в открытый текст, чтобы у вас была соответствующая длина ввода. CBC требует, чтобы длина входных данных была кратной размеру блока (16 байтов). Заполнение PKCS # 5 - популярный метод, с помощью которого вы добавляете не менее 1 байта, не более 16 байтов, так что все они имеют значение n , где n - количество добавлены байты. Затем получатель может узнать (однозначно), сколько байтов было добавлено, и удалить их. Java может добавить отступы за вас, и я полагаю, что Ruby также может обработать отступы автоматически, если вас попросят.

  • В коде Java вы используете key.getBytes () .Я предполагаю, что ключ - это String . Знайте, что getBytes () кодирует строку в соответствии с набором символов платформы по умолчанию, который не всегда одинаков во всем мире. Вы избавите себя от беспокойства, указав явную кодировку. Кроме того, поскольку вы хотите использовать 128-битный ключ, но вы получаете что-то на стороне Ruby только с «AES-256», я предполагаю, что вы фактически используете 256-битный ключ на стороне Java. Я предполагаю, что ваша строка key является шестнадцатеричным представлением вашего ключа в виде 32 символов. key.getBytes () не интерпретирует шестнадцатеричные цифры; он кодирует сами символы, давая 32-байтовый массив - и 32 байта, то есть 256 бит, а не 128.

11
ответ дан 6 December 2019 в 21:11
поделиться

Я согласен с вашими подозрениями по поводу заполнения. Заполнение PKCS # 5 «округлит» ваш открытый текст до следующей границы целого блока; если вы дадите ему целое количество блоков, он добавит один целый блок заполнения.

На вашем месте я бы посмотрел, что именно вы получаете, когда запрашиваете у JCE AES - я подозреваю, что вы получаете AES / CBC / PKCS5Padding, но, возможно, имеет смысл явно запросить то, что вы хотеть. Точно так же вам нужно точно узнать, что вы получаете на конце Ruby - может ли «мусор» в конце расшифровки быть байтами заполнения? Прочтите спецификацию PKCS # 5 и сравните ее с тем, что вы получаете.

Меня немного беспокоит, что вы говорите, что используете AES-128 на стороне Java, но (очевидно) AES-256 на стороне Ruby / OpenSSL. Такое несоответствие практически гарантированно не сработает - но вы говорите, что криптография работает, по крайней мере, для коротких сообщений. Возможно, вы на самом деле получаете AES-256 из java (опять же, если вы спрашиваете об «AES», что вы на самом деле получаете?) Или что-то странное происходит на рубиновой стороне, которая является обнаруживая, что вы используете 128-битный ключ, и делаете то, что он считает правильным.

В сторону: Задумывались ли вы, нужна ли защита целостности вашим шифротекстам? Конфиденциальность - это хорошо, но успешное дешифрование не гарантирует того, что зашифрованный текст не был изменен при передаче.

1
ответ дан 6 December 2019 в 21:11
поделиться
Другие вопросы по тегам:

Похожие вопросы: