Невозможно расшифровать зашифрованные данные aes-256-gcm в java - PullRequest
0 голосов
/ 22 марта 2020

Я зашифровал файл с помощью OpenSSL aes-256-gcm. Поскольку aes-256-gcm не поддерживается командной строкой, я установил LibreSSL и могу использовать приведенную ниже команду для шифрования данных файла.

openssl en c -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 Ответ

1 голос
/ 23 марта 2020

Это не должно работать. Командная строка 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 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 и Blowfi sh шифрование в Java / Scala и расшифровывать в bash (последнее - обратное направление, но необходимость совпадения одинакова)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...