We are using the following code to encrypt data in Java, and trying to convert the logic to PHP. The data encrypted with one language cannot be decrypted with the other language. Is there any difference?
My Java class
public class EncYes {
private static final char[] hexDigits = new char[]{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
public static void main(String[] args) {
try {
String encString=null;
EncYes enc = new EncYes();
switch(args[0]){
case "e":
System.out.println(enc.encrypt(args[1],args[2]));
break;
case "d":
System.out.println(enc.decrypt(args[1],args[2]));
break;
}
} catch (Exception e) {
System.out.println(e);
}
}
public String encrypt(String json, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
Cipher cipher = null;
EncYes enc = new EncYes();
SecretKeySpec skeySpec = new SecretKeySpec(enc.hexfromString(key), "AES");
byte[] ivSrc = new byte[12];
GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivSrc);
cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(1, skeySpec, ivSpec);
byte[] encstr = cipher.doFinal(json.getBytes());
return enc.hextoString(encstr);
}
public String decrypt(String json, String key) throws NoSuchAlgorithmException, NoSuchPaddingException, IllegalBlockSizeException, BadPaddingException, InvalidKeyException, InvalidAlgorithmParameterException {
Cipher cipher = null;
EncYes enc = new EncYes();
SecretKeySpec skeySpec = new SecretKeySpec(enc.hexfromString(key), "AES");
byte[] ivSrc = new byte[12];
GCMParameterSpec ivSpec = new GCMParameterSpec(128, ivSrc);
cipher = Cipher.getInstance("AES/GCM/NoPadding");
cipher.init(2, skeySpec, ivSpec);
byte[] encstr = cipher.doFinal(enc.hexfromString(json));
return new String(encstr);
}
public static byte[] hexfromString(String s) {
int i = s.length();
byte[] abyte0 = new byte[(i + 1) / 2];
int j = 0;
int k = 0;
if (i % 2 == 1) {
abyte0[k++] = (byte)HexfromDigit(s.charAt(j++));
}
while(j < i) {
abyte0[k++] = (byte)(HexfromDigit(s.charAt(j++)) << 4 | HexfromDigit(s.charAt(j++)));
}
return abyte0;
}
public static int HexfromDigit(char c) {
if (c >= '0' && c <= '9')
return c - 48;
if (c >= 'A' && c <= 'F')
return (c - 65) + 10;
if (c >= 'a' && c <= 'f')
return (c - 97) + 10;
else
throw new IllegalArgumentException("invalid hex digit: ");
}
public static String asHex(byte[] buf) {
StringBuffer strbuf = new StringBuffer(buf.length * 2);
for(int i = 0; i < buf.length; ++i) {
if ((buf[i] & 255) < 16) {
strbuf.append("0");
}
strbuf.append(Long.toString((long)(buf[i] & 255), 16));
}
return strbuf.toString();
}
public static String HextoString(byte abyte0[], int i, int j) {
char ac[] = new char[j * 2];
int k = 0;
for (int l = i; l < i + j; l++) {
byte byte0 = abyte0[l];
ac[k++] = hexDigits[byte0 >>> 4 & 0xf];
ac[k++] = hexDigits[byte0 & 0xf];
}
return new String(ac);
}
public static String hextoString(byte[] abyte0) {
return HextoString(abyte0, 0, abyte0.length);
}
public static String generateIv() {
UUID uId = UUID.randomUUID();
return uId.toString().replace("-", "");
}
}
My PHP class
class EncYes {
private static $hexDigits = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'];
public static function main($args) {
try {
$enc = new EncYes();
switch ($args[0]) {
case "e":
return $enc->encrypt($args[1], $args[2]) . "\n";
break;
case "d":
return $enc->decrypt($args[1], $args[2]) . "\n";
break;
}
} catch (Exception $e) {
echo $e->getMessage() . "\n";
}
}
public function encrypt($json, $key) {
$iv = str_repeat("\0", 12);
$cipher = "aes-128-gcm";
$tag = "";
$encrypted = openssl_encrypt($json, $cipher, $this->hexfromString($key), OPENSSL_RAW_DATA, $iv, $tag,"",12);
if ($encrypted === false) {
throw new Exception("Encryption failed");
}
return $this->hextoString($encrypted . $tag);
}
public function decrypt($json, $key) {
$iv = str_repeat("\0", 12); // 12-byte IV filled with zeros
$cipher = "aes-128-gcm";
$data = $this->hexfromString($json);
$encrypted = substr($data, 0, -12);
$tag = substr($data, -12);
$decrypted = openssl_decrypt($encrypted, $cipher, $this->hexfromString($key), OPENSSL_RAW_DATA, $iv, $tag);
if ($decrypted === false) {
throw new Exception("Decryption failed");
}
return $decrypted;
}
public static function hexfromString($s) {
$i = strlen($s);
$abyte0 = array_fill(0, (int)(($i + 1) / 2), 0);
$j = 0;
$k = 0;
if ($i % 2 == 1) {
$abyte0[$k++] = self::HexfromDigit($s[$j++]);
}
while ($j < $i) {
$abyte0[$k++] = (self::HexfromDigit($s[$j++]) << 4) | self::HexfromDigit($s[$j++]);
}
return implode(array_map("chr", $abyte0));
}
public static function HexfromDigit($c) {
if ($c >= '0' && $c <= '9') {
return ord($c) - ord('0');
}
if ($c >= 'A' && $c <= 'F') {
return (ord($c) - ord('A')) + 10;
}
if ($c >= 'a' && $c <= 'f') {
return (ord($c) - ord('a')) + 10;
}
throw new InvalidArgumentException("invalid hex digit: " . $c);
}
public static function asHex($buf) {
$strbuf = "";
for ($i = 0; $i < strlen($buf); $i++) {
$byte = ord($buf[$i]);
if (($byte & 255) < 16) {
$strbuf .= "0";
}
$strbuf .= dechex($byte & 255);
}
return $strbuf;
}
public static function HextoString2($abyte0, $i, $j) {
$ac = array_fill(0, $j * 2, '0');
$k = 0;
for ($l = $i; $l < $i + $j; $l++) {
$byte0 = ord($abyte0[$l]);
$ac[$k++] = self::$hexDigits[$byte0 >> 4 & 0xf];
$ac[$k++] = self::$hexDigits[$byte0 & 0xf];
}
return implode("", $ac);
}
public static function hextoString($abyte0) {
return self::HextoString2($abyte0, 0, strlen($abyte0));
}
public static function generateIv() {
return str_replace("-", "", uuid_create());
}
}
Sample data for the Java code:
Encryption -------------------
java EncYes "e" "Hello" "a59d23ac19020c989cd8566a4ea16646ad4e02f67516cedc3bd7d833efda516a"
B062024E2B9C4D4FFB204AB3622459CEFEAEFF969D
Decryption ------------------
java EncYes "d" "B062024E2B9C4D4FFB204AB3622459CEFEAEFF969D" "a59d23ac19020c989cd8566a4ea16646ad4e02f67516cedc3bd7d833efda516a"
Hello