4

I'd like to implement a simple encryption/decryption tool in java. Therefore I found a little tutorial on: http://www.codejava.net/coding/file-encryption-and-decryption-simple-example

I changed some lines of code, to guarantee the encryption of large files. Now I got the problem, that the decryption doen't work.

I got the following error message/exception:

Error encrypting/decrypting file
    at Algorithmus.Encryptor.doCrypto(Encryptor.java:71)
    at Algorithmus.Encryptor.decrypt(Encryptor.java:39)
    at GUI.MainWindow$encryptThread.run(MainWindow.java:838)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:966)
    at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:824)
    at com.sun.crypto.provider.AESCipher.engineDoFinal(AESCipher.java:436)
    at javax.crypto.Cipher.doFinal(Cipher.java:2165)
    at Algorithmus.Encryptor.doCrypto(Encryptor.java:60)
    ... 2 more

I tried to change the Transoformation parameter to AES/CBC/PKCS5Padding but that has no effect. Does anyone know, how to optimize the given code?

        private static final String ALGORITHM = "AES";

        private static final String TRANSFORMATION = "AES";

        public static  void encrypt(String key, File inputFile, File outputFile)
                throws ExtendedException {
            doCrypto(Cipher.ENCRYPT_MODE, key, inputFile, outputFile);
        }

        public static  void decrypt(String key, File inputFile, File outputFile)
                throws ExtendedException {
            doCrypto(Cipher.DECRYPT_MODE, key, inputFile, outputFile);
        }

        private static void doCrypto(int cipherMode, String key, File inputFile,
                File outputFile) throws ExtendedException {
            try {
                Key secretKey = new SecretKeySpec(key.getBytes(), ALGORITHM);
                Cipher cipher = Cipher.getInstance(TRANSFORMATION);
                cipher.init(cipherMode, secretKey);

                FileInputStream inputStream = new FileInputStream(inputFile);


                CipherOutputStream out = new CipherOutputStream(new FileOutputStream(outputFile), cipher);
                byte[] buffer = new byte[8192];
                byte[] outputBytes = null;
                FileOutputStream outputStream = new FileOutputStream(outputFile);
                int count;
                while ((count = inputStream.read(buffer)) > 0)
                {
                    out.write(buffer, 0, count);
                    outputBytes = cipher.doFinal(buffer);

                }


                inputStream.close();
                outputStream.close();

            } catch (NoSuchPaddingException | NoSuchAlgorithmException
                    | InvalidKeyException | BadPaddingException
                    | IllegalBlockSizeException | IOException ex) {
                throw new ExtendedException("Error encrypting/decrypting file", ex);
            }
        }

1 Answer 1

3

Just use the CipherOutputStream. Do not invoke cipher.doFinal(buffer) and don't forget to close the output stream.

FileInputStream inputStream = new FileInputStream(inputFile);
FileOutputStream fileout = new FileOutputStream(outputFile);
CipherOutputStream out = new CipherOutputStream(fileout , cipher);

try {
    byte[] buffer = new byte[8192];
    int count;

    while ((count = inputStream.read(buffer)) > 0) {
        out.write(buffer, 0, count);
    }
} finally {
    out.close();
    inputStream.close();
}

The CipherOutputStream manages the cipher for you. It invokes doFinal when the stream will be closed and flushes the internal buffer.

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

2 Comments

Thanks a lot. It works perfectly! But if I type in the wrong passprase, no exception will be thrown. The decrypted file will be created, but it's not readable for humans
@jollepe AES/CBC encryption by itself does not provide authentication of the correct password, if you need that add a MAC of the encrypted data and use it for verification or use AES/GCM. Returning an error to the user for bad padding must be avoided or an attacker can exploit it in a padding oracle attack.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.