简体   繁体   English

JAVA PHP加密解密

[英]JAVA PHP Encryption Decryption

I have the following encryption function in my application: 我的应用程序中有以下加密功能:

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;
}

And in PHP the encrypted message is decoded using openssl_decrypt() with AES-128-CBC set as the method of encryption. 在PHP中,使用openssl_decrypt()解码加密消息,并将AES-128-CBC设置为加密方法。

However the decryption always fails the response I get from the server is that it cannot recognize the encryption method. 然而,解密总是失败我从服务器得到的响应是它无法识别加密方法。

I have no control over the server so I cannot change anything on that end only in my Java app. 我无法控制服务器,因此我无法仅在我的Java应用程序中更改任何内容。

I have tried different modes like AES/CBC/NoPadding but I get an exception 我尝试过不同的模式,如AES/CBC/NoPadding但我得到了一个例外

Input Length Not Multiple of 16 bytes

Now I know there is nothing wrong with the encryption because I am able to encrypt and decrypt in my java app when using AES/CBC/PKCS5Padding it just fails when post to the server. 现在我知道加密没有任何问题,因为我在使用AES/CBC/PKCS5Padding时能够在我的java应用程序中加密和解密它在发布到服务器时失败了。

Key is a md5 hash. 密钥是md5哈希。

This is a sample of the data I need to encrypt: 这是我需要加密的数据示例:

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

Only the "details" value is supposed to be encrypted. 只应对“详细信息”值进行加密。 The code is supposed to be a md5 hash. 代码应该是md5哈希。 The resulting hash is then to be used as a key for the AES encryption. 然后,生成的哈希将用作AES加密的密钥。 The IV is supposed to be the first 16 chars of the hash. IV应该是哈希的前16个字符。 When the encryption is done the result should be encoded in base64 and sent to the server. 加密完成后,结果应在base64中编码并发送到服务器。

Trying to reverse this, I got an error of 试图扭转这种局面,我得到了一个错误

java.security.InvalidKeyException: Illegal key size java.security.InvalidKeyException:非法的密钥大小

at line 在线

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

To make it work, I changed the SecretKeySpec byte array from key.getBytes("UTF-8") to key.substring(0, 16).getBytes("UTF-8") and used it like this: 为了使它工作,我将SecretKeySpec字节数组从key.getBytes("UTF-8")更改为key.substring(0, 16).getBytes("UTF-8") 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));

I got an output like this: 我有这样的输出:

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

To decrypt that in PHP, I used the following code that uses the first 16 chars of key to use it as a key and iv initializer like this: 为了在PHP中解密,我使用以下代码,使用key的前16个字符将其用作keyiv初始值设定项,如下所示:

$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]));

And of course I got the wanted JSON data I encrypted with Java: 当然,我得到了用Java加密的想要的JSON数据:

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

It's strange you do not get an error at this line: 奇怪的是你没有在这一行得到错误:

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

because I do using JDK 1.8 with: 因为我使用JDK 1.8

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM