1
votes

I'm trying to encrypt/decrypt strings in python and java using AES, and encryption result is same in both. The encryption works fine, but when i try to decrypt the string in java it shows me this error ( javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher ). In python it works fine. What is the problem with java decryption ?

private static String toHexString(byte[] data) {        
    StringBuffer buf = new StringBuffer();
    for (int i = 0; i < data.length; ++i) {
        String s = Integer.toHexString(data[i] & 0XFF);
        buf.append((s.length() == 1) ? ("0" + s) : s);
    }
    return buf.toString();
}

public static String encrypt(String input, String key) {
    byte[] crypted = null;
    try {
        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        crypted = cipher.doFinal(input.getBytes());
        final String encryptedString = toHexString(Base64.encodeBase64(crypted));
        return encryptedString;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return "";
}




  public static String decrypt(String encrypted, String key)  {
         char[] ch= encrypted.toCharArray();
    try {

        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher2.init(Cipher.DECRYPT_MODE, skeySpec);

       byte[] h =Hex.decodeHex(ch);

     String de = new String(Base64.decodeBase64(cipher2.doFinal(Hex.decodeHex(ch))),"UTF-8");  

    return de; 
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return null;
}
1
You need to check that the byte length of the encrypted bytes are the same both after encryption and before decryption. The error is telling you that you are trying to decrypt a byte array whose length is not a multiple of sixteen. Something somewhere is either losing bytes or adding bytes. Sometimes string processing can add unwanted newlines and suchlike. Best to check the two byte arrays byte-by-byte to see where the differences are.rossum
Why are you using both base64 and hex encoding? I thought one would be enoughslipperyseal
1. How do you know "The encryption works fine" if you can not decrypt it? Just because there is not an error indication does not mean it worked correctly as expected. 2. An javax.crypto.IllegalBlockSizeException means the the data to be decrypted is not the correct size, it must be a multiple of 16-bytes. 3. Provide test key, data and encrypted data. 3. Best bet guess is there is an encoding mis-match, see point 3 above.zaph
Do not use ECB mode in new work and update legacy work ASAP, it is not secure, see ECB mode, scroll down to the Penguin. Instead use CBC mode with a random IV, just prefix the encrypted data with the IV for use in decryption, it does not need to be secret.zaph

1 Answers

1
votes

Simple, you should perform the base 64 decoding before decryption, not after.


Here is an example where the ciphertext is base 64 encoded. There is really no reason to perform base 64 and hex encoding, you can do either one of them, but using both doesn't make sense.

I used an alternative Base64 codec, you didn't specify which one you were using.

WARNING: do not copy below code, it is not secure; it only provides a direct answer to the question.

public static String encrypt(String input, String key) {
    byte[] crypted = null;
    try {
        SecretKeySpec skey = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher.init(Cipher.ENCRYPT_MODE, skey);
        crypted = cipher.doFinal(input.getBytes());
        final String encryptedString = Base64.toBase64String(crypted);
        return encryptedString;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return "";
}

public static String decrypt(String encrypted, String key) {
    // char[] ch= encrypted.toCharArray();
    try {

        SecretKeySpec skeySpec = new SecretKeySpec(key.getBytes(), "AES");
        Cipher cipher2 = Cipher.getInstance("AES/ECB/PKCS5Padding");
        cipher2.init(Cipher.DECRYPT_MODE, skeySpec);

        // byte[] h = Hex.decode(encrypted);

        String de = new String(cipher2.doFinal(Base64
                .decode(encrypted)), "UTF-8");

        return de;
    } catch (Exception e) {
        System.out.println(e.toString());
    }
    return null;
}

I presume this is for learning purposes as there are many issues with the code, e.g. using keys in strings, ECB mode encryption, etcetera.