Encrypt / Decrypt Between Android and PHP

10 votes · 54 comments

This is the code in Android (Java) and PHP to encrypt and decrypt Strings


mcrypt = new MCrypt();
/* Encrypt */
String encrypted = MCrypt.bytesToHex( mcrypt.encrypt("Text to Encrypt") );
/* Decrypt */
String decrypted = new String( mcrypt.decrypt( encrypted ) );


$mcrypt = new MCrypt();
$encrypted = $mcrypt->encrypt("Text to encrypt");
$decrypted = $mcrypt->decrypt($encrypted);
raw ·
· download
/***********/ /**JAVA**/ import java.security.NoSuchAlgorithmException; import javax.crypto.Cipher; import javax.crypto.NoSuchPaddingException; import javax.crypto.spec.IvParameterSpec; import javax.crypto.spec.SecretKeySpec; public class MCrypt { private String iv = "fedcba9876543210";//Dummy iv (CHANGE IT!) private IvParameterSpec ivspec; private SecretKeySpec keyspec; private Cipher cipher; private String SecretKey = "0123456789abcdef";//Dummy secretKey (CHANGE IT!) public MCrypt() { ivspec = new IvParameterSpec(iv.getBytes()); keyspec = new SecretKeySpec(SecretKey.getBytes(), "AES"); try { cipher = Cipher.getInstance("AES/CBC/NoPadding"); } catch (NoSuchAlgorithmException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (NoSuchPaddingException e) { // TODO Auto-generated catch block e.printStackTrace(); } } public byte[] encrypt(String text) throws Exception { if(text == null || text.length() == 0) throw new Exception("Empty string"); byte[] encrypted = null; try { cipher.init(Cipher.ENCRYPT_MODE, keyspec, ivspec); encrypted = cipher.doFinal(padString(text).getBytes()); } catch (Exception e) { throw new Exception("[encrypt] " + e.getMessage()); } return encrypted; } public byte[] decrypt(String code) throws Exception { if(code == null || code.length() == 0) throw new Exception("Empty string"); byte[] decrypted = null; try { cipher.init(Cipher.DECRYPT_MODE, keyspec, ivspec); decrypted = cipher.doFinal(hexToBytes(code)); } catch (Exception e) { throw new Exception("[decrypt] " + e.getMessage()); } return decrypted; } public static String bytesToHex(byte[] data) { if (data==null) { return null; } int len = data.length; String str = ""; for (int i=0; i<len; i++) { if ((data[i]&0xFF)<16) str = str + "0" + java.lang.Integer.toHexString(data[i]&0xFF); else str = str + java.lang.Integer.toHexString(data[i]&0xFF); } return str; } public static byte[] hexToBytes(String str) { if (str==null) { return null; } else if (str.length() < 2) { return null; } else { int len = str.length() / 2; byte[] buffer = new byte[len]; for (int i=0; i<len; i++) { buffer[i] = (byte) Integer.parseInt(str.substring(i*2,i*2+2),16); } return buffer; } } private static String padString(String source) { char paddingChar = ' '; int size = 16; int x = source.length() % size; int padLength = size - x; for (int i = 0; i < padLength; i++) { source += paddingChar; } return source; } } ==================================================== /**********/ /**PHP**/ <?php class MCrypt { private $iv = 'fedcba9876543210'; #Same as in JAVA private $key = '0123456789abcdef'; #Same as in JAVA function __construct() { } function encrypt($str) { //$key = $this->hex2bin($key); $iv = $this->iv; $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); mcrypt_generic_init($td, $this->key, $iv); $encrypted = mcrypt_generic($td, $str); mcrypt_generic_deinit($td); mcrypt_module_close($td); return bin2hex($encrypted); } function decrypt($code) { //$key = $this->hex2bin($key); $code = $this->hex2bin($code); $iv = $this->iv; $td = mcrypt_module_open('rijndael-128', '', 'cbc', $iv); mcrypt_generic_init($td, $this->key, $iv); $decrypted = mdecrypt_generic($td, $code); mcrypt_generic_deinit($td); mcrypt_module_close($td); return utf8_encode(trim($decrypted)); } protected function hex2bin($hexdata) { $bindata = ''; for ($i = 0; $i < strlen($hexdata); $i += 2) { $bindata .= chr(hexdec(substr($hexdata, $i, 2))); } return $bindata; } }
Add a comment


"People aren't hearing all the music. Artists and producers work hard in the studio perfecting their sound. But people can't really hear it with normal headphones. Most headphones can't handle the bass, the detail, the dynamics. Bottom line, the music doesn't move you. With Beats, people are going to hear what the artists hear, and listen to the music the way they should: the way I do."- Dr. Dre

Reply · Aug. 7, 2011, 2:38 p.m.

Monster Beats by Dr. Dre Studio Red Sox Definition Headphones UK belong to Monster beats studio by dr dre UK,dr dre earphones ,it features advanced driver design for precise audio clarity,plus it deep bass, delicate high pitch make it has good sound quality .besides, the different beautiful colour can make you outstanding more easily.You can use Monster Beats by Dr. Dre Studio Red Sox Definition Headphones UK to play the kind of rock, ohip-hop music.

Reply · Aug. 7, 2011, 2:39 p.m.

On the java side of this I am not able to declare the instance of the class as mcrypt = new MCrypt, i must instead declare it as MCrypt mcrypt = new MCrypt;

Additionally MCrypt mcrypt = new MCrypt; String encrypted = MCrypt.bytesToHex( mcrypt.encrypt("Text to Encrypt") ); I get type errors when using the class as you suggest. Can you please tell me what I am doing wrong? Thank you for the neat piece of code you have submitted.

Reply · Nov. 28, 2011, 3:19 a.m.

Hi, Yes you need to add the MCrypt to create the object (I didn't put it as I have that variable already declared as a class attribute. Can you show me the errrors you're getting using the encrypt method?

Reply · Nov. 30, 2011, 3:08 p.m.

Hi, SeRPRo, I was happy to find your easy-to-understand MCrypt code to use it in my Android project. Somehow when I've written unit test to test it before including into my project, it failed. Failure was b/c initial value was not equal to the encryped after decryption - encrypted value contains spaces it it. After trimming encrypted value I got success.

Could you please help in changing code to make encryption without adding extra spaces?

Thank you, Sergey N.

Reply · Jan. 8, 2012, 6:10 p.m.

Hi Sergey, When do you have that problem when you decrypt in JAVA or PHP? because in PHP I did add the trim method. but in Java I didn't need it when I tested it.

Reply · Jan. 12, 2012, 12:49 p.m.

Hi SeRPRo, thanks for the response :) actually I am doing this in Java code, and it seems that it should be also trimmed there. I just wondered if you had to do this or not. e.g. when I encrypt and then decrypt "qwe", decrypt(...) method returns "qwe " with spaces at the end.

Reply · Jan. 14, 2012, 11:22 a.m.

Hi again,

I just looked again at my code, and I don't use any kind of trim on the Java side to decrypt the text, but as the source is available feel free to modify whatever you want. You can modify the decrypt function to return a String instead of byte array and trim it before you return it.

I hope this will help you

Reply · Jan. 16, 2012, 4:16 p.m.

Hi, first thanks for this tutorial

I've got 1 problem : What I encrypt in PHP is a jsonArray but when i decrypt it in Java I've got a jsonObject with at the end some symbol ?

Result: {"id":43,"name":"TOTO"}?

Can you help me ?

Reply · Jan. 13, 2012, 8:46 a.m.

Hi Thomas, When you use that String to create the JSONObject or JSONArray do you get any errors? because I do the same and it's working fine, though I think I don't have that extra character.

Reply · Jan. 16, 2012, 4:11 p.m.

I had the same problem. The decrypted values have some ?? charaters at the and. Looking to it closer, the byte array contains some 0 values. I had no problems with it when using the string at all in android, but when I stored the data in a SharedPreferences file, the XML got corrupted because of it.

I have created a simple function to remove the zero bytes from the end. This solves my problem.

if( bytes.length > 0)
    int trim = 0;
    for( int i = bytes.length - 1; i >= 0; i-- ) if( bytes[i] == 0 ) trim++;

    if( trim > 0 )
        byte[] newArray = new byte[bytes.length - trim];
        System.arraycopy(bytes, 0, newArray, 0, bytes.length - trim);
        bytes = newArray;

Also, I noticed that the bytesToHex was very slow (for encrypting). I replaced it with this one which is much faster:

public static String bytesToHex(byte[] buf)
    char[] chars = new char[2 * buf.length];
    for (int i = 0; i < buf.length; ++i)
        chars[2 * i] = HEX_CHARS[(buf[i] & 0xF0) >>> 4];
        chars[2 * i + 1] = HEX_CHARS[buf[i] & 0x0F];
    return new String(chars);

For the rest perfect code. Thanks for sharing!!!

Reply · Feb. 23, 2012, 8:12 p.m.

how did you declare "HEX_CHARS" and what have you put in it ?

Reply · Nov. 6, 2012, 9:23 p.m.

Can you please tell me where to add this code to remove the ?? characters

Reply · June 5, 2013, 11:55 a.m.

Is it possible to support special chars like the euro sign and german vowel mutations? What do i have to change?


Reply · Jan. 17, 2012, 6:46 a.m.

Sure.. I don't know why I missed that. you need to change the encrypt and decrypt method on your php class:

function encrypt($str) {
  $encrypted = mcrypt_generic($td, utf8_encode($str));

function decrypt($code) {
  return utf8_decode(trim($decrypted));

I hope it helps

Reply · Jan. 17, 2012, 11:03 a.m.

Thx very much, and in Java? :) I tried my best, but i couldn't figure it out. :D

Reply · Jan. 17, 2012, 11:29 a.m.

I tried it in Java and it seems to work fine, do you have problems with Java too?

I created this code and it worked:

import javax.swing.JOptionPane;

public class testJava {

    public static void main(String args[])
        String value = JOptionPane.showInputDialog("Enter a string:");

         * ENCRYPT / DECRYPT
        try {
            MCrypt mcrypt = new MCrypt();
            String encrypted = MCrypt.bytesToHex( mcrypt.encrypt( value ) );
            JOptionPane.showMessageDialog(null, encrypted);
            String decrypted = new String(mcrypt.decrypt( encrypted ));
            JOptionPane.showMessageDialog(null, decrypted);

        } catch (Exception e) {
Reply · Jan. 17, 2012, 2:17 p.m.

If the String contains special chars, he abort the script near this:encrypted = cipher.doFinal(padString(text).getBytes()); I dont know why, but this problem is in Eclipse and on smartphones. :(

Reply · Jan. 17, 2012, 2:29 p.m.

is the String with special chars hard-coded in your project or is it an input string from the smartphone? If you want, you can send me the part of the source where you use it and it fails so I can test it locally. My email is like my username [at] gmail [dot] com

Reply · Jan. 17, 2012, 3:12 p.m.

Hi again. Hard-coded and input string via EditText on Eclipse and on Smartphone.

Here the Code in Android:

alt text

And here what i get:

alt text

Reply · Jan. 18, 2012, 6:23 a.m.

Ok I found the problem in JAVA, just replace the bytesToHex method with:

public static String bytesToHex(byte[] b)
    StringBuffer buf = new StringBuffer();
    int len = b.length;
    for (int j=0; j<len; j++)
    return buf.toString();
public static String byteToHex(byte b)
    char hexDigit[] = {'0', '1', '2', '3', '4', '5', '6', '7',
            '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
    char[] a = { hexDigit[(b >> 4) & 0x0f], hexDigit[b & 0x0f] };
    return new String(a);
Reply · Jan. 18, 2012, 4:45 p.m.

Still the same problem. But after many hours i found the failure. :) Just replace cipher = Cipher.getInstance("AES/CBC/NoPadding"); with cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

Thx for your help. Btw: Very good script. :)

Reply · Jan. 19, 2012, 6:52 a.m.

Works for me in either way.. but I'm glad it finally works for you! :)

Reply · Jan. 19, 2012, 10:06 a.m.


When I use your example (without any changes) on Android and Php, I don't get the same encrypted value. Is this normal?

For Java I'm getting: beb4ce4c41a3c3445be48ad55906f5bc And for PHP I'm getting: cb4b4ca864213684070465b38783a6c8

Do you have any idea what the reason for this difference could be?

Kind regards and thanks! Jan

Reply · Jan. 19, 2012, 8:25 p.m.


That's because of the extra characters were inserted in Java.. try to add the changes on the previous comment and see if it's the same..

Reply · Jan. 20, 2012, 10:26 a.m.


I have added all the above changes, but I'm still getting the same result... What is the expected result to have when you encrypt the "Text to encrypt" with the above algorithm? So that I know whether I have to investigate Java or PHP code...

When I use the AES/CBC/PKCS5Padding I even get: beb4ce4c41a3c3445be48ad55906f5bc9e020255d861b1a91de5f1ecc3a75b2f

Thanks, Jan

Reply · Jan. 21, 2012, 10:22 a.m.

Hi, I have to look deeper in the code but I found that in Java for "Text to encrypt" when I decode the encrypted result what I got is: string(32) "Text to encrypt " (with an added character at the end)

Maybe if you trim the resulted text you can get the same string.

Reply · Jan. 23, 2012, 4:43 p.m.

Hi, well the resulted text is not really the issue (for now) but the encrypted message is already different between php and java so that makes me wonder what's going wrong...

I'm also investigating it since I need this really for a project of mine so let's hope we can find some solution for this.

Thanks anyway! Jan

Reply · Jan. 23, 2012, 6:22 p.m.


I have found the solution for my problem... In the php-code it is state that padding is done using the 0 character, in your example you are doing padding with ' ' (space). If I change that, the encrypted text that I got from php and java are both the same!

Kind regards, Jan

Reply · Jan. 23, 2012, 10:21 p.m.

From one Jan to another;

I have the exact same problem as you had, but I can't seem to really understand what part of the code you changed for it to work. Would you mind elaborating? Sorry for being a beginner at this :)

All the best, Jan

Reply · Jan. 30, 2012, 3 p.m.

Ok I'm so stupid. I got it to work by changing this line in the java-code, like you said: char paddingChar = ' '; to this char paddingChar = 0;

Reply · Jan. 30, 2012, 3:15 p.m.

Yes, that's it.. but I cannot edit my own post.. :)

Reply · March 1, 2012, 2:57 p.m.

Just to understand it: Is this AES-128, AES-196 or AES-256? And why?

Reply · Jan. 21, 2012, 4:22 p.m.

It's AES-128 as you can see the key is 16 bytes long. If you multiplied 16 bytes (Key) by 8 (1 byte = 8 bits) you get 128bits. I just posted is for example purposes. You can modify the code and set the encryption method you want.

I hope this explains your questions.

Reply · Jan. 23, 2012, 4:36 p.m.

hi i am following this tutorial in ur website Encrypt / Decrypt Between Android and PHP and i am getting error as iv must be 16 bytes long but in my case my password will be around 40-50 characters long then how should i declare it so that it can encrypt it properly please help me

Reply · Feb. 23, 2012, 11:45 a.m.

Hi dada.venki,

I don't know what do you mean by "your password" but the IV (initialization vector) has to be 16 bytes long.. generate something random.

Reply · March 1, 2012, 2:56 p.m.

You are wrong. Failure was b/c initial value was not equal to the encryped after decryption - encrypted value contains spaces it it. After trimming encrypted value I got success.

Reply · March 3, 2012, 2:56 a.m.

hello thanks for your very helpful class :) but when i try to decrypt a string bufer a get this exeption :

Error converting result java.lang.Exception: [decrypt] unable to parse '

can you please help me to get the string bufer decrypted as well ??


Reply · March 28, 2012, 9:50 a.m.

Thanks, the code works perfectly well. the given code is for 128-bit AES encryption and decryption, but i want the same for 192-bit AES encryption and decryption. Can you please post the changes to be done.

Reply · March 31, 2012, 10:40 a.m.

Failure was b/c initial value was not equal to the encryped after decryption - encrypted value contains spaces it it. After trimming encrypted value I got success.

Reply · May 21, 2012, 12:14 p.m.

Hello! Great info you have here! Just one question, do this classes have any license? GPL or something?

Reply · Aug. 20, 2012, 11:41 p.m.

I think it fits better under CC Attribution license


Reply · Aug. 22, 2012, 10:02 a.m.

You can fork the project in GitHub https://github.com/SeRPRo/Android-PHP-Encrypt-Decrypt

Reply · Sept. 11, 2012, 12:33 p.m.

I'm having the same error others are reporting.

PHP returns: cb4b4ca864213684070465b38783a6c8 Android encrypted returns: 9975e28df055c336a9b7090b03f88689 Android decrypted returns: "Text to Encrypt "

I tried changing char paddingChar = ' '; to this char paddingChar = 0; still didn't help.

So I know the problem is with the padding, but I'm not sure how to fix it.

Also I'm not sure why I'm getting: 9975e28df055c336a9b7090b03f88689 And the other person got: beb4ce4c41a3c3445be48ad55906f5bc

Using the code originally posted without any changes.

Reply · Aug. 23, 2012, 9:14 p.m.

I'm not able to edit the original post, but I think in one of the comments, one user had the same issue and we finally got it working. Have you tried that solution? (Is the comment with loads of replies)

Reply · Aug. 24, 2012, 10:33 a.m.

Yea I read it. I actually found out the problem it wasn't that...

JAVA CODE: String encrypted = MCrypt.bytesToHex( mcrypt.encrypt("Text to Encrypt") );

PHP CODE: $encrypted = $mcrypt->encrypt("Text to encrypt");

You accidentally change "Encrypt" to "encrypt" in the php version, so I never got the correct code to come through even when I fixed the padding problem. In the end I transitioned to AES/CBC/PKCS5Padding to avoid the padding differences between Java and PHP. PHP doens't support PKCS5Padding so I had to find a custom workaround.

For those of you that want to use PKCS5Padding do the following:

IN JAVA (MCrypt Class): CHANGE: cipher = Cipher.getInstance("AES/CBC/NoPadding"); TO: cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

CHANGE: encrypted = cipher.doFinal(padString(text).getBytes()); TO: encrypted = cipher.doFinal(text.getBytes("UTF-8"));

DELETE padString method (not used anymore)

IN JAVA (Main Class): CHANGE: String decrypted = new String( mcrypt.decrypt( encrypted ) ); TO: String decrypted = new String(MCrypt.decrypt(encrypted), "UTF-8");

IN PHP: Add the following functions to be used before you encrypt and after you decrypt: function pkcs5_pad ($text) { $blocksize = 16; $pad = $blocksize - (strlen($text) % $blocksize); echo($pad."
"); 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); }

ENCRYPT EX: $encrypted = $mcrypt->encrypt(pkcs5_pad("Text to Encrypt")); DECRYPT EX: $decrypted = pkcs5_unpad($mcrypt->decrypt($encrypted));

BTW Serpro I hope you don't feel bad that people are changing up your code so much. Honestly this is like the BEST and ONLY example of encrypting in Java and PHP. Honestly a great example.

Reply · Aug. 24, 2012, 2:26 p.m.

Reposted to look nicer...

**IN JAVA (MCrypt Class):**
**CHANGE:** cipher = Cipher.getInstance("AES/CBC/NoPadding");
**TO:** cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");

**CHANGE:** encrypted = cipher.doFinal(padString(text).getBytes());
**TO:** encrypted = cipher.doFinal(text.getBytes("UTF-8"));

**DELETE** padString method (not used anymore)

**IN JAVA (Main Class):**
**CHANGE:** String decrypted = new String( mcrypt.decrypt( encrypted ) );
**TO:** String decrypted = new String(MCrypt.decrypt(encrypted), "UTF-8");

**IN PHP:**
Add the following functions to be used before you encrypt and after you decrypt:

function pkcs5_pad ($text) {
    $blocksize = 16;
    $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);

**ENCRYPT EX:** $encrypted = $mcrypt->encrypt(pkcs5_pad("Text to Encrypt"));
**DECRYPT EX:** $decrypted = pkcs5_unpad($mcrypt->decrypt($encrypted));
Reply · Aug. 24, 2012, 2:39 p.m.

For some reason, i need to "double" the encrypt... i mean, i create a random alphanumeric on my mobile, encrypt it send it to a php php crypt it (with another secret pass, same IV), resend it to the mobile the mobile decrypt it and resend the code (this way, if someone is able to find the "phone" code, he can't define the internet code and vice-versa) But, my problem is when i try to decode the "double coded" string on the phone (step3...), i have an error message sent by "cipher" who tell me that the "pad block is corrupted"... I think the problem come from hexToBytes and the "base16" conversion, but i'm not sure and i don't know how to correct it....does anybody have any idea ?

Reply · Nov. 6, 2012, 9:30 p.m.

At the end, what is the code (java & php) fixed? (?? chars at end and pkcs5) thanks

Reply · Feb. 17, 2013, 3:42 p.m.

Hi, I can't edit the code here.. but you can find the project on my GitHub


Reply · Feb. 19, 2013, 3:06 p.m.

Encryption/decryption fails when using special characters.

Crypto failed: [encrypt] data not block size aligned

Any ideas how to fix it?

Reply · March 28, 2013, 9:31 p.m.

Hi Serpro, Thanks for shared such a nice code. I'm working on a project for my Final Assignment and need to encrypt the data before send it to the web (PHP). This is really help me. Thanks a lot Serpro. :)

Reply · April 12, 2013, 8:54 p.m.

Hi Antonius,

Thanks for your kind message. I'm glad this piece of code can help you. Because I can't edit anymore the code here I have a more recent version in GitHub https://github.com/SeRPRo/Android-PHP-Encrypt-Decrypt

Feel free to download it from there and let me know any issues.

Reply · April 29, 2013, 7:45 p.m.

Hi, I have tested this code but I hadn't the same value encrypted :( could you help me?

Reply · April 16, 2014, 3:59 p.m.