JDK-8075224 : IllegalBlockSizeException: Input length must be multiple of 16 when decrypting
  • Type: Bug
  • Component: security-libs
  • Sub-Component: javax.crypto
  • Affected Version: 8u31
  • Priority: P3
  • Status: Closed
  • Resolution: Incomplete
  • OS: windows_8
  • CPU: x86
  • Submitted: 2015-02-12
  • Updated: 2015-10-13
  • Resolved: 2015-04-08
Related Reports
Relates :  
Description
FULL PRODUCT VERSION :
java version "1.8.0_31"
Java(TM) SE Runtime Environment (build 1.8.0_31-b13)
Java HotSpot(TM) Client VM (build 25.31-b07, mixed mode, sharing)

ADDITIONAL OS VERSION INFORMATION :
Window 8.1

A DESCRIPTION OF THE PROBLEM :
While decryption on file using AES algorithm I am facing mentioned problem in JRE version 1.8.0_31 and 1.8.0_25.

It work well with Jre version 1.8.0_20.





REGRESSION.  Last worked in version 8u20

ADDITIONAL REGRESSION INFORMATION: 
java version "1.8.0_20"
Java(TM) SE Runtime Environment (build 1.8.0_20-b26)
Java HotSpot(TM) Client VM (build 25.20-b23, mixed mode, sharing)

STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
Execute attached code snap.

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
File should be decrypted successfully without any exception.
ACTUAL -
java.io.IOException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher



ERROR MESSAGES/STACK TRACES THAT OCCUR :
java.io.IOException: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
        at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:115)
        at javax.crypto.CipherInputStream.read(CipherInputStream.java:233)
        at sun.nio.cs.StreamDecoder.readBytes(Unknown Source)
        at sun.nio.cs.StreamDecoder.implRead(Unknown Source)
        at sun.nio.cs.StreamDecoder.read(Unknown Source)
        at java.io.InputStreamReader.read(Unknown Source)
        at java.io.BufferedReader.fill(Unknown Source)
        at java.io.BufferedReader.readLine(Unknown Source)
        at java.io.BufferedReader.readLine(Unknown Source)
        at yes.util.Decrypt.loadEncrypted(Decrypt.java:393)
        at yes.util.Decrypt.decrypt(Decrypt.java:63)
        at DecryptUtility.actionPerformed(DecryptUtility.java:522)
        at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
        at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
        at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
        at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
        at java.awt.Component.processMouseEvent(Unknown Source)
        at javax.swing.JComponent.processMouseEvent(Unknown Source)
        at java.awt.Component.processEvent(Unknown Source)
        at java.awt.Container.processEvent(Unknown Source)
        at java.awt.Component.dispatchEventImpl(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
        at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
        at java.awt.Container.dispatchEventImpl(Unknown Source)
        at java.awt.Window.dispatchEventImpl(Unknown Source)
        at java.awt.Component.dispatchEvent(Unknown Source)
        at java.awt.EventQueue.dispatchEventImpl(Unknown Source)
        at java.awt.EventQueue.access$400(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.awt.EventQueue$3.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue$4.run(Unknown Source)
        at java.awt.EventQueue$4.run(Unknown Source)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.security.ProtectionDomain$1.doIntersectionPrivilege(Unknown Source)
        at java.awt.EventQueue.dispatchEvent(Unknown Source)
        at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
        at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
        at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: javax.crypto.IllegalBlockSizeException: Input length must be multiple of 16 when decrypting with padded cipher
        at com.sun.crypto.provider.CipherCore.doFinal(CipherCore.java:913)
        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:2004)
        at javax.crypto.CipherInputStream.getMoreData(CipherInputStream.java:112)
        ... 47 more


REPRODUCIBILITY :
This bug can be reproduced always.

---------- BEGIN SOURCE ----------
import java.io.*;
import java.security.Key;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.Provider;
import java.security.Security;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.security.spec.KeySpec;
import java.util.*;
import javax.crypto.*;
import javax.crypto.*;
import javax.crypto.spec.DESKeySpec;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.SecretKeySpec;



public class Decrypt{

public static void main(String[] args)
{

try {
			CipherInputStream ci;
			String TransactionLog="ABC.xml";
			String FEK="C9063155B07A542BD678B1E2969C1B775E47BFA9";
                        Cipher c =null;
                        SecretKeySpec secretKey=null;
                        InputStreamReader reader =null;
                        FileInputStream fis = null;
                        
                        fis=new FileInputStream(TransactionLog);
						
						/*Please do paste this data into file
							adP2rz4phDL01MmgPz/B+QoWvWr8UAwKcBNOVcDOvbHI1tIpIaW5a+Vyd8eK6K2WW2mjyhrhIGI9
							TeL552EnzKmOjefkCV8miv1yxUG+TfshXNVlaS5n4xHQ178cnsqyOylg0HoOGOIGBwE/HMEo1jlf
							l/+bRy7o8j5+ruDvqs4ztSnG/lj09dCIvkOSUS454adFtllpYATyWSQLBesNbqWrerDKH52GTBiR
							3OvXyYGAqdlah3iN4MQ56B8HtOZt3CD9y+v0lhYmVHeBrVZ0m5+b2EG12xDBCezy7JitALQP/175
							pt9+rbQLDBMJKvd7DKZs

						*/	
                        c = Cipher.getInstance("AES/CBC/PKCS5Padding" );
                        
                       
                        byte[] deskeydata = null;
			
                        deskeydata = Hex.fromString(FEK);
						byte[] newiv=new byte[99, 126, 11, -10, -128, -58, -122, -16, -48, -82, 40, 69, 52, -121, 121, 88];
                        IvParameterSpec ivspec = new IvParameterSpec(newiv);
                        deskeydata = Arrays.copyOf(deskeydata, 16);
                        secretKey = new SecretKeySpec(deskeydata, "AES");
                        c.init(2, secretKey, ivspec);
                        ci = new CipherInputStream(new Base64.InputStream(fis, Base64.DECODE), c);
                        reader = new InputStreamReader(ci, "UTF-8");
                
                      
			BufferedReader br = new BufferedReader(reader);
			String xmlString = "";
                        String xmlData = "";
			while ((xmlString=br.readLine()) != null) {

				xmlData += xmlString;
                              
			}
                        reader.close();
                        fis.close();
                        ci.close();
						br.close();
						System.out.println(" File is decrypted"+xmlData);
			                        
		} catch (Exception ex) {
			System.out.println(" File is Not decrypted in Exception");
			ex.printStackTrace();

		}
		
		}
		
}
---------- END SOURCE ----------

CUSTOMER SUBMITTED WORKAROUND :
I believe there must be some problem in cipherInputStream.java of JCE jar of JRE version 1.8.0_31 and 1.8.0_25.

As I replace JCE Jar of version 1.8.0_20 it works.


Comments
After 8u20, there was a change that throws BadPadding and IllegalBlockSize exceptions when a fully read stream does not contain the correctly encrypted message, in this case the whole message was not a multiple of 16 from the stream. The use of Base64 complicates the provided test, but when I run the base64 message through a base64 decoder, the data length is 243, which is not a multiple of 16. I have no reason to believe there is a bug with a length of 243. Previous suppression of these exceptions was incorrect because it did not alert the application of corrupted encrypt messages and that the whole message was not decrypted when the stream was fully read. The test appears to be using third party libraries and imports in the example code were stripped out. Use of Base64 and Hex fail to compile. Base64 might be coming from project PolyGlot. Hex, I do not know where. It would be simpler if the example program didn't use Base64 and could show this using the decoded text from the input file. The use of Readers also complicates the example code which is unnecessary I believe. An example using ByteArrayInputStream and CipherInputStream would be ideal. If the submitter still feels this is a bug, please explain why reading a truncated encrypted message and throwing away the last block is correct programming in your case. And why you wouldn't like to be notified of a decryption failure by an exception.
08-04-2015

The submitter is trying to initialize an array of byte values. Even after updating the provided test case (see attached), we get the compilation failures. I will check again with submitter if he could provide a contained program that will run with just the Java SE libraries. ------------------------------------------- >javac Decrypt.java Decrypt.java:50: error: cannot find symbol deskeydata = Hex.fromString(FEK); ^ symbol: variable Hex location: class Decrypt Decrypt.java:56: error: cannot find symbol ci = new CipherInputStream(new Base64.InputStream(fis, B ase64.DECODE), c); ^ symbol: class InputStream location: class Base64 Decrypt.java:56: error: cannot find symbol ci = new CipherInputStream(new Base64.InputStream(fis, B ase64.DECODE), c); ^ symbol: variable DECODE location: class Base64 3 errors --------------------------------------
12-03-2015

I'm not able to compile the attached source. This looks like a duplicate of JDK-8042281 which has a fix for JDK 9 b14. Written back to the customer to check for JDK 9 ea and 8u40 ea and respond back with the outcome. ------------------------------------------------------------------------------------------------------------------ On 2/27/2015 10:29 AM, .... wrote: > Hi ..., > > I'm not able to compile the test case provided by you. Meanwhile, can you also check if this issue is reproducible with JDK 8u40 ea and JDK 9 ea. You can download the required from: > https://jdk8.java.net/download.html > https://jdk9.java.net/download/ > > Please respond back with the outcome. > > Thank You, ------------------------------------------------------------------------------------------------------------------
27-02-2015