Java 7 & # 8594; Java 8: AES Throws an exception: "BadPaddingException: This final block is not inserted correctly" in conjunction with BufferedReader & ZipStreams

We instantiate the cipher with the following statement:

Cipher cipher = Cipher.getInstance("AES"); SecretKeySpec key = new SecretKeySpec(cipherKey, "AES"); 

This works in java 7 (1.7_45), but no longer works in Java 8 (1.8_25). We pass cipher to CipherInputStream and use streams to read / write data. The actual exception occurs during close .

EDIT:

A quick look at the JDK code shows that the BadPaddingException was thrown, and in 7 it was ignored:

JDK 7: CipherInputStream.close:

  try { this.cipher.doFinal(); } catch (BadPaddingException var2) { ; } catch (IllegalBlockSizeException var3) { ; } 

JDK 8: CipherInputStream.close:

 try { if(!this.done) { this.cipher.doFinal(); } } catch (IllegalBlockSizeException | BadPaddingException var2) { if(this.read) { throw new IOException(var2); } } 

The question is, how to avoid the BadPaddingException in the first place?

EDIT 2:

After some research and experimentation, we came to the following test program:

 public final class CipherSpike2 { private static final byte[] SECRET_KEY = new byte[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; public static void main(String[] args) throws NoSuchPaddingException, NoSuchAlgorithmException, InvalidKeyException, IOException { encryptDecrypt(511); encryptDecrypt(512); } private static void encryptDecrypt(int i) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, IOException { byte[] clearText = generateClearText(i); System.out.println("Clear text length: " + clearText.length); ByteArrayOutputStream bos = new ByteArrayOutputStream(); CipherOutputStream cos = new CipherOutputStream(bos, getCipher(Cipher.ENCRYPT_MODE)); cos.write(clearText); cos.close(); final byte[] content = bos.toByteArray(); System.out.println("written bytes: " + content.length); CipherInputStream inputStream = new CipherInputStream(new ByteArrayInputStream(content), getCipher(Cipher.DECRYPT_MODE)); inputStream.read(); inputStream.close(); } private static byte[] generateClearText(int size) { return new byte[size]; } private static Cipher getCipher(int encryptMode) throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException { Cipher cipher = Cipher.getInstance("AES/ECB/PKCS5Padding"); SecretKeySpec key = new SecretKeySpec(SECRET_KEY, "AES"); cipher.init(encryptMode, key); return cipher; } } 

First, the program writes 511 bytes, which results in 512-byte "file content." We read exactly one byte. CipherInputStream reads data in a 512-byte block, so every byte is read, and we can close the stream.

Next, we create the contents of 512 bytes. This is added before 528. If now we read only one byte, we have a few bytes left, and if we close the stream, it will now work with this exception.

Now this problem is especially problematic in combination with ZipStreams: the encrypted content is in the previous step, encrypted using ZipOutputStream and read using ZipInputStream. It seems that ZipInputStream does not consume as many bytes as was previously recorded.

It seems the only solution is to catch the BadPaddingException in close (). (?) From the point of view of the API, it seems strange to me that I cannot close the stream without exception, regardless of the number of bytes I 'read.

EDIT 3 Developed by ZipStream:

In our application, we read a bunch of encrypted text files. Thus, the constant for the flows looks like this:

 BufferedReader/Writer -> InputStreamReader/Writer -> ZipInputStream/Output -> CipherInputStream/Output -> Underlying File Stream 

We read the contents of the file with the "traditional" while loop (reader.readLine! = Null) until we reach EOF. After that, we try to close the file. But sometimes this leads to an exception in Java 8 - see above (-: It seems that ZipOutputStream writes more bytes and ZipInputStreams consumes, but I have not looked at the code yet.

+7
java java-8 encryption aes
source share
2 answers

Java 1.8 CipherInputStream throws a BadPaddingException if you do not consume the stream completely. This may be the case when using ZipInputStream , since there is no need to read the zip index at the end of the file to use zip in streaming mode.

I recommend wrapping CipherInputStream in an implementation of the InputStream faΓ§ade, which ignores BadPaddingException when delegating the close() method. Do not do this if authentication of the contents of the stream is required for your use case, of course, or if some kind of temporary oracle attack is possible. A.

+4
source share

It looks like you clicked https://bugs.openjdk.java.net/browse/JDK-8061619 . There was a good reason for changing the behavior (see http://blog.philippheckel.com/2014/03/01/cipherinputstream-for-aead-modes-is-broken-in-jdk7-gcm/ )

You must explicitly specify the add-on in the encryption instance (for example, AES/GCM/NoPadding , but check the suitability for your application. Incorrect filling is associated with a number of SSL attacks)

+5
source share

All Articles