Шифрование с PHP на Java (Android): как исправить ошибку «Неверная конечная длина блока»? - PullRequest
0 голосов
/ 27 июня 2019

Пробовал несколько различных методов, найденных в Google и SOF, но я просто не могу заставить это работать.Я пытаюсь зашифровать строку в PHP и расшифровать ее в Java (активность Android).В PHP для шифрования строки я использую AES-256-CBC с хэшем sha256 (который успешно шифрует / дешифрует в PHP).Проблема в том, что независимо от того, что я пытаюсь, я не могу получить незашифрованную строку в Java.Моя последняя попытка закончилась консольной ошибкой «Функции шифра: OPENSSL_internal: WRONG_FINAL_BLOCK_Length».

Я подозреваю, что моя проблема связана с кодировкой Base64, но все мои попытки до сих пор не увенчались успехом.Или, возможно, я использую неправильный шифр на стороне Java.Я читал о некоторых людях, которым нужно преобразовать в гекс, хотя я не понимаю, почему.

Обратите внимание, что значения iv и key на самом деле не совпадают, просто они используются здесь для примера.

Мой код PHP:

$secret_key = "1111111111111111";
$secret_iv = "1111111111111111";

$encrypt_method = "AES-256-CBC"; 
$key = hash( 'sha256', $secret_key );
$iv = substr( hash( 'sha256', $secret_iv ), 0, 16 );
$output = base64_encode( openssl_encrypt( $string, $encrypt_method, $key, 0, $iv ) );

Мой код Java:

    String given_iv = "1111111111111111";
    String key = "1111111111111111";

    IvParameterSpec iv = new IvParameterSpec(given_iv.getBytes());
    SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");

    Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5PADDING");
    cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

    byte[] decodedEncryptedData = Base64.decode(data.getBytes(),Base64.NO_WRAP);

    byte[] original = cipher.doFinal(decodedEncryptedData);
    Log.i(TAG, "Result: " + new String(original));
    return new String(original);

Может кто-нибудь сказать, пожалуйста, где я ошибся.Спасибо.

Обновление 1: Как отметили @Peter и @Topaco, я дважды кодировал Base64 на стороне PHP, это было удалено, так же как и использование ключа / IV непосредственно на стороне Java.К сожалению, ошибка сохраняется.

Код PHP теперь:

    $secret_key = "1111111111111111";
    $secret_iv = "1111111111111111";

    $encrypt_method = "AES-256-CBC"; 
    $output = openssl_encrypt( $string, $encrypt_method, $secret_key, 0, $secret_iv );

Код Java остается прежним.Однако я возился с Cipher.getInstance ("AES / CBC / PKCS5PADDING") и изменил его на "AES / CBC / NOPADDING", он изменил ошибку, теперь я получаю вывод искаженного текста, но по-прежнему безуспешнорасшифровка полностью.

1 Ответ

0 голосов
/ 02 июля 2019

Наконец-то удалось найти рабочее решение благодаря @Topaco. Как они указали, я не только использовал двойное кодирование (Base64), но и должен был использовать AES-128-CBC вместо AES-256-CBC. Как я выяснил, open_ssl в php, похоже, не выдает ошибку, когда IV имеет недопустимую длину, скорее он дополняет или удаляет символы по мере необходимости. AES-128-CBC правильно работал с 16-битным IV, и все было решено.

Для тех, кто может наткнуться на этот пост в будущем, окончательным решением было изменить сторону PHP следующим образом:

$secret_key = "1111111111111111";
$secret_iv = "1111111111111111";

$encrypt_method = "AES-128-CBC"; 
$output = openssl_encrypt( $string, $encrypt_method, $secret_key, 0, $secret_iv );
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...