Archive for March, 2007

AES Interop Between PHP and Java (Part 2)

Monday, March 12th, 2007

… Give him a fish; you fed him for today. Teach him how to fish; you fed him for life …

The Problem: In a previous post, I show how to use AES in PHP to encrypt a message and decrypt it in Java. Then Amit asked if it could be done the other way around.

Again, without all the knowledge about AES, Key, CBC, ECB, etc, etc… I will present a simple solution. Keep in mind, these are bits and pieces, so that I wouldn’t take all the fun out of you. I will just show you how to encrypt and decrypt and you can implement other things in between so that you can also have the fun.

The Solution:

  1. Encrypt a message in Java:
    001	import javax.crypto.*;
    002	import javax.crypto.spec.*;
    003	import java.security.*;
    004	import java.io.*;
    005
    006	public class tester {
    007	  public static String bytesToHex(byte[] data) {
    008	    if (data==null) {
    009	      return null;
    010	    } else {
    011	      int len = data.length;
    012	      String str = "";
    013	      for (int i=0; i<len; i++) {
    014	        if ((data[i]&0xFF)<16)
    015	          str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF);
    016	        else
    017               str = str + java.lang.Integer.toHexString(data[i]&0xFF);
    018	      }
    019	    return str;
    020	  }
    021
    022	  public static void main(String[] args) throws Exception {
    023	    String plaintext = "Hello World     ";
    024         String key = "01234567890abcde";
    025         String iv = "fedcba9876543210";
    026
    027         SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), "AES");
    028         IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
    029
    030	    Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding");
    031	    cipher.init(Cipher.ENCRYPT_MODE,keyspec,ivspec);
    032	    byte[] encrypted = cipher.doFinal(plaintext.getBytes());
    033
    034         System.out.println("Encrypted: " + bytesToHex(encrypted));
    035
    036         cipher.init(Cipher.DECRYPT_MODE,keyspec,ivspec);
    037	    byte[] decrypted = cipher.doFinal(encrypted);
    038	    System.out.println(new String(decrypted));
    039	  }
    040	}
  2. The output of the Java program should be “444e6969a269829a3e59a86300614fc5″. Take note that I cheated by making the plain text message as “Hello World ” (16 bytes). You can work out the padding part of Java program (or someone is nice enough to put it in the comment).
  3. We just take the output and decrypt it over in the following PHP program:
    001	<?php
    002	function hex2bin($hexdata) {
    003	  $bindata="";
    004
    005	  for ($i=0;$i<strlen($hexdata);$i+=2) {
    006	   $bindata.=chr(hexdec(substr($hexdata,$i,2)));
    007	  }
    008
    009	  return $bindata;
    010	}
    011
    012	$cipher     = "rijndael-128";
    013	$mode       = "cbc";
    014	$secret_key = "01234567890abcde";
    015	$iv         = "fedcba9876543210";
    016
    017	$td = mcrypt_module_open($cipher, "", $mode, $iv);
    018
    019	mcrypt_generic_init($td, $secret_key, $iv);
    020	$decrypted_text = mdecrypt_generic($td, hex2bin("444e6969a269829a3e59a86300614fc5"));
    021	echo trim($decrypted_text);
    022	mcrypt_generic_deinit($td);
    023	mcrypt_module_close($td);
    024	?>
  4. The output should be “Hello World”.