java.security.InvalidKeyException: Given final block not properly padded

JDK Bug System | Webbug Group | 8 months ago
tip
Click on the to mark the solution that helps you, Samebug will learn from it.
As a community member, you’ll be rewarded for you help.
  1. 0

    FULL PRODUCT VERSION : java version "1.8.0_102" Java(TM) SE Runtime Environment (build 1.8.0_102-b14) Java HotSpot(TM) 64-Bit Server VM (build 25.102-b14, mixed mode) ADDITIONAL OS VERSION INFORMATION : Microsoft Windows [Version 10.0.10586] A DESCRIPTION OF THE PROBLEM : Retrieving a serialized form of a javax.crypto.SealedObject (using JRE 1.8.0_74 or newer) that was previously sealed using PBEWithHmacSHA256AndAES_256 in JRE 1.8.0_66 (or earlier) will fail with java.security.InvalidKeyException: Given final block not properly padded My tests show that the sealing/unsealing cycle works fine when both are performed by a VM that lies in closed range [1.8.0_74, 1.8.0_102] or [1.8.20, 1.8.0_66] (the ranges that I could test). Hence, the breaking change must have been introduced by 1.8.0_74. I noted that other PBE algorithms look to be working fine across this point, for example, PBEWithHmacSH1AndAES_128 and PBEWithHmacSH256AndAES_128 had not issue when sealed with 1.8.0_60 and unsealed with 1.8.0_102. REGRESSION. Last worked in version 8u77 ADDITIONAL REGRESSION INFORMATION: java version "1.8.0_66" Java(TM) SE Runtime Environment (build 1.8.0_66-b18) Java HotSpot(TM) 64-Bit Server VM (build 25.66-b18, mixed mode) STEPS TO FOLLOW TO REPRODUCE THE PROBLEM : 1- Run the test case I've provided named "generateSealedObject()" to obtain the byte[] corresponding to the serialized form of the sealed object, which contains string "test data", using JDK 1.8.0_66 or older. 2- Using the byte array obtained from step 1, run test case named "unsealFailsAfter8u74()" using JDK 1.8.0_66 or older. Confirm that the test passes by retrieving the sealed data,without throwing any exception. 3- Repeat step 2 using JDK 1.8.0_74 or newer. Confirm that the test fails by generating the exception mentioned earlier, "java.security.InvalidKeyException: Given final block not properly padded". EXPECTED VERSUS ACTUAL BEHAVIOR : EXPECTED - The test in step 3 should've passed without throwing any exception ACTUAL - java.security.InvalidKeyException: Given final block not properly padded at javax.crypto.SealedObject.getObject(SealedObject.java:260) at bugs.JavaBugs.unsealFailsAfter8u74(JavaBugs.java:74) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:498) ERROR MESSAGES/STACK TRACES THAT OCCUR : java.security.InvalidKeyException: Given final block not properly padded at javax.crypto.SealedObject.getObject(SealedObject.java:260) at bugs.JavaBugs.unsealFailsAfter8u74(JavaBugs.java:74) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at java.lang.reflect.Method.invoke(Method.java:498) REPRODUCIBILITY : This bug can be reproduced always. ---------- BEGIN SOURCE ---------- package bugs; import static org.testng.Assert.assertEquals; import static org.testng.Assert.fail; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.security.InvalidAlgorithmParameterException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; import java.util.Arrays; import javax.crypto.Cipher; import javax.crypto.IllegalBlockSizeException; import javax.crypto.NoSuchPaddingException; import javax.crypto.SealedObject; import javax.crypto.SecretKey; import javax.crypto.SecretKeyFactory; import javax.crypto.spec.PBEKeySpec; import javax.crypto.spec.PBEParameterSpec; import org.testng.annotations.Test; import com.sun.xml.internal.messaging.saaj.util.ByteInputStream; public class JavaBugs { @Test public void generateSealedObject() throws NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeySpecException, InvalidKeyException, InvalidAlgorithmParameterException, IllegalBlockSizeException, IOException { String data = "test data"; byte[] salt = new byte[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16}; PBEKeySpec keySpec = new PBEKeySpec("test1234567890".toCharArray()); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256"); PBEParameterSpec paramSpec = new PBEParameterSpec(salt, 1024 * 16); SecretKey key = secretKeyFactory.generateSecret(keySpec); Cipher cipher = Cipher.getInstance("PBEWithHmacSHA256AndAES_256"); cipher.init(Cipher.ENCRYPT_MODE, key, paramSpec); SealedObject sealedObject = new SealedObject(data, cipher); try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) { oos.writeObject(sealedObject); oos.flush(); System.out.println(Arrays.toString(bos.toByteArray())); } } @Test public void unsealFailsAfter8u74() throws NoSuchAlgorithmException, InvalidKeySpecException, InvalidKeyException, IOException, ClassNotFoundException { PBEKeySpec keySpec = new PBEKeySpec("test1234567890".toCharArray()); SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("PBEWithHmacSHA256AndAES_256"); SecretKey key = secretKeyFactory.generateSecret(keySpec); SealedObject sealedObject; Object data; byte[] sealedObjectBytes = {-84, -19, 0, 5, 115, 114, 0, 25, 106, 97, 118, 97, 120, 46, 99, 114, 121, 112, 116, 111, 46, 83, 101, 97, 108, 101, 100, 79, 98, 106, 101, 99, 116, 62, 54, 61, -90, -61, -73, 84, 112, 2, 0, 4, 91, 0, 13, 101, 110, 99, 111, 100, 101, 100, 80, 97, 114, 97, 109, 115, 116, 0, 2, 91, 66, 91, 0, 16, 101, 110, 99, 114, 121, 112, 116, 101, 100, 67, 111, 110, 116, 101, 110, 116, 113, 0, 126, 0, 1, 76, 0, 9, 112, 97, 114, 97, 109, 115, 65, 108, 103, 116, 0, 18, 76, 106, 97, 118, 97, 47, 108, 97, 110, 103, 47, 83, 116, 114, 105, 110, 103, 59, 76, 0, 7, 115, 101, 97, 108, 65, 108, 103, 113, 0, 126, 0, 2, 120, 112, 117, 114, 0, 2, 91, 66, -84, -13, 23, -8, 6, 8, 84, -32, 2, 0, 0, 120, 112, 0, 0, 0, 100, 48, 98, 6, 9, 42, -122, 72, -122, -9, 13, 1, 5, 13, 48, 85, 48, 52, 6, 9, 42, -122, 72, -122, -9, 13, 1, 5, 12, 48, 39, 4, 16, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 2, 2, 64, 0, 2, 1, 32, 48, 12, 6, 8, 42, -122, 72, -122, -9, 13, 2, 9, 5, 0, 48, 29, 6, 9, 96, -122, 72, 1, 101, 3, 4, 1, 42, 4, 16, 41, -30, -122, 112, 112, 57, 35, 123, -30, 27, -30, 47, -9, -93, 56, -43, 117, 113, 0, 126, 0, 4, 0, 0, 0, 32, -101, 78, -93, 37, -12, -8, -54, -34, 103, 17, -14, -74, 63, -84, 82, -113, 1, 47, -29, 23, 45, -100, -109, -98, -39, 95, -62, 6, -11, 95, 16, 114, 116, 0, 27, 80, 66, 69, 87, 105, 116, 104, 72, 109, 97, 99, 83, 72, 65, 50, 53, 54, 65, 110, 100, 65, 69, 83, 95, 50, 53, 54, 116, 0, 27, 80, 66, 69, 87, 105, 116, 104, 72, 109, 97, 99, 83, 72, 65, 50, 53, 54, 65, 110, 100, 65, 69, 83, 95, 50, 53, 54}; try (ByteInputStream bis = new ByteInputStream(sealedObjectBytes, sealedObjectBytes.length); ObjectInputStream ois = new ObjectInputStream(bis)) { sealedObject = (SealedObject) ois.readObject(); } data = sealedObject.getObject(key); assertEquals(data, "test data"); } } ---------- END SOURCE ---------- CUSTOMER SUBMITTED WORKAROUND : Nothing.

    JDK Bug System | 8 months ago | Webbug Group
    java.security.InvalidKeyException: Given final block not properly padded

    Root Cause Analysis

    1. java.security.InvalidKeyException

      Given final block not properly padded

      at javax.crypto.SealedObject.getObject()
    2. Android Platform
      SealedObject.getObject
      1. javax.crypto.SealedObject.getObject(SealedObject.java:260)
      1 frame
    3. bugs
      JavaBugs.unsealFailsAfter8u74
      1. bugs.JavaBugs.unsealFailsAfter8u74(JavaBugs.java:74)
      1 frame
    4. Java RT
      Method.invoke
      1. sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
      2. java.lang.reflect.Method.invoke(Method.java:498)
      2 frames