Karthik Sivam Karthik Sivam - 5 months ago 158
Android Question

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption

I'm working on a android project in which I have to decrypt string from a file in PHP server, encryption was done using PHP.(AES 128 algorithm)

Encryption Code:

function aes128Encrypt($key, $data) {
$key = md5($key);
return mcrypt_encrypt(MCRYPT_RIJNDAEL_128, $key, $data, MCRYPT_MODE_CBC, str_repeat("\0", 16));
}


My code for getting string from URL:

String myUri = "http://www.example.com/lib2.php";
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(myUri);

HttpResponse response = httpClient.execute(get);

String bodyHtml = "";
String xmlFile = "";
bodyHtml = EntityUtils.toString(response.getEntity());
System.out.println(bodyHtml);
xmlFile = decrypt(bodyHtml);
System.out.println(xmlFile);


decrypt() method:

public static String decrypt(String encData) throws Exception
{
Key key = generateKey();

Cipher c = Cipher.getInstance(algo + "/CBC/PKCS7Padding");

//Cipher c = Cipher.getInstance(algo);

IvParameterSpec ivSpec = new IvParameterSpec(ivbytes);

c.init(Cipher.DECRYPT_MODE, key , ivSpec);

//byte[] decValue = Base64.decode(encData , Base64.NO_PADDING);

//byte[] decFin = Base64.decode(decValue, Base64.NO_PADDING);

//byte[] decFinal = c.doFinal(decValue);

byte[] decFinal = c.doFinal(encData.getBytes());

String getAns = new String(decFinal, "UTF8");

return getAns;
}


In generateKey():

public static Key generateKey()
{

try {
MessageDigest digest = java.security.MessageDigest
.getInstance("MD5");

digest.update(myChar.getBytes());

key1 = digest.digest();

} catch (NoSuchAlgorithmException e) {
e.printStackTrace();
}



Key key = new SecretKeySpec(key1,algo);
return key;
}
}


The Logcat shows below exception:

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption


at the line
c.doFinal()


The Codes I'v commented out are also the codes I'v used to check. What is wrong with this code?. Any help will be appreciated.

Answer

The problem probably is the way you treat the value from the PHP server as a Java String. The PHP mcrypt_encrypt function returns a binary string, where each byte can have any value. PHP mcrypt_encrypt does not use any character encoding. So using EntityUtils.toString() is already an error - and using String.getBytes() without specifying the encoding generally is as well.

You just need to use either getContent() or writeTo(OutputStream outstream) to get the the binary ciphertext. If you opt for the first option, you can wrap a CipherInputStream around it. Initialize it with the "AES/CBC/NoPadding" cipher and you can directly decrypt the plain text string. Beware that you may have to trim a certain number of 00 valued bytes from the result to get to the plaintext.

Comments