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
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).