Openssl, Java: невозможно расшифровать длинные сообщения - PullRequest
0 голосов
/ 24 августа 2018

Я шифрую текст с помощью Java и пытаюсь расшифровать его с помощью Openssl в Linux. Я использую AES-128 с CBC.

Я получаю сообщение об ошибке «плохое дешифрование» от Openssl, когда использую Openssl для дешифрования 64-символьной зашифрованной строки, созданной Java. Но если строка состоит из 16 символов, Openssl может правильно ее расшифровать.

Я запускаю это в Linux:

echo ${encryptedText} | ./openssl aes-128-cbc -d -a -K $( echo -n ${KEY} | hexdump -v -e '/1 "%02X"') -iv $(echo -n ${IV} | hexdump -v -e '/1 "%02X"')

Примечание: $ encryptedText, $ KEY, $ IV передаются как строки, а не как шестнадцатеричные. Эта команда превращает его в гекс: $ (echo -n $ {KEY} | hexdump -v -e '/ 1 "% 02X"')

и получаю эту ошибку:

358048944:error:0606506D:digital envelope routines:EVP_DecryptFinal_ex:wrong final block length:evp_enc.c:460:

Мой код шифрования с Java, в основном:

import javax.crypto.*;

Cipher cipher;
SecretKey key;
String IV;
IvParameterSpec params;

cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
String randomString = GENERATE_RANDOM_TYPEABLE_ASCII(16_LENGTH);

key = new SecretKeySpec(randomString.getBytes("UTF-8"), "AES");
IV = GENERATE_RANDOM_TYPEABLE_ASCII(16_LENGTH);
params = new IvParameterSpec(IV.getBytes("UTF-8"));

cipher.init(Cipher.ENCRYPT_MODE, key, params);
byte[] encryptedTextBytes = cipher.doFinal((decryptedString).getBytes("UTF-8")); // decryptedString is passed as a parameter

String encryptedText = new Base64().encodeAsString(encryptedTextBytes);
return encryptedText;

Чего я не понимаю, так это того, почему крипто работает для 16-символьных строк, но не работает для 64-символьных.

Еще одна важная вещь, на которую следует обратить внимание, - это то, что если я расшифрую текст с помощью онлайн-инструментов, таких как http://aes.online -domain-tools.com / , строка расшифровывается отлично. Поэтому я думаю, что мое шифрование работает нормально, но по какой-то причине OpenSSL создает проблемы.

1 Ответ

0 голосов
/ 25 августа 2018

Я не воспроизвел вашу проблему, но подозреваю, что это вызывает у вас проблемы: функция Base64.encodeAsString() при ее использовании возвращает длинную строку вместо блока шириной 16 символов:

import org.apache.commons.codec.binary.Base64;

public class B64Test {

    public static void main(String[] args) {
        byte[] plaintext = new byte[100];
        String b64text = new Base64().encodeAsString(plaintext);
        System.out.println(b64text);
    }
}

дает вывод

AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==

Если вы хотите передать это в openssl для декодирования, вам нужно предоставить дополнительную опцию -A, чтобы openssl base64 обрабатывал данные в одной строке. Обратите внимание, что -A необходимо использовать вместе с -a или с -base64, что то же самое, но более читабельно. Это объясняется в документации для openssl enc .

В качестве альтернативы вы можете указать конструктору Base64() вставлять разрывы строк после, например, 64 символов, например:

String b64text = new Base64(64).encodeAsString(plaintext);
...