javax.crypto.IllegalBlockSizeException: last block incomplete in decryption - Decrypting an encrypted AES String

lazypig picture lazypig · Nov 7, 2012 · Viewed 30.5k times · Source

I am trying to decrypt the string "~9?8?m???=?T?G" that I receive from a back-end server which uses OpenSSL to encrypt the String using AES-256-CBC. There is the code block:

public static String decryptText(String textToDecrypt) {
    try {

        byte[] base64TextToDecrypt = Base64.encodeBase64(textToDecrypt.getBytes("UTF-8"));

        byte[] guid = "fjakdsjkld;asfj".getBytes("UTF-8");

        byte[] iv = new byte[16];
        System.arraycopy(guid, 0, iv, 0, guid.length);
        IvParameterSpec ips = new IvParameterSpec(iv);

        byte[] secret = DECRYPTION_SECRET_HASH.getBytes("UTF-8");
        SecretKeySpec secretKey = new SecretKeySpec(secret, "AES");

        Cipher cipher = Cipher.getInstance("AES/CBC/PKCS5Padding");
        // decryption pass
        cipher.init(Cipher.DECRYPT_MODE, secretKey, ips);
        byte[] converted = cipher.doFinal(base64TextToDecrypt);
        System.out.println(new String(converted));

    } catch (Exception e) {
        e.printStackTrace();
        Log.e(TAG, "Decipher error for " + textToDecrypt, e);
    }
    return "";
}

Unfortunately, when I get to the

byte[] converted = cipher.doFinal(base64TextToDecrypt);

statement the following exception is thrown:

javax.crypto.IllegalBlockSizeException: last block incomplete in decryption

Any ideas?

Answer

Maarten Bodewes picture Maarten Bodewes · Nov 7, 2012

You should decode the string instead of encoding the platform specific representation of the string, right at the start of your method.

byte[] base64TextToDecrypt = Base64.decodeBase64(textToDecrypt);

or more precisely:

byte[] bytesToDecrypt = Base64(base64TextToDecrypt);

if you name your variables correctly.

In general, each time you (feel like you have to) use the String.getBytes(): byte[] method or the String(byte[]) constructor you are likely doing something wrong. You should first think about what you are trying to do, and specify a if you do need to use it.

In your case, the output in the converted variable is probably character-encoded. So you you could use the following fragment:

String plainText = new String(converted, StandardCharsets.UTF_8);
System.out.println(plainText);

instead of what you have now.