Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JAVA PHP Encryption Decryption

Tags:

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.

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.

I have tried different modes like AES/CBC/NoPadding but I get an exception

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.

Key is a md5 hash.

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. The resulting hash is then to be used as a key for the AES encryption. The IV is supposed to be the first 16 chars of the hash. When the encryption is done the result should be encoded in base64 and sent to the server.

like image 397
user3718908x100 Avatar asked Aug 12 '17 11:08

user3718908x100


People also ask

How do you use encrypt and decrypt in PHP?

In PHP, Encryption and Decryption of a string is possible using one of the Cryptography Extensions called OpenSSL function for encrypt and decrypt. openssl_encrypt() Function: The openssl_encrypt() function is used to encrypt the data. Parameters: $data: It holds the string or data which need to be encrypted.

Which encryption is best for PHP?

Secret key encryption (or symmetric encryption as it's also known) uses a single key to both encrypt and decrypt data. In the past PHP relied on mcrypt and openssl for secret key encryption. PHP 7.2 introduced Sodium, which is more modern and widely considered more secure.

Can AES 256 be decrypted?

Only those who have the special key can decrypt it. AES uses symmetric key encryption, which involves the use of only one secret key to cipher and decipher information.


1 Answers

Trying to reverse this, I got an error of

java.security.InvalidKeyException: Illegal key size

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:

    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:

$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:

{
        "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:

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import org.apache.commons.codec.binary.Base64;
like image 72
Christos Lytras Avatar answered Oct 20 '22 05:10

Christos Lytras