Home > Java Core > java security > AES Encryption Class Compatible with Java and PHP

AES Encryption Class Compatible with Java and PHP

Most of the time we come across a scenario where we want something that is encrypted in Java, that requires to be decrypted by PHP or vice versa. In this article, we will build a Java class that encrypt-decrypt the input string and the same class in PHP which also encrypt-decrypts the input string and produces the same result.

AES Encryption Decryption in Java

import javax.crypto.Cipher;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;

import java.util.Base64;

public class JavaPHPCompatibleEncryption {

    private static String CIPHER_NAME = "AES/CBC/PKCS5PADDING";
    private static int CIPHER_KEY_LEN = 16; //128 bits

    public static final String ENCRYPTION_KEY = "u7k3g4e6n7t6h7l2"; // 128 bit key
    public static final String ENCRYPTION_IV = "9876543210fedcba"; // 16 bytes IV


    public static String encryptToHex(String key, String iv, String data) {
        try {
            if (key.length() < JavaPHPCompatibleEncryption.CIPHER_KEY_LEN) {
                int numPad = JavaPHPCompatibleEncryption.CIPHER_KEY_LEN - key.length();

                for(int i = 0; i < numPad; i++){
                    key += "0"; //0 pad to len 16 bytes
                }

            } else if (key.length() > JavaPHPCompatibleEncryption.CIPHER_KEY_LEN) {
                key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
            }

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

            Cipher cipher = Cipher.getInstance(JavaPHPCompatibleEncryption.CIPHER_NAME);
            cipher.init(Cipher.ENCRYPT_MODE, skeySpec, initVector);

            byte[] encryptedData = cipher.doFinal((data.getBytes()));

            String base64_EncryptedData = Base64.getEncoder().encodeToString(encryptedData);
            String base64_IV = Base64.getEncoder().encodeToString(iv.getBytes("UTF-8"));

            return asciiToHex(base64_EncryptedData + ":" + base64_IV);

        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }


    public static String decryptFromHex(String key, String hexdata) {
        try {
            if (key.length() < JavaPHPCompatibleEncryption.CIPHER_KEY_LEN) {
                int numPad = JavaPHPCompatibleEncryption.CIPHER_KEY_LEN - key.length();

                for(int i = 0; i < numPad; i++){
                    key += "0"; //0 pad to len 16 bytes
                }

            } else if (key.length() > JavaPHPCompatibleEncryption.CIPHER_KEY_LEN) {
                key = key.substring(0, CIPHER_KEY_LEN); //truncate to 16 bytes
            }

            String data = hexToAscii(hexdata);

            String[] parts = data.split(":");

            IvParameterSpec iv = new IvParameterSpec(Base64.getDecoder().decode(parts[1]));
            SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes("UTF-8"), "AES");

            Cipher cipher = Cipher.getInstance(JavaPHPCompatibleEncryption.CIPHER_NAME);
            cipher.init(Cipher.DECRYPT_MODE, skeySpec, iv);

            byte[] decodedEncryptedData = Base64.getDecoder().decode(parts[0]);

            byte[] original = cipher.doFinal(decodedEncryptedData);

            return new String(original);
        } catch (Exception ex) {
            ex.printStackTrace();
        }

        return null;
    }

    private static String asciiToHex(String asciiStr) {
        char[] chars = asciiStr.toCharArray();
        StringBuilder hex = new StringBuilder();
        for (char ch : chars) {
            hex.append(Integer.toHexString((int) ch));
        }

        return hex.toString();
    }

    private static String hexToAscii(String hexStr) {
        StringBuilder output = new StringBuilder("");

        for (int i = 0; i < hexStr.length(); i += 2) {
            String str = hexStr.substring(i, i + 2);
            output.append((char) Integer.parseInt(str, 16));
        }

        return output.toString();
    }

    public static void main(String[] args) {

        String input = "Hi, I am using AES Enc-Dec Algorithm";
        String enc = encryptToHex(ENCRYPTION_KEY, ENCRYPTION_IV, input);
        String dec = decryptFromHex(ENCRYPTION_KEY,enc);
        System.out.println("Input Text     : " + input);
        System.out.println("Encrypted Text : " + enc);
        System.out.println("Decrypted Text : " + dec);
    }
}

The output of the above Java class –

Input Text     : Hi, I am using AES Enc-Dec Algorithm

Encrypted Text : 314e4d51397a2f566d6947375a7137574c646a7a6747784137587a694c78586d375555485a70587249596b6b5a2f736b6e3550426b38695136634f716a7830693a4f5467334e6a55304d7a49784d475a6c5a474e6959513d3d

Decrypted Text : Hi, I am using AES Enc-Dec Algorithm

AES Encryption Decryption in PHP

<?php

class JavaPHPCompatibleEncryption {

    private static $OPENSSL_CIPHER_NAME = "aes-128-cbc"; //Name of OpenSSL Cipher 
    private static $CIPHER_KEY_LEN = 16; //128 bits

    static function encrypt($key, $iv, $data) {
    
        if (strlen($key) < JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN) {
            $key = str_pad("$key", JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN, "0"); //0 pad to len 16
        } else if (strlen($key) > JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN) {
            $key = substr($str, 0, JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN); //truncate to 16 bytes
        }
        
        $encodedEncryptedData = base64_encode(openssl_encrypt($data, JavaPHPCompatibleEncryption::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, $iv));
        $encodedIV = base64_encode($iv);
        $encryptedPayload = $encodedEncryptedData.":".$encodedIV;

        return bin2hex($encryptedPayload);
        
    }

    
    static function decrypt($key, $data) {
        if (strlen($key) < JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN) {
            $key = str_pad("$key", JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN, "0"); //0 pad to len 16
        } else if (strlen($key) > JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN) {
            $key = substr($str, 0, JavaPHPCompatibleEncryption::$CIPHER_KEY_LEN); //truncate to 16 bytes
        }
        $dataStr = hex2bin($data);
        
        $parts = explode(':', $dataStr); //Separate Encrypted data from iv.
        $decryptedData = openssl_decrypt(base64_decode($parts[0]), JavaPHPCompatibleEncryption::$OPENSSL_CIPHER_NAME, $key, OPENSSL_RAW_DATA, base64_decode($parts[1]));
        
        return $decryptedData;
    }

}


$iv = '9876543210fedcba';
$key = 'u7k3g4e6n7t6h7l2';

$inputData = "Hi, I am using AES Enc-Dec Algorithm";

echo "Input Text     : $inputData <br><br>";

$encrypted = JavaPHPCompatibleEncryption::encrypt($key, $iv, $inputData);

echo "Encrypted Text: $encrypted <br><br>";

$decryptedPayload = JavaPHPCompatibleEncryption::decrypt($key, $encrypted);

echo "Decrypted Text: $decryptedPayload <br><br>";

?>

The output of the above PHP class –

Input Text : Hi, I am using AES Enc-Dec Algorithm

Encrypted Text: 314e4d51397a2f566d6947375a7137574c646a7a6747784137587a694c78586d375555485a70587249596b6b5a2f736b6e3550426b38695136634f716a7830693a4f5467334e6a55304d7a49784d475a6c5a474e6959513d3d

Decrypted Text: Hi, I am using AES Enc-Dec Algorithm

Here you can see that from both the languages, the same encrypted string is been generated. We can use this in the cross-platform application, where encryption is done at one end and decrypted at another end.