Вывод команды OpenSSL AES/CBC 256 не совпадает с выводом кода Java

Привет, я использую команду openSSL для шифрования и расшифровки моего сообщения. Теперь я хочу, чтобы эта команда была преобразована в код Java. Я пробовал разные решения, представленные в Интернете, но ни один из кодов не соответствует результатам.

Вот моя команда OpenSSL с моим преуменьшением в комментариях:

key="FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA"

# Getting 16 digits from the iv.txt file and putting it into the bin
head -c 16 iv.txt > iv.bin

# Converting iv.bin text into the HEXA value
iv=`xxd -l 16 -p iv.bin`

# encrypt without "-a" 
openssl enc -aes-256-cbc -K $key -iv $iv -in plainKey.txt -out encryptedKey.bin

# printing encrypted results in base64 format this need to be matched with my java code.
echo "<enc>"`cat encryptedKey.bin | base64`"</enc>"

Это то, что я сделал на Java:

Примечание: этот код из переполнения стека принял ответ с небольшими изменениями. Я также пробовал некоторые другие коды, но не могу упомянуть все здесь.

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.bind.DatatypeConverter;

public class Test {

public static void main(String[] args) {
    try {
        runEncryption();
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static void runEncryption() throws Exception
{
    //String to be encrypted
    String plainText = "abcd@1234\n";

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

    // IV text
    String iv = "C837E1B6C3D3A7E28F47719DE0C182C9";

    // getting 16 characters of iv text
    iv = iv.substring(0,16);

    // Value of key
    String key = "FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA";

    // Logic for converting 16 Digits of IV into HEX
    StringBuffer hexString = new StringBuffer();
    for (int i=0;i<iv.getBytes().length;i++) {
        String hex=Integer.toHexString(0xff & iv.getBytes()[i]);
        if(hex.length()==1) hexString.append('0');
        hexString.append(hex);
    }

    // Seems something wrong here because if i am passing all the bytes to keySpe like key.getBytes() it is producing exception  so i am passing 16 bytes as previous code was doing in SO
    SecretKeySpec keySpec = new SecretKeySpec(hexToBytes(key), 0, 16, "AES");
    IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes(hexString.toString()));

    cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
    byte[] encrypted = cipher.doFinal(plainText.getBytes("UTF-8"));

    String encryptedBase64 = new String(DatatypeConverter.printBase64Binary(encrypted));

    System.out.println("");
    System.out.println("Encrypted base64 = " + encryptedBase64);
}

private static byte[] hexToBytes(String s)
{
    int len = s.length();
    byte[] data = new byte[len / 2];

    for (int i = 0; i < len; i += 2)
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4) + Character.digit(s.charAt(i + 1), 16));

    return data;
}    
}

Я генерирую ключ и iv с помощью команды openSSL

openssl enc -aes-256-cbc -k secret -P -md sha1

Кажется, здесь что-то не так, потому что, если я передаю все байты в keySpec, например key.getBytes(), он создает исключение, поэтому я передаю 16 байтов, как предыдущий код делал в SO, я также упомянул об этом в комментариях к коду, пожалуйста, сообщите об этом это спасибо.


person Zahid Ali    schedule 27.11.2017    source источник
comment
Могут быть и другие проблемы, но сначала давайте иметь те же параметры - вы передаете только 16 байтов ключа, вы фактически делаете AES-128, где openssl используется с aes-256-cbc. Далее - почему вы сами выполняете преобразование шестнадцатеричного кода в строку? (не   -  person gusto2    schedule 27.11.2017


Ответы (1)


У вас есть несколько ошибок в вашем коде

давайте предположим, что вы хотите сделать это

 openssl enc -aes-256-cbc -K FB4FF1BA6F1FCC1A11B8B3910342CBD3A2BEAEB8F52E8910D9B25C0C96280EEA -iv 03B13BBE886F00E00000000000000000 -base64 -in input.txt

в вашем коде у вас есть несколько ошибок (моменты wtf). Я не буду исправлять их для вас, но в основном:

  1. Я бы посоветовал использовать какую-нибудь обычную библиотеку (например, commons-codec, ..) для кодирования/декодирования из шестнадцатеричного кода, хотя, похоже, пока это работает

  2. вы используете 16 байт (128 бит) iv и ключ, эффективно выполняющий AES-128. Вам нужно использовать AES-256 с ключом и длиной 256 бит (32 байта). Вы сократили оба до 16 байт, поэтому они отличаются от значений, используемых с openssl.

  3. главный переломный момент: IvParameterSpec ivSpec = new IvParameterSpec(hexToBytes(hexString.toString())); пожалуйста, немного подумайте об этом. hexToBytes(iv)

person gusto2    schedule 27.11.2017
comment
что касается пункта 1, я не получал один и тот же шестнадцатеричный код, используя несколько библиотек, поэтому я сделал это как обычно, но я буду использовать библиотеку, как только получу желаемые зашифрованные результаты, и для пункта 2, если я увеличу размер из ключа и iv я получаю сообщение об ошибке неверный ключ, и этот ключ я генерирую с открытым ssl, используя команду $ openssl enc -aes-256-cbc -k secret -P -md sha1 - person Zahid Ali; 28.11.2017
comment
Пожалуйста, убедитесь, что и iv, и ключ (это реальный размер массива байтов) имеют размер 256 бит (32 байта). Это сработало для меня. Просто идея - какую версию/дистрибутив Java вы используете? Вам не нужна Политика неограниченной силы JCE? - person gusto2; 28.11.2017
comment
он работает и в моем случае, но проблема в том, что его вывод не совпадает с выводом openSSL. У меня мало знаний об openSSL и криптографии. Можете ли вы подсказать мне, как я могу получить 256-битный iv и ключ? Спасибо. - person Zahid Ali; 28.11.2017
comment
Если вы используете Oracle JRE, вам необходимо установить политику JCE неограниченной силы. В противном случае вы ограничены AES-128 (насколько я знаю). Так что, возможно, для начала вы можете попробовать использовать 16-байтовые ключи и aes-128 с openssl и Java, чтобы увидеть, правильно ли это сделано (это достаточно сильно, не волнуйтесь). Или вы можете попробовать использовать BouncyCastle или OpenJDK. - person gusto2; 28.11.2017
comment
Спасибо, что ваши последние комментарии сработали для меня после установки Unlimited Strength JCE Policy, ошибка «Недопустимый размер ключа» исчезла, и результат совпал с желаемым результатом. теперь я пробую BouncyCastle, чтобы приложение не требовало изменения JRE. - person Zahid Ali; 28.11.2017