-
Bug
-
Resolution: Duplicate
-
P3
-
None
-
7u71, 8u31
-
x86
-
windows_8
FULL PRODUCT VERSION :
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600]
A DESCRIPTION OF THE PROBLEM :
Closing a cipher input stream early before reading all content will throw a BadPaddingException when closing the stream. The encryption used is Blowfish.
REGRESSION. Last worked in version 7u67
ADDITIONAL REGRESSION INFORMATION:
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See attached sample.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The stream should not throw an exception on close unless all data has been read.
ACTUAL -
The stream throws a BadPaddingException when calling close on the cipher input stream.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded
at javax.crypto.CipherInputStream.close(CipherInputStream.java:321)
at test.TestBlowfish.main(TestBlowfish.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(BlowfishCipher.java:319)
at javax.crypto.Cipher.doFinal(Cipher.java:1970)
at javax.crypto.CipherInputStream.close(CipherInputStream.java:314)
... 6 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.util.Arrays;
public class TestBlowfish {
private static final boolean ENABLE_BUG = true;
public static void main(String[] args) throws Exception {
final byte[] original = new byte[64 * 1024];
for (int i = 0; i < original.length; i++) {
original[i] = (byte) i;
}
final byte ivBytes[] = new byte[]{8, 7, 6, 5, 4, 3, 2, 1};
final SecretKeySpec key = new SecretKeySpec("password".getBytes(), "Blowfish");
final IvParameterSpec iv = new IvParameterSpec(ivBytes);
final Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
try (OutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher)) {
cipherOutputStream.write(original);
cipherOutputStream.write(original);
}
final byte[] decrypt = new byte[64 * 1024];
cipher.init(Cipher.DECRYPT_MODE, key, iv);
try (InputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(outputStream.toByteArray()), cipher)) {
readAll(cipherInputStream, decrypt);
if (!Arrays.equals(original, decrypt)) {
throw new IllegalStateException("decrypt error");
}
if (!ENABLE_BUG) {
readAll(cipherInputStream, decrypt);
if (!Arrays.equals(original, decrypt)) {
throw new IllegalStateException("decrypt error");
}
}
}
}
private static void readAll(InputStream inputStream, byte[] buffer) throws IOException {
int read = 0;
while (read != buffer.length) {
read += inputStream.read(buffer, read, buffer.length - read);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The code must be changed to handle this case explicitly and this is impossible for any deployed application without updating it.
The BadPaddingException must be explicitly caught and ignored when calling close on a cipher input stream.
SUPPORT :
YES
java version "1.7.0_71"
Java(TM) SE Runtime Environment (build 1.7.0_71-b14)
Java HotSpot(TM) 64-Bit Server VM (build 24.71-b01, mixed mode)
ADDITIONAL OS VERSION INFORMATION :
Microsoft Windows [Version 6.3.9600]
A DESCRIPTION OF THE PROBLEM :
Closing a cipher input stream early before reading all content will throw a BadPaddingException when closing the stream. The encryption used is Blowfish.
REGRESSION. Last worked in version 7u67
ADDITIONAL REGRESSION INFORMATION:
java version "1.7.0_67"
Java(TM) SE Runtime Environment (build 1.7.0_67-b01)
Java HotSpot(TM) 64-Bit Server VM (build 24.65-b04, mixed mode)
STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
See attached sample.
EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The stream should not throw an exception on close unless all data has been read.
ACTUAL -
The stream throws a BadPaddingException when calling close on the cipher input stream.
ERROR MESSAGES/STACK TRACES THAT OCCUR :
Exception in thread "main" java.io.IOException: javax.crypto.BadPaddingException: Given final block not properly padded
at javax.crypto.CipherInputStream.close(CipherInputStream.java:321)
at test.TestBlowfish.main(TestBlowfish.java:45)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: javax.crypto.BadPaddingException: Given final block not properly padded
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:811)
at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:676)
at com.sun.crypto.provider.BlowfishCipher.engineDoFinal(BlowfishCipher.java:319)
at javax.crypto.Cipher.doFinal(Cipher.java:1970)
at javax.crypto.CipherInputStream.close(CipherInputStream.java:314)
... 6 more
REPRODUCIBILITY :
This bug can be reproduced always.
---------- BEGIN SOURCE ----------
package test;
import javax.crypto.Cipher;
import javax.crypto.CipherInputStream;
import javax.crypto.CipherOutputStream;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;
import java.io.*;
import java.util.Arrays;
public class TestBlowfish {
private static final boolean ENABLE_BUG = true;
public static void main(String[] args) throws Exception {
final byte[] original = new byte[64 * 1024];
for (int i = 0; i < original.length; i++) {
original[i] = (byte) i;
}
final byte ivBytes[] = new byte[]{8, 7, 6, 5, 4, 3, 2, 1};
final SecretKeySpec key = new SecretKeySpec("password".getBytes(), "Blowfish");
final IvParameterSpec iv = new IvParameterSpec(ivBytes);
final Cipher cipher = Cipher.getInstance("Blowfish/CBC/PKCS5Padding");
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
cipher.init(Cipher.ENCRYPT_MODE, key, iv);
try (OutputStream cipherOutputStream = new CipherOutputStream(outputStream, cipher)) {
cipherOutputStream.write(original);
cipherOutputStream.write(original);
}
final byte[] decrypt = new byte[64 * 1024];
cipher.init(Cipher.DECRYPT_MODE, key, iv);
try (InputStream cipherInputStream = new CipherInputStream(new ByteArrayInputStream(outputStream.toByteArray()), cipher)) {
readAll(cipherInputStream, decrypt);
if (!Arrays.equals(original, decrypt)) {
throw new IllegalStateException("decrypt error");
}
if (!ENABLE_BUG) {
readAll(cipherInputStream, decrypt);
if (!Arrays.equals(original, decrypt)) {
throw new IllegalStateException("decrypt error");
}
}
}
}
private static void readAll(InputStream inputStream, byte[] buffer) throws IOException {
int read = 0;
while (read != buffer.length) {
read += inputStream.read(buffer, read, buffer.length - read);
}
}
}
---------- END SOURCE ----------
CUSTOMER SUBMITTED WORKAROUND :
The code must be changed to handle this case explicitly and this is impossible for any deployed application without updating it.
The BadPaddingException must be explicitly caught and ignored when calling close on a cipher input stream.
SUPPORT :
YES
- duplicates
-
JDK-8064546 CipherInputStream throws BadPaddingException if stream is not fully read
-
- Closed
-