Я зашифровал файл с помощью OpenSSL aes-256-gcm. Поскольку aes-256-gcm не поддерживается командной строкой, я установил LibreSSL и могу использовать приведенную ниже команду для шифрования данных файла.
Openssl enc -aes-256-gcm -K 61616161616161616161616161616161 -iv 768A5C31A97D5FE9 -e -in file.in -out file.out
Мне нужно расшифровать данные file.out на Java, и я не могу этого сделать.
Образец кода :
// Get Cipher Instance
Cipher cipher = Cipher.getInstance("AES/GCM/NoPadding");
String key = "61616161616161616161616161616161";
byte[] IV = "768A5C31A97D5FE9".getBytes();
// Create SecretKeySpec
SecretKeySpec keySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");
// Create GCMParameterSpec
GCMParameterSpec gcmParameterSpec = new GCMParameterSpec(128, IV);
// Initialize Cipher for DECRYPT_MODE
cipher.init(Cipher.DECRYPT_MODE, keySpec, gcmParameterSpec);
// Perform Decryption
byte[] decryptedText = cipher.doFinal(cipherText); // for the data by reading file.out
Однако я получаю исключение, говорящее javax.crypto.AEADBadTagException: несоответствие тегов!
1 ответ
Это не должно работать. Командная строка openssl enc
не поддерживает шифры/режимы AEAD, хотя ранние версии 1.0.1 (ниже патча h, в 2012-2014 гг.) не могли отловить, если вы неправильно указали такой шифр и молча выдали неверный вывод. Если вы на самом деле используете LibreSSL, а не OpenSSL, похоже, он унаследовал эту проблему, а не исправил ее, хотя весь смысл проекта LibreSSL заключался в том, чтобы исправить все ошибки, вызванные некомпетентными людьми OpenSSL.
Если бы это был шифр, который правильно работал в OpenSSL (а также в Java), например, aes-256-ctr, то ваша единственная проблема заключалась бы в том, что openssl enc -K -iv
берут свои аргументы в шестнадцатеричном формате (подходит для контекста оболочки), тогда как Java crypto вызывается из кода, который может обрабатывать двоичные данные, и ожидает свои аргументы в этой форме. В результате значения, которые вы предоставляете OpenSSL, на самом деле составляют 16 байтов (128 бит) и 8 байтов (64 бита), а не 256 бит и 128 бит, как они должны быть (для CTR; для GCM IV из 96 бит было бы правильным, но, как уже отмечалось, GCM здесь не работает). openssl enc
автоматически дополняет -K -iv
(двоичными) нулями, но Java этого не делает. Таким образом, вам нужно что-то более похожее на
byte[] key = Arrays.copyOf( javax.xml.bind.DatatypeConverter.parseHexBinary("61616161616161616161616161616161"), 32);
// Arrays.copyOf zero-pads when expanding an array
// then use SecretKeySpec (key, "AES")
// and IVParameterSpec (iv) instead of GCMParameterSpec
// but after Java8 most of javax.xml is removed, so unless you
// are using a library that contains this (e.g. Apache)
// or have already written your own, you need something like
byte[] fromHex(String h){
byte[] v = new byte[h.length()/2];
for( int i = 0; i < h.length(); i += 2 ) v[i] = Integer.parseInt(h.substring(i,i+2),16);
return v;
}
Сравните шифрование AES с помощью инструмента командной строки openssl и расшифровывать в Java и Blowfish шифровать в Java/Scala и расшифровать в bash (последнее — в обратном направлении, но необходимость сопоставления такая же)
Похожие вопросы
Связанные вопросы
Новые вопросы
java
Java — это высокоуровневый объектно-ориентированный язык программирования. Используйте этот тег, если у вас возникли проблемы с использованием или пониманием самого языка. Этот тег часто используется вместе с другими тегами для библиотек и/или фреймворков, используемых разработчиками Java.