Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher
Asked Answered
G

1

8

In my application I am encrypting and decrypting data using secretKey. For that I am using AES algorithm. But I am getting exception in decrypt, one value out of three already encrypted values using secret key.

Exception is:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher.

Below is my code:

Function to encyrpt value

public static String symmetricEncrypt(String text, String secretKey) {
    BASE64Decoder decoder = new BASE64Decoder();
    byte[] raw;
    String encryptedString;
    SecretKeySpec skeySpec;
    BASE64Encoder bASE64Encoder = new BASE64Encoder();
    byte[] encryptText = text.getBytes();
    Cipher cipher;
    try {
        raw = decoder.decodeBuffer(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
        encryptedString = bASE64Encoder.encode(cipher.doFinal(encryptText));
    } 
    catch (Exception e) {
        e.printStackTrace();
        return "Error";
    }
    return encryptedString;
}

Function to decrypt value

public static String symmetricDecrypt(String text, String secretKey) {
    BASE64Decoder decoder = new BASE64Decoder();
    BASE64Decoder base64Decoder = new BASE64Decoder();
    Cipher cipher;
    String encryptedString;
    byte[] encryptText = null;
    byte[] raw;
    SecretKeySpec skeySpec;
    try {
        raw = decoder.decodeBuffer(secretKey);
        skeySpec = new SecretKeySpec(raw, "AES");
        encryptText = base64Decoder.decodeBuffer(text);
        cipher = Cipher.getInstance("AES");
        cipher.init(Cipher.DECRYPT_MODE, skeySpec);
        encryptedString = new String(cipher.doFinal(encryptText));
    } catch (Exception e) {
        e.printStackTrace();
        return "Error";
    }
    return encryptedString;
}

Following are the values that I am encrypting and decrypting

String secretKey = "XMzDdG4D03CKm2IxIWQw7g==";
String value1= "ABCD";
String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA==";
String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4=";
String value4= "20000";

/**  Ecnryption and decryption of value1 **/
String encryptedValue1= symmetricEncrypt(value1, secretKey);
String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey);

/**  Decryption of  enctypedValue1 **/
String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey);
System.out.println(decryptedValue2);

/**  Decryption of  enctypedValue2 (Not decrypted)**/
String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey);
System.out.println(decryptedValue3);

/**  Ecnryption and decryption of value4 **/
String encryptedValue4= symmetricEncrypt(value4, secretKey);
String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey);

In the test function, I have written the following three test cases.

  1. A new value (value1) being encrypted and decrypted using a secret key.
  2. Two example encrypted values (enctypedValue1, enctypedValue2) which are being decrypted using same secret key. encryptedValue2 which got a problem while decrypting using same secret key.
  3. A new value (value4) being encrypted and decrypted using a secret key.

On decrypting encryptedValue2 I am getting the following exception:

Illegal Block Size Exception Input length must be multiple of 16 when decrypting with padded cipher

Following is what I have derived till now.

  1. The problematic value seems to have a problem while decoding it, it returns 81 length array which is unable to get decrypted?

  2. If this problem was to happen it should have happened to all the values.

  3. Is this a value specific problem or it is something related to padding or it can have a different behavior on different browser, different os?

Gabe answered 10/7, 2013 at 10:13 Comment(5)
in your decrypt method, you used cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); However, in your encrypt method, you used cipher = Cipher.getInstance("AES");. They need to be the same. Add padding to cipher in encrypt method.Fidelis
This link might be helpful :#7640963Plastered
@Fidelis thanks for the correction. Actually it's writing mistake. Please see the edited question.Asymptote
@Fidelis is it require to add padding in SecretKeySpec or while generating secret key?Gabe
It is not required by itself. However in real world, block cipher algorithms are not used immediately alone for transmitting data. They are used in several modes such as CBC mode which is used in SSL. Here is a good read about padding: en.wikipedia.org/wiki/Padding_%28cryptography%29 Also, I highly recommend reading about block cipher encryption algorithms (AES is a block cipher algorithm): en.wikipedia.org/wiki/Block_cipherFidelis
F
12

I was able to run the code without any problem. However, I used Apache's Base64 for encoding/decoding...maybe your Base64 has bugs. If you wrote it yourself, there is a big chance that you missed some cases. For real production code, use heavily tested libraries such as Apache's.

You can find the library that I used for Base64 here: http://commons.apache.org/proper/commons-codec/download_codec.cgi

Here is the full working code:

    package security.symmatric;

    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;

    import org.apache.commons.codec.binary.Base64;

    public class AES {
        public static String symmetricEncrypt(String text, String secretKey) {
            byte[] raw;
            String encryptedString;
            SecretKeySpec skeySpec;
            byte[] encryptText = text.getBytes();
            Cipher cipher;
            try {
                raw = Base64.decodeBase64(secretKey);
                skeySpec = new SecretKeySpec(raw, "AES");
                cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.ENCRYPT_MODE, skeySpec);
                encryptedString = Base64.encodeBase64String(cipher.doFinal(encryptText));
            } 
            catch (Exception e) {
                e.printStackTrace();
                return "Error";
            }
            return encryptedString;
        }

        public static String symmetricDecrypt(String text, String secretKey) {
            Cipher cipher;
            String encryptedString;
            byte[] encryptText = null;
            byte[] raw;
            SecretKeySpec skeySpec;
            try {
                raw = Base64.decodeBase64(secretKey);
                skeySpec = new SecretKeySpec(raw, "AES");
                encryptText = Base64.decodeBase64(text);
                cipher = Cipher.getInstance("AES");
                cipher.init(Cipher.DECRYPT_MODE, skeySpec);
                encryptedString = new String(cipher.doFinal(encryptText));
            } catch (Exception e) {
                e.printStackTrace();
                return "Error";
            }
            return encryptedString;
        }

        public static void main(String[] args) {
            String secretKey = "XMzDdG4D03CKm2IxIWQw7g==";
            String value1= "ABCD";
            String enctypedValue1= "3uweh4pzoVyH1uODQmVNJA==";
            String enctypedValue2= "37PTC20w4DMZYjG3f+GWepSvAbEJUccMXwS/lXilLav1qM/PrCTdontw5/82OdC1zzyhDEsFVRGo rV6gXAQcm+Zai15hliiUQ8l8KRMtUl4=";
            String value4= "20000";

            /**  Ecnryption and decryption of value1 **/
            String encryptedValue1= symmetricEncrypt(value1, secretKey);
            String decryptedValue1 = symmetricDecrypt(encryptedValue1, secretKey);
            System.out.println(decryptedValue1);

            /**  Decryption of  enctypedValue1 **/
            String decryptedValue2 = symmetricDecrypt(enctypedValue1, secretKey);
            System.out.println(decryptedValue2);

            /**  Decryption of  enctypedValue2 **/
            String decryptedValue3 = symmetricDecrypt(enctypedValue2, secretKey);
            System.out.println(decryptedValue3);

            /**  Ecnryption and decryption of value4 **/
            String encryptedValue4= symmetricEncrypt(value4, secretKey);
            String decryptedValue4 = symmetricDecrypt(encryptedValue4, secretKey);
            System.out.println(decryptedValue4);
        }
    }
Fidelis answered 11/7, 2013 at 7:47 Comment(4)
Thank you It worked. I am using sun's Base64. I wanted to ask that what is the difference between Apache's Base64 and Sun's Base64? Should I replace it with Apache's Base64 in my program?Gabe
Yes, I highly recommend using Apache's. Try to avoid using Sun's libraries at all costs. Why? because their libraries are made to be used internally at Sun only (not exposed as "public API"). Thus, they could change the API, break backward compatibility, and stop supporting an API at any point and without a notice. At least that what I understand...Fidelis
This code is working fine from main method ,but not when I wrote inside the applet class .Giving the invocation target exception.Any assistance ?Plastered
How do you generate the secret key?Anopheles

© 2022 - 2024 — McMap. All rights reserved.