Warning: fopen(/home/partdesi/public_html/propaso/blog/wp-content/cache/wp_cache_mutex.lock) [function.fopen]: failed to open stream: Permission denied in /home/partdesi/public_html/propaso/blog/wp-content/plugins/wp-cache/wp-cache-phase2.php on line 96
Fun Things in Life » Blog Archive » AES Interop Between PHP and Java (Part 2)

AES Interop Between PHP and Java (Part 2)

… 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”.

24 Responses to “AES Interop Between PHP and Java (Part 2)”

  1. linus Says:

    Just for your information, there is a blog to show how to Encrypt in PHP and Decrypt in Java here http://www.propaso.com/blog/2007/01/27/aes-interop-between-php-and-java/

  2. Valerian Says:

    Your script makes me shimmer with desire, except that you don’t indicate where to find or what is in the includes:

    import javax.crypto.*;
    002 import javax.crypto.spec.*;
    003 import java.security.*;
    004 import java.io.*;

    “So hot right now”

  3. Valerian Says:

    Nevermind. I see that you’re going from Java to PHP, not Javascript. How typical of a tyrannical leader like myself to make such a mistake.

  4. linus Says:

    Hi Valerian,

    It would be really nice if you have a JavaScript version of AES encryption/decryption that you might want to share it here. If not I might get myself to do it if I am feeling not that lazy.

  5. Matt Says:

    > You can work out the padding part of Java program (or someone is nice enough to put it in > the comment

    This example covers exactly what I’m looking for except that I need to be able to encrypt a string that varies greatly in length (a.k.a. no cheating with 16 byte strings). Could someone post a modified version of the example above (both sides: java & php) that can handle this? Thanks in advance!

  6. Thiago Says:

    I have the same problem. I need to encrypt in java and decript in php…(without hacking)
    How do this?

    Thanks

  7. linus Says:

    Hello,

    I have wrote a quick patch for padding the characters since there are two request for it and no one had put it in yet. First, add the following function to the program:

    public static String padString(String source, char paddingChar, int size) {
    int padLength = size-source.length()%size;
    for (int i = 0; i < padLength; i++) {
    source += paddingChar;
    }
    return source;
    }

    then change line 023 in the Java program from:

    String plaintext = “Hello World “;

    to

    String plaintext = padString(”Hello World”, ‘ ‘, 16);

    that should do the trick. (take note that the second parameter is a space ‘ ‘).

  8. Cody Says:

    Hey everybody,

    Writing a cipher in Javascript is *not* something you want to do because it violates rule #1 of encryption: NEVER give anyone they Key.

    In a javascript implementation you give everyone they key, because javascript is run on the client’s machine.

    I’ve recently written a PHP AES class that is 100% FIPS 197 compliant. You could use it to cipher between PHP and any other language, and best of all it doesn’t require any pre-complied libraries for PHP.

    Check it out at http://www.phpaes.com/ *** This is not free code **Admin**

    E-mail me with any questions: cody [at] wshost [dawt] net

  9. linus Says:

    Hi Cody,

    It is possible to use an external JavaScript file using something like:

    <script src="my.js" language="javascript" type="text/javascript"></script>

    However, I am not a guru in JavaScript (or even in PHP or Java), so I not able to advise how secure an external JavaScript is. Sorry that I have to comment on your URL to let others know that it is not free.

  10. Richard Says:

    Linus,
    You cannot put the key in the internal Javascript file like your example above, because, just as the Client browser calls that file with an HTTP GET request, so can anyone else. For example, :

    Your Domain : http://www.somedomain.com

    your program : my.js (called as a include in say index.html

    then I could type : http://www.somedomain.com/my.js

    and read the entire javascript file as text in my browser !!!

    the only only way you can do this in JS is NEVER (unless you use AJAX (php + xml/rpc)

  11. Liam Says:

    There are times where it is absolutely appropriate to say thank you for a great how-to. Thank you for this post. It fit like a puzzle piece into a project I was working on and simply did not want to look into all the api’s for php for the aes encryption (much less CBC!!!). I have the front and back end built in java (jsp).. thank you again!

  12. Heiner Says:

    Hi,

    I use mcrypt to store some passwords in a db.
    Now i want to decrpyt those pw on the client side. I really don’t know anything about java.
    Is this a java-applet which can be run from a browser? How would I compile it. I googled a little bit, but am not sure what to google for really.

    Any suggestions on any (simple) java starting howto would be nice.
    Any applets i can use would be even better… :)
    I hope anybody can point me in the right direction.
    Thankx

  13. linus Says:

    Hi Heiner,

    You can actually decrypt it in PHP, if there is no requirement to use Java. However, if you are interested in using Applet, you can start by looking at http://www.realapplets.com/tutorial/HelloWorld.html

  14. Heiner Says:

    Hi linus,

    I know that I can decrypt in PHP. I already realized an application that en-/decrypts. I found this blog when I searched for a possibility to decrypt the passwords on the client side.
    If that is somehow possible (I don’t even know if the java-source, which is posted here, can be executed at the client end) I would not have to think about a ssl-encryption for my little script.

    Even with a ssl-encryption I would rather send the data encrypted to the client and then locally decrypt it.

    Thx for the reply and I hope for more… :)

  15. Heiner Says:

    OK, when I compile the source from PART 1 and try to run it my java console throws this errors:

    java.lang.ClassCastException: tester cannot be cast to java.applet.Applet
    at sun.applet.AppletPanel.createApplet(Unknown Source)
    at sun.plugin.AppletViewer.createApplet(Unknown Source)
    at sun.applet.AppletPanel.runLoader(Unknown Source)
    at sun.applet.AppletPanel.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)
    java.lang.ClassCastException: tester cannot be cast to java.applet.Applet
    at sun.applet.AppletPanel.createApplet(Unknown Source)
    at sun.plugin.AppletViewer.createApplet(Unknown Source)
    at sun.applet.AppletPanel.runLoader(Unknown Source)
    at sun.applet.AppletPanel.run(Unknown Source)
    at java.lang.Thread.run(Unknown Source)

    What did I do wrong?
    The HelloWorld example from the posted website from linus did work fine…

  16. Audrey Says:

    Thank you for these examples. Wanted to let you know that the links from php.net/mcrypt do not work anymore.

    Part 1 - Encrypt Using PHP / Decrypt Using Java
    http://www.propaso.com/blog/2007/01/27/aes-interop-between-php-and-java/

    Part 2 - Encrypt Using Java / Decrypt Using PHP
    http://www.propaso.com/blog/2007/03/12/aes-interop-between-php-and-java
    -part-2-working-the-other-way-around/

  17. linus Says:

    Hi Audrey,

    Thanks for informing me, I will update the php.net soon.

  18. Fun Things in Life » Blog Archive » AES Interop Between PHP and Java (Part 3) Says:

    […] Things in Life What’s Life without Fun? « AES Interop Between PHP and Java (Part 2) AES Interop Between PHP and Java (Part 4) […]

  19. Daniel Craig Says:

    Hi there, I was looking around for a while searching for aes encryption and I happened upon this site and your post regarding AES Interop Between PHP and Java (Part 2), I will definitely this to my aes encryption bookmarks!

  20. runsvalid Says:

    thanks for this! my php host doesn’t have mcrypt installed, unfortunately, so i went around looking for libraries that didn’t require it.

    there’s http://www.phpaes.com/ as mentioned above but that’s not free. here’s one that is:

    http://phpseclib.sourceforge.net/documentation/crypt.html#crypt_aes_benchmarks

    LGPL licensed and 11x faster than the one at http://www.phpaes.com/. uses mcrypt if available, php otherwise.

  21. shimul Says:

    great tutorial

    thanks

  22. ndeh Says:

    MCRYPT CBC Interoperability seems fine.
    But MCRYPT OFB Does not match !!! with others implementations.
    What is wrong with OFB ?

  23. linus Says:

    Hi ndeh,

    I have never tried OFB. As I am not really an expert in encryption. I will try to understand more.

  24. Shane Says:

    First of all, I’d like to saya BIG THANK YOU for this blog! You saved me a lot of time and effort!!!

    I did face a little trouble compiling the php code you provided though. The error involved something to do with an incorrect IV size. So, i replaced the IV with “” and then added an extra line. It works well like this:

    $td = mcrypt_module_open(”rijndael-128″, “”, “cbc”, “”);
    mcrypt_generic_init($td, $key, $iv);

    Hope this will helpful to someone. Thanks again!!!

Leave a Reply