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.