JAVA PHP Шифрование Расшифровка

У меня есть следующая функция шифрования в моем приложении:

public static String encrypt(String key, String value) {
try {
IvParameterSpec iv = new IvParameterSpec(key.substring(0, 16).getBytes("UTF-8"));
SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

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

byte[] encrypted = cipher.doFinal(value.getBytes("UTF-8"));

return Base64.encodeBase64String(encrypted);
} catch (Exception ex) {
ex.printStackTrace();
}

return null;
}

И в PHP зашифрованное сообщение декодируется с использованием openssl_decrypt() с AES-128-CBC установить в качестве метода шифрования.

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

У меня нет контроля над сервером, поэтому я ничего не могу изменить только в моем приложении Java.

Я пробовал разные режимы, такие как AES/CBC/NoPadding но я получаю исключение

Input Length Not Multiple of 16 bytes

Теперь я знаю, что нет ничего плохого в шифровании, потому что я могу зашифровать и расшифровать в своем приложении Java при использовании AES/CBC/PKCS5Padding это просто не удается при публикации на сервер.

Ключ — это хэш MD5.

Это пример данных, которые мне нужно зашифровать:

{
"merchant_id": "EXX-00000001",
"user_id": "000000000001",
"code": "000200",
"details": {
"acc_no": "1234691007924321",
"exp": "07/19",
"name": "MICHAEL XXXXXX",
"type": "VIS"}
}

Предполагается, что только значение «details» должно быть зашифровано. Код должен быть хэшем md5. Полученный в результате хеш затем будет использоваться в качестве ключа для шифрования AES. Предполагается, что IV — это первые 16 символов хэша. Когда шифрование выполнено, результат должен быть закодирован в base64 и отправлен на сервер.

5

Решение

Пытаясь изменить это, я получил ошибку

java.security.InvalidKeyException: недопустимый размер ключа

на линии

cipher.init(Cipher.ENCRYPT_MODE, skeySpec, iv);

Чтобы это работало, я изменил SecretKeySpec байтовый массив из key.getBytes("UTF-8") в key.substring(0, 16).getBytes("UTF-8") и использовал это так:

    String md5Key= "e510a13edeea112b57683d724d5d70a6";
String detailsData = "{\n" +
"        \"acc_no\": \"1234691007924321\",\n" +
"        \"exp\": \"07/19\",\n" +
"        \"name\": \"MICHAEL XXXXXX\",\n" +
"        \"type\": \"VIS\"\n" +
"    }";

System.out.println(encrypt(md5Key, detailsData));

Я получил вывод, как это:

iufp4Rl+x/yTO7hSQBH7uU63sXAyzxgLequ3+JkFYZFz3PWwhxDC87TEC+bZ4rirgZVasrkLE1ehWWRGFV42Z29vAok+TMdwOvOettELUD3g8W2F40OyjMg4ItYkiZM+2W6Q2zf6t4sLzM6/AYqmAy1dKjPJcCQaFcnqK6mUFcM=

Чтобы расшифровать это в PHP, я использовал следующий код, который использует первые 16 символов key использовать его как key а также iv инициализатор, как это:

$enc_data = 'iufp4Rl+x/yTO7hSQBH7uU63sXAyzxgLequ3+JkFYZFz3PWwhxDC87TEC+bZ4rirgZVasrkLE1ehWWRGFV42Z29vAok+TMdwOvOettELUD3g8W2F40OyjMg4ItYkiZM+2W6Q2zf6t4sLzM6/AYqmAy1dKjPJcCQaFcnqK6mUFcM=';
$key = 'e510a13edeea112b57683d724d5d70a6';
$key16 = substr($key, 0, 16);
$key16Hex = unpack('H*', $key16);

print openssl_decrypt($enc_data, "AES-128-CBC", $key16, 0, hex2bin($key16Hex[1]));

И, конечно, я получил нужные данные JSON, которые я зашифровал с помощью Java:

{
"acc_no": "1234691007924321",
"exp": "07/19",
"name": "MICHAEL XXXXXX",
"type": "VIS"}

Странно, что вы не получаете сообщение об ошибке в этой строке:

SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

потому что я использую JDK 1.8 с:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
4

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]