0

I'm trying to create AES encryption/decryption methods, but I cant seem to get my original input without using AES/ECB/NoPadding. Now I am trying to use AES/CBC/PKCS7Padding. I have confirmed that reading and writing the byte to/from the file works fine. With PKCS7 padding I get a BadPaddingException from

cipher.doFinal(encrypted)

in the decrypt method. Without padding, no exceptions - however the output is scrambled. I've spent time going through other posts about this exact same issue but I cant seem to find a solution that fits my problem.

How do I unscramble that output?

protected boolean encrypt(String place, String encrypt) {
    try {

        // encrypt the text
        cipher.init(Cipher.ENCRYPT_MODE, aesKey);
        byte[] encrypted = cipher.doFinal(encrypt.getBytes());

        Context context = HomeViewActivity.hva.getApplicationContext();
        FileOutputStream writer = context.openFileOutput(file_name.get(place.toUpperCase()), Context.MODE_PRIVATE);
        writer.write(encrypted);
        writer.close();
        return true; //successfully wrote encrypted string to file
    }catch(Exception e) {
        e.printStackTrace();
    }
    return false;
}
protected String decrypt(String place){
    String decrypted = null;
    try{
        Context context = HomeViewActivity.hva.getApplicationContext();
        // decrypt the text
        cipher.init(Cipher.DECRYPT_MODE, aesKey);
        FileInputStream reader = context.openFileInput(file_name.get(place.toUpperCase()));
        byte[] encrypted = new byte[reader.available()];
        reader.read(encrypted);
        reader.close();
        decrypted= new String(cipher.doFinal(encrypted));
    }catch(FileNotFoundException e){return null;}
    catch(IllegalBlockSizeException |
            BadPaddingException |
            InvalidKeyException |
            NoSuchAlgorithmException |
            IOException |
            NoSuchPaddingException e){e.printStackTrace();}
    return decrypted;
}

Edit 1: Made the encrypted array read in from file the appropriate size

Edit 2: initialized key and cipher in constructor instead of each method

9
  • 1
    Why don't you use the same algorithm to decrypt than the one used to encrypt? Why do you only decrypt 16 bytes, and not the complete output of the encryption? Commented Feb 24, 2015 at 21:01
  • Like i said, i get an exception if I use padding in the decryption method. Also the array is 16 bytes because it is encrypted with a 128 bit key Commented Feb 24, 2015 at 22:34
  • 1
    To clarify: key size and block size are different. AES uses 128-bit blocks, and 128-, 192- or 256-bit keys. Padding ensures that the text is a multiple of the block size. Using NoPadding means that you are responsible for ensuring the input is the right size. In any case, it needs to be consistent on encrypt and decrypt (which isn't clear from the code posted). And, to @JBNizet's point, you should expect the cipher text (i.e., encrypted) to be more than 1 block. By only taking 16 bytes, you may be truncating the data. Commented Feb 25, 2015 at 4:31
  • 2
    You seem to be using a key that is transported as a string. If the string is binary you may lose data. Loosing data means a different key. A different key means that you get garbage plaintext (as AES CBC is not integrity protected). Garbage plaintext means that the padding is random as well, meaning that it will fail with BadPaddingException. Commented Feb 25, 2015 at 10:05
  • 1
    Reading this again I don't see any handling of the IV value. The IV value should be random and prefixed to the ciphertext, then removed and reused for decryption. ECB does not use an IV value. Commented Feb 28, 2015 at 2:17

1 Answer 1

1

The problem is that ECB doesn't use an IV and that CBC - and most other modes of operation do use an IV value. Java randomizes the IV value when it is not explicitly given, which means that the plaintext after decryption is not correct.

For AES CBC mode this means that the first 16 bytes of the plaintext - the initial block - contains random characters. As the blocks after the initial block contain the normal plaintext you won't get a BadPaddingException in the code.

The normal solution to this problem is to prefix the IV value to the ciphertext or write it to the underlying stream first. Needless to say you have to retrieve the IV during decryption and skip the IV value during decryption by altering the offset in a buffer or by advancing a stream (for files you may not want to copy the entire ciphertext).

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.