3
votes

I'm trying to decrypt the encrypted string from server. But when I decrypt it I get follwoing error. I need to decrypt the string successfully . We are using AES 256 cbc

> java.lang.Exception: [decrypt] error:1e06b065:Cipher
> functions:EVP_DecryptFinal_ex:BAD_DECRYPT
11-18 12:32:12.976 14325-14325/aes.example.com.aes_encyrption_demo W/art: Before Android 4.1, method android.graphics.PorterDuffColorFilter android.support.graphics.drawable.VectorDrawableCompat.updateTintFilter(android.graphics.PorterDuffColorFilter, android.content.res.ColorStateList, android.graphics.PorterDuff$Mode) would have incorrectly overridden the package-private method in android.graphics.drawable.Drawable
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err: java.lang.Exception: [decrypt] error:1e06b065:Cipher functions:EVP_DecryptFinal_ex:BAD_DECRYPT
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at aes.example.com.aes_encyrption_demo.MCrypt.decrypt(MCrypt.java:73)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at aes.example.com.aes_encyrption_demo.MainActivity.onCreate(MainActivity.java:59)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.Activity.performCreate(Activity.java:6303)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1108)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2376)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2483)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.ActivityThread.access$900(ActivityThread.java:153)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1349)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.os.Handler.dispatchMessage(Handler.java:102)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.os.Looper.loop(Looper.java:148)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at android.app.ActivityThread.main(ActivityThread.java:5442)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at java.lang.reflect.Method.invoke(Native Method)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:738)
11-18 12:32:13.069 14325-14325/aes.example.com.aes_encyrption_demo W/System.err:     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:628)

When I use AES/CBC/NoPadding , I'm able to decrypt but the text is appended with junk characters .

Decrypted a:2:{s:5:"email";s:24:"[email protected]";s:8:"password";s:7:"Test123";}��

Actual String a:2:{s:5:"email";s:24:"[email protected]";s:8:"password";s:7:"Test123";}

Case 1: AES/CBC/PKCS5Padding : BAD_DECRYPT or BAD PADDING error

Case 2: AES/CBC/NoPadding : junk values at the end of decrypted text

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");
//            cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        } 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;
    }

Activity.java

try{
         decrypted = new String( mcrypt.decrypt( msg ) );
        }catch (Exception e){
            e.printStackTrace();
        }
        System.out.println("decrypted: " + decrypted);

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;
        }

}

I have already tried many links on stackoverflow.

Reference : http://www.androidsnippets.com/encrypt-decrypt-between-android-and-php.html

EDIT

The decryption fails with error when I use AES/CBC/PKCS5Padding , is this because the padding is not correctly applied by the server php code , or is it something at my end? How can this be resolved.

EDIT 2

FOUND the problem I tried with 16 byte key , but was getting a Bad padding exception, it was due to the fact the server side code did not implement PKCS7. After PKCS7 padding was implemented at server side , the issue was resolved. AES/CBC/PKCS5Padding mode will give bad padding exception if the padding is not added in encrypted string.

2
Padding is added at the end of your plaintext to extend t to the next block boundary. AES is a block cipher. Those junk characters at the end are the padding. Look at them, see what type of padding is being used and set your decryption method to expect that type of padding. For other errors look at what the error message is telling you.rossum
@Robert i don't get only junk value , i get correct text followed by junk valuesRachita Nanda
@rosum the decryption fails with error when I use AES/CBC/PKCS5Padding , is this because the padding is not correctly applied by the server php code , or is it something at my end?Rachita Nanda

2 Answers

2
votes

PHP uses non-deterministic zero-padding which can be removed by simply removing all zero valued bytes from the decrypted byte array. Of course that will also remove any zero byte values from the plaintext.


Notes:

  • AES-256 is used when your key size is 256 bits. Currently it is not, it will consist of 128 bits, so AES-128 is likely used;
  • You are currently using platform encoding for the strings in Java and well some kind of encoding for the strings in PHP, you should make sure that the encoding matches (never use new String(byte[]) or getBytes() without explicitly specifying the encoding);
  • keys consist of random bytes, not of characters;
  • CBC should not be used for transport mode encryption.

USE SSL/TLS INSTEAD

0
votes

Found the problem when I tried with 16 byte key also. I was getting a Bad padding exception, it was due to the fact the server side code did not implement PKCS7.

When I was using AES/CBC/NoPadding mode , there was no error , but the decrypted string contained junk value at the end. This was because padding was not added in the encrypted string.

After PKCS7 padding was implemented at server side , the issue was resolved. AES/CBC/PKCS5Padding mode will give bad padding exception if the padding is not added in encrypted string.

Refer https://gist.github.com/Halama/5956871 for implementing padding in php while encryption.