Decrypt an AES encoded message (encrypted in Python) in Java
Question: I want to decrypt an AES encrypted message in Java. I’ve been trying various
Algorithm/Mode/Padding options from the [standard
library](http://docs.oracle.com/javase/7/docs/api/javax/crypto/Cipher.html)
and from [BouncyCastle](http://www.bouncycastle.org/). No luck :-(

The encrypting entity is written in Python and is already in production.
Encrypted messages have already gone out, so I cannot easily change that part.
The Python code looks like this:

    
    
    from Crypto.Cipher import AES
    import base64
    import os
    import sys
    
    BLOCK_SIZE = 16
    PADDING = '\f'
    
    pad = lambda s: s + (BLOCK_SIZE - len(s) % BLOCK_SIZE) * PADDING
    
    EncodeAES = lambda c, s: base64.b64encode(c.encrypt(pad(s)))
    DecodeAES = lambda c, e: c.decrypt(base64.b64decode(e)).rstrip(PADDING)
    
    secret = 'XXXXXXXXXXXXXXXX'
    
    cipher = AES.new(secret)
    
    clear='test'
    encoded = EncodeAES(cipher, clear)
    
    print 'Encrypted string:>>{}<<'.format(encoded)
    
    decoded = DecodeAES(cipher, encoded)
    
    print 'Decrypted string:>>{}<<'.format(decoded)
    

Obviously AES is used, and I figured out that I have to use ECB mode. But I
have not found a padding mode that works on the Java side. If the input fits
within the block size and no padding is happening, I can decrypt the message
in Java. If the message needs to be padded, decryption fails.

The Java code to decrypt looks like this:

    
    
    public class AESPaddingTest {
    
        private enum Mode {
            CBC, ECB, CFB, OFB, PCBC
        };
    
        private enum Padding {
            NoPadding, PKCS5Padding, PKCS7Padding, ISO10126d2Padding, X932Padding, ISO7816d4Padding, ZeroBytePadding
        }
    
        private static final String ALGORITHM = "AES";
        private static final byte[] keyValue = new byte[] { 'X', 'X', 'X', 'X',
                'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X', 'X' };
    
        @BeforeClass
        public static void configBouncy() {
            Security.addProvider(new BouncyCastleProvider());
        }
    
        @Test
        public void testECBPKCS5Padding() throws Exception {
            decrypt("bEpi03epVkSBTFaXlNiHhw==", Mode.ECB,
                    Padding.PKCS5Padding);
        }
    
        private String decrypt(String valueToDec, Mode modeOption,
                Padding paddingOption) throws GeneralSecurityException {
            Key key = new SecretKeySpec(keyValue, ALGORITHM);
    
            Cipher c = Cipher.getInstance(ALGORITHM + "/" + modeOption.name() + "/" + paddingOption.name());
    
            c.init(Cipher.DECRYPT_MODE, key);
    
            byte[] decValue = c.doFinal(valueToDec.getBytes());
    
            String clear = new String(Base64.encodeBase64(decValue));
    
            return clear;
        }
    
    }
    

The error thrown is:

> javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16
> when decrypting with padded cipher

Any ideas?


Answer: thanks for the good question, answer and comments. I did minor changes to the
code and now it works like a charm for me.

    
    
    import java.security.GeneralSecurityException;
    import java.security.Key;
    import java.security.Security;
    
    import javax.crypto.Cipher;
    import javax.crypto.spec.SecretKeySpec;
    
    import android.util.Base64;
    
    public class AESTest {
    
        public enum Mode {
            CBC, ECB, CFB, OFB, PCBC
        };
    
        public enum Padding {
            NoPadding, PKCS5Padding, PKCS7Padding, ISO10126d2Padding, X932Padding, ISO7816d4Padding, ZeroBytePadding
        }
    
        private static final String ALGORITHM = "AES";
    
        private static final byte[] keyValue ="myKey".getBytes();
    
    
        String decrypt(String valueToDec, Mode modeOption,
                Padding paddingOption) throws GeneralSecurityException {
    
    
    
            byte[] decodeBase64 = Base64.decode(valueToDec.getBytes(),0);
    
            Key key = new SecretKeySpec(keyValue, ALGORITHM); 
            Cipher c = Cipher.getInstance("AES/ECB/NoPadding"); 
            c.init(Cipher.DECRYPT_MODE, key); 
            byte[] encValue = c.doFinal(decodeBase64); 
            return new String(encValue).trim();
    
        }
    
    }
    

Then, I used the class in my Android Activity as follows:

    
    
    AESTest aes=new AESTest();
    String decrypted = aes.decrypt(myCipheredText,Mode.ECB,Padding.NoPadding);
    

Note that the secret in python code and mykey in java code are tthe same.

