Reputation: 4659
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:"afroj.alam@broc.com";s:8:"password";s:7:"Test123";}��
Actual String a:2:{s:5:"email";s:24:"afroj.alam@broc.com";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.
Upvotes: 3
Views: 2206
Reputation: 4659
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.
Upvotes: 0
Reputation: 94058
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:
new String(byte[])
or getBytes()
without explicitly specifying the encoding);USE SSL/TLS INSTEAD
Upvotes: 2