AES Interop Between PHP and Java (Part 1)
… Life is never easy, learning takes time. Hope this will help someone out there …
The Problem: I want to encrypt a message in PHP using AES and then take it to a Java program to decrypt it.
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:
- We are using mcrypt with PHP. The encryption program in PHP:
001 <?php 002 $cipher = "rijndael-128"; 003 $mode = "cbc"; 004 $plain_text = "Hello World"; 005 $secret_key = "01234567890abcde"; 006 $iv = "fedcba9876543210"; 007 008 td = mcrypt_module_open($cipher, "", $mode, $iv); 009 mcrypt_generic_init($td, $secret_key, $iv); 010 $cyper_text = mcrypt_generic($td, $plain_text); 011 echo bin2hex($cyper_text); 012 mcrypt_generic_deinit($td); 013 mcrypt_module_close($td); 014 ?>
- The output from the above program should be “ac5c3404f57a5061f36a694eb5d56214″
- We just take the output and decrypt it over in the following Java program:
001 import javax.crypto.spec.IvParameterSpec; 002 import javax.crypto.Cipher; 003 import java.security.MessageDigest; 004 import java.security.NoSuchAlgorithmException; 005 import java.lang.Exception; 006 import javax.crypto.spec.SecretKeySpec; 007 import javax.crypto.SecretKey; 008 import java.io.IOException; 009 010 public class tester { 011 public static byte[] hexToBytes(String str) { 012 if (str==null) { 013 return null; 014 } else if (str.length() < 2) { 015 return null; 016 } else { 017 int len = str.length() / 2; 018 byte[] buffer = new byte[len]; 019 for (int i=0; i<len; i++) { 020 buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16); 021 } 022 return buffer; 023 } 024 } 025 026 public static void main(String [] args) throws Exception { 027 Cipher cipher = Cipher.getInstance("AES/CBC/NoPadding"); 028 SecretKeySpec keySpec = new SecretKeySpec("01234567890abcde".getBytes(), "AES"); 029 IvParameterSpec ivSpec = new IvParameterSpec("fedcba9876543210".getBytes()); 030 cipher.init(Cipher.DECRYPT_MODE, keySpec, ivSpec); 031 byte[] outText = cipher.doFinal(hexToBytes("ac5c3404f57a5061f36a694eb5d56214")); 032 System.out.println(new String(outText).trim()); 033 } 034 } - The output from the Java program should be “Hello World”. Take note that on line 31, we put in the output from PHP.
February 10th, 2007 at 2:21 am
Hi..
Is it possible to do other way round ? encypting in Java and decrypting in PHP ?
Thanks
March 11th, 2007 at 5:05 am
Hey thanks a lot, exactly what I needed, exactly when I needed it
I really wish mcrypt had PKCS#5 padding…
March 12th, 2007 at 8:56 pm
Marc: Thanks, I wish mcrypt has PKCS5 padding too. I think someone wrote a function for it. Check out http://www.php.net/mcrypt (comment from duerra_NOT_THIS_ at pushitlive dot net).
Amit: I have been away for a long Chinese New Year holidays and finally get around to do a post of what you are looking for, encrypting in Java and decrypting in PHP. Check out my new post at http://www.propaso.com/blog/2007/03/12/aes-interop-between-php-and-java-part-2-working-the-other-way-around/
April 4th, 2007 at 4:44 pm
i tried to encrypt with very long text
but the result is error
it said that the string is too long
can u help me???
April 4th, 2007 at 4:45 pm
sorry with the 1st post
i mean decrypt not encrypt
April 4th, 2007 at 4:55 pm
I assume that you are encrypting with PHP and decrypting with Java. Could you give an idea of how long is your string (in term of number of characters)??
April 6th, 2007 at 12:54 pm
yo’re right i’m encrypting with php and decrypt with java..
i copy the hexadesimal string from encrypted file
the string long is 507808 character
April 6th, 2007 at 1:13 pm
this is the string…… 1ebcd6f2544c777c1779
1a3d8846133fc5
May 18th, 2007 at 12:05 pm
[…] Problem: Part 1 and Part 2 has been quite interesting. I was thinking of what to do next and Robi Ilham asked me to […]
May 18th, 2007 at 12:06 pm
[…] 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 […]
September 6th, 2007 at 1:00 am
Should the final parameter in the call to mcrypt_module_open be “” (rather than $iv)?
September 6th, 2007 at 9:16 am
In Java, we set the initial vector to
IvParameterSpec ivSpec = new IvParameterSpec(”fedcba9876543210″.getBytes());
for decryption, so the initial vector in PHP for encryption should be the corresponding
mcrypt_generic_init($td, $secret_key, $iv);
where $iv is set to “fedcba9876543210″
November 10th, 2007 at 3:06 pm
Hi, im trying to encrypt using php and decript using ruby. Im having trouble getting ruby to do the same and I think its either a padding or a encoding issue. I took your example and the php part works fine, my ruby example is here:
1. secret = “01234567890abcde”
2. otherCval = “Hello World”
3. c3 = OpenSSL::Cipher::Cipher.new(”aes-128-cbc”)
4. c3.key = key3 = Digest::SHA1.hexdigest(secret).unpack(’a2′*16).map{|x| x.hex}.pack(’c'*16)
5. c3.iv = “fedcba9876543210″
6. c3.decrypt
7. hexval = “ac5c3404f57a5061f36a694eb5d56214″
8. regval = hexval.unpack(’a2′*16).map{|x| x.hex}.pack(’c'*16) %>
9. regval =
10. d = c3.update(regval)
11. d
February 8th, 2008 at 2:53 pm
How can I store my key in a password protected file for later use?
M
February 12th, 2008 at 4:04 pm
Hi,
Can someone help me. I have been trying to do this and it is almost a week now. I am stuck in the final.
Actually the php team has written the encryption and decryption program and it needs to be converted to java. This means that the php server will send some encrypted info and the key to java server and java should decrypt it and vice versa.
The php version of encryption is:
———————————————
function encrypt($val, $key)
{
$key = hex2bin($key);
$td = mcrypt_module_open (’xtea’, ”, ‘ecb’, ”);
mcrypt_generic_init ($td, $key, “00000000″);
$encrypted_data = mcrypt_generic ($td, $val);
mcrypt_generic_deinit ($td);
mcrypt_module_close ($td);
return bin2hex($encrypted_data);
}
————————————————–
and the java equivalent that i wrote was :
public static void main(String[] args) throws Exception
{
String key = “01234567890abcde01234567890abcde”;
String data = “Hello World”;
byte[] byteValKey = hexToBytes(key);
Security.addProvider(new org.bouncycastle.jce.provider.BouncyCastleProvider());
SecretKeySpec keyspec = new SecretKeySpec(byteValKey, “XTEA”);
Cipher cipher1 = Cipher.getInstance(”XTEA/ECB/PKCS5Padding”,”BC”);
cipher1.init(Cipher.ENCRYPT_MODE, keyspec);
byte[] encrypted = cipher1.doFinal(data.getBytes());
System.out.println(”Encrypted: ” + bytesToHex(encrypted));
}
————————————————————
the decryption program for php is:
function decrypt($crypt, $key)
{
$key = hex2bin($key);
$crypt = hex2bin($crypt);
$td = mcrypt_module_open (’xtea’, ”, ‘ecb’, ”);
mcrypt_generic_init ($td, $key, “00000000″);
$decrypted_data = mdecrypt_generic ($td, $crypt);
mcrypt_generic_deinit ($td);
mcrypt_module_close ($td);
return rtrim($decrypted_data);
}
——————————————————–
when i tried to encrypt a string say “Hello World” and get the result and feed this result in the php decrypt program, then i see “Hello World” + some special characters at the end. I do not know how those special characters appear. I think i have give the wrong padding or i really dont know where i am wrong. Also i am yet to write the equivalent decrypt function in java. Can anyone please help.
Thanks so much
February 12th, 2008 at 5:40 pm
Let me quote from php.net manual (by duerra_NOT_THIS_ at pushitlive dot net):
< ?
function encrypt_something($input)
{
$size = mcrypt_get_block_size('des', 'ecb');
$input = pkcs5_pad($input, $size);
$key = 'YOUR SECRET KEY HERE';
$td = mcrypt_module_open('des', '', 'ecb', '');
$iv = mcrypt_create_iv (mcrypt_enc_get_iv_size($td), MCRYPT_RAND);
mcrypt_generic_init($td, $key, $iv);
$data = mcrypt_generic($td, $input);
mcrypt_generic_deinit($td);
mcrypt_module_close($td);
$data = base64_encode($data);
return $data;
}
function pkcs5_pad ($text, $blocksize)
{
$pad = $blocksize - (strlen($text) % $blocksize);
return $text . str_repeat(chr($pad), $pad);
}
function pkcs5_unpad($text)
{
$pad = ord($text{strlen($text)-1});
if ($pad > strlen($text)) return false;
if (strspn($text, chr($pad), strlen($text) - $pad) != $pad) return false;
return substr($text, 0, -1 * $pad);
}
?>
April 28th, 2008 at 3:16 pm
I have a requirement of same encryption in Java and PHP both.Since I am entering data like user id i.e email id from Java client and Vaildating it from PHP client when user try to login.
I need the same encryption from both Java and PHP.I have the following code in PHP and Java giving me 2 different output for same input string.
Any help is appreciated.
Following are the Encryption code in JAVA and PHP
public static String encryptString(String plaintext) {
// String plaintext = padString(”password insurent”,’ ‘,16);
String padedtext = padString(plaintext, ‘ ‘, 16);
String key = “17293045806insur”;
String iv = “fedcba9876543210″;
SecretKeySpec keyspec = new SecretKeySpec(key.getBytes(), “AES”);
IvParameterSpec ivspec = new IvParameterSpec(iv.getBytes());
Cipher cipher;
byte[] encrypted = null;
try {
cipher = Cipher.getInstance(”AES/CBC/NoPadding”);
cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec);
encrypted = cipher.doFinal(padedtext.getBytes());
} catch (NoSuchAlgorithmException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (NoSuchPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidKeyException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (InvalidAlgorithmParameterException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IllegalBlockSizeException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (BadPaddingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(”Encrypted: ” + bytesToHex(encrypted));
return bytesToHex(encrypted);
}
from java
input=”pkamble@insurent.com”
output =d02b17d1f918d4d0c38f1f19094d2e0e998e45fa62df7bd3942d1add3caa29e3
from php for input=”pkamble@insurent.com”
output =d02b17d1f918d4d0c38f1f19094d2e0e988cd26028732c56fd2cf875989b3d4d
PHP Code
April 29th, 2008 at 4:27 am
Hi Pravin,
Sorry can you post your PHP code again?
December 6th, 2008 at 2:29 pm
Hi Pravin,
We have used the php and java encryption and decryption code that was explained in the blog. It seems quite helpful.
We are able to do the encryption/decryption in all below 4 cases. Viz
1. File encrypted in php and decrypted in php on the same machine - Works
2. File encrypted in Java and decrypted in Java on the same machine - Works
3. File encrypted in php and decrypted in Java on the same machine - Works
4. File encrypted in Java and decrypted in php on the same machine - Works
However, when we download the encrypted file using an ftpclient or java FTPClient library, the downloaded file becomes corrupt and the decryption fails.
The server used was windows 2003 and ftpclient is filezilla.
Can you help us with this one. Is there any solution as to not corrupt the encrypted file using any ftpclient.
When Decrypting the downloaded file, only a few characters get decrypted, and all other character become Junk.
Can you please help us.
Thanks
Sandhya
December 8th, 2008 at 6:07 am
Hi Sandhya,
What you explained, does not make sense. If you can encrypt a file, copy it via a flash drive to another machine and decrypt it. You basically can ftp and download it.
Please double check your keys, etc.
July 9th, 2009 at 1:42 pm
Hi linus.. im a starter on cryptography programming. currently im doing an a simple encryption software that work like an article you posted above. the problem is, how to make the length of the cipher text become shorter, maybe 8 character? in other side, the java also able to decrypt it. which part should i add or modify? thanks..
July 10th, 2009 at 2:42 am
Hi Catherine,
If I haven’t returned all the knowledge my lecturer taught me during collage days, for encryption, cypher text increase with the amount of plain text that you have. This is not the same as hashes like MD5, SHA, etc., which only product a specific length of digest.
July 11th, 2009 at 2:36 pm
i see.. anyway that’s not a problem..
currently i am facing a problem which when i use a decryption on j2me sdk. some errors are shown up on SecretKeySpec, IvParameterSpec with the cannot find symbol warning. i have import the correct package. im really stuck on this now. please help me… this is my final year project and the submission date gonna be next week.. thanks alot…