JDK-8242620 : Cannot serialize RSASSA-PSS keys with non-null params
  • Type: Bug
  • Component: security-libs
  • Sub-Component: java.security
  • Priority: P3
  • Status: Resolved
  • Resolution: Duplicate
  • Submitted: 2020-04-14
  • Updated: 2020-04-14
  • Resolved: 2020-04-14
Related Reports
Blocks :  
Duplicate :  
Relates :  
Description
The following program

        //CASE#4 Fails
        int dgLen = MessageDigest.getInstance(DIGEST).getDigestLength();
        int saltLength = K_SIZE / 8 - dgLen - 2;
        PSSParameterSpec params = new PSSParameterSpec(DIGEST, "MGF1", new MGF1ParameterSpec(DIGEST),
                saltLength, PSSParameterSpec.TRAILER_FIELD_BC);
        try {
            kpg.initialize(new RSAKeyGenParameterSpec(K_SIZE, RSAKeyGenParameterSpec.F4, params));
            KeyPair kp3 = kpg.generateKeyPair();
            testSerialize(kp3);
        } catch (Exception e) {
            pass = false;
            System.out.println("#######  CASE#4 FAILED  #########");
            e.printStackTrace(System.out);
        }
fails with an InvalidKeySpecException that is

java.io.NotSerializableException: java.security.Key: [PRIVATE] [RSASSA-PSS] [PKCS#8]
	at java.base/java.security.KeyRep.readResolve(KeyRep.java:185)
	at java.base/jdk.internal.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at java.base/java.io.ObjectStreamClass.invokeReadResolve(ObjectStreamClass.java:1291)
	at java.base/java.io.ObjectInputStream.readOrdinaryObject(ObjectInputStream.java:2200)
	at java.base/java.io.ObjectInputStream.readObject0(ObjectInputStream.java:1685)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:499)
	at java.base/java.io.ObjectInputStream.readObject(ObjectInputStream.java:457)
	at KeySerialization.deserialize(KeySerialization.java:225)
	at KeySerialization.deserializedCopy(KeySerialization.java:213)
	at KeySerialization.testSerialize(KeySerialization.java:189)
	at KeySerialization.test(KeySerialization.java:115)
	at KeySerialization.main(KeySerialization.java:95)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
	at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.base/java.lang.reflect.Method.invoke(Method.java:564)
	at com.sun.javatest.regtest.agent.MainWrapper$MainThread.run(MainWrapper.java:127)
	at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.security.spec.InvalidKeySpecException: java.security.InvalidKeyException: java.security.ProviderException: Unsupported algorithm 1.2.840.113549.1.1.10
	at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:251)
	at java.base/java.security.KeyFactory.generatePrivate(KeyFactory.java:390)
	at java.base/java.security.KeyRep.readResolve(KeyRep.java:176)
	... 19 more
Caused by: java.security.InvalidKeyException: java.security.ProviderException: Unsupported algorithm 1.2.840.113549.1.1.10
	at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.<init>(RSAPrivateCrtKeyImpl.java:138)
	at java.base/sun.security.rsa.RSAPrivateCrtKeyImpl.newKey(RSAPrivateCrtKeyImpl.java:82)
	at java.base/sun.security.rsa.RSAKeyFactory.generatePrivate(RSAKeyFactory.java:356)
	at java.base/sun.security.rsa.RSAKeyFactory.engineGeneratePrivate(RSAKeyFactory.java:247)
	... 21 more

Comments
Derialization failed due to the same cause as JDK-8242556, thus closing this one as duplicate.
14-04-2020

Sample Test to reproduce, import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; import java.math.BigInteger; import java.security.KeyFactory; import java.security.KeyPair; import java.security.KeyPairGenerator; import java.security.MessageDigest; import java.security.PrivateKey; import java.security.PublicKey; import java.security.interfaces.RSAPrivateKey; import java.security.interfaces.RSAPublicKey; import java.security.spec.AlgorithmParameterSpec; import java.security.spec.MGF1ParameterSpec; import java.security.spec.PKCS8EncodedKeySpec; import java.security.spec.PSSParameterSpec; import java.security.spec.RSAKeyGenParameterSpec; import java.security.spec.RSAPrivateKeySpec; import java.security.spec.RSAPublicKeySpec; import java.util.Arrays; import java.util.Base64; /* * @test * @bug 8242335 * @summary Test RSASSA-PSS keys * @run main Test */ public class Test { private static final int K_SIZE = 2048; private static final String DIGEST = "SHA-256"; public static void main(String[] args) throws Exception { KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSASSA-PSS", "SunRsaSign"); KeyFactory kf = KeyFactory.getInstance("RSASSA-PSS", "SunRsaSign"); boolean pass = true; // CASE#1 Pass try { kpg.initialize(K_SIZE); KeyPair kp = kpg.generateKeyPair(); testSerialize(new KeyPair(kf.generatePublic(kf.getKeySpec(kp.getPublic(), RSAPublicKeySpec.class)), kf.generatePrivate(kf.getKeySpec(kp.getPrivate(), RSAPrivateKeySpec.class)))); } catch (Exception e) { pass = false; System.out.println("####### CASE#1 FAILED #########"); e.printStackTrace(System.out); } // CASE#2 Pass try { kpg.initialize(K_SIZE); KeyPair kp1 = kpg.generateKeyPair(); testSerialize(new KeyPair(kf.generatePublic(new RSAPublicKeySpec( ((RSAPublicKey) kp1.getPublic()).getModulus(), ((RSAPublicKey) kp1.getPublic()).getPublicExponent())), kf.generatePrivate(new RSAPrivateKeySpec(((RSAPrivateKey) kp1.getPrivate()) .getModulus(), ((RSAPrivateKey) kp1.getPrivate()).getPrivateExponent())))); } catch (Exception e) { pass = false; System.out.println("####### CASE#2 FAILED #########"); e.printStackTrace(System.out); } // CASE#3 Pass try { kpg.initialize(K_SIZE); KeyPair kp2 = kpg.generateKeyPair(); testSerialize(new KeyPair((PublicKey)kf.translateKey(kp2.getPublic()), (PrivateKey)kf.translateKey(kp2.getPrivate()))); } catch (Exception e) { pass = false; System.out.println("####### CASE#3 FAILED #########"); e.printStackTrace(System.out); } //CASE#4 Fails int dgLen = MessageDigest.getInstance(DIGEST).getDigestLength(); int saltLength = K_SIZE / 8 - dgLen - 2; PSSParameterSpec params = new PSSParameterSpec(DIGEST, "MGF1", new MGF1ParameterSpec(DIGEST), saltLength, PSSParameterSpec.TRAILER_FIELD_BC); try { kpg.initialize(new RSAKeyGenParameterSpec(K_SIZE, RSAKeyGenParameterSpec.F4, params)); KeyPair kp3 = kpg.generateKeyPair(); testSerialize(kp3); } catch (Exception e) { pass = false; System.out.println("####### CASE#4 FAILED #########"); e.printStackTrace(System.out); } //Case#5 Fails try { Constructor<RSAKeyGenParameterSpec> c = RSAKeyGenParameterSpec.class.getConstructor(int.class, BigInteger.class, AlgorithmParameterSpec.class); kpg.initialize(c.newInstance(K_SIZE, RSAKeyGenParameterSpec.F4, params)); KeyPair kp4 = kpg.generateKeyPair(); testSerialize(kp4); } catch (Exception e) { pass = false; System.out.println("####### CASE#5 FAILED #########"); e.printStackTrace(System.out); } if(!pass) { throw new RuntimeException("Some case failed. Check log for more detail."); } } /** * Test serialization of KeyPair and Keys it holds. */ private static void testSerialize(KeyPair keyPair) throws Exception { // Verify Serialized PrivateKey instance. if (!keyPair.getPrivate().equals( deserializedCopy(keyPair.getPrivate(), PrivateKey.class))) { throw new RuntimeException("PrivateKey is not equal with PrivateKey" + " generated through Serialization"); } // Verify Serialized PublicKey instance. if (!keyPair.getPublic().equals( deserializedCopy(keyPair.getPublic(), PublicKey.class))) { throw new RuntimeException("PublicKey is not equal with PublicKey" + " generated through Serialization"); } // Verify Serialized KeyPair instance. KeyPair copy = deserializedCopy(keyPair, KeyPair.class); if (!keyPair.getPrivate().equals(copy.getPrivate())) { throw new RuntimeException("PrivateKey is not equal with PrivateKey" + " generated through Serialized KeyPair"); } if (!keyPair.getPublic().equals(copy.getPublic())) { throw new RuntimeException("PublicKey is not equal with PublicKey" + " generated through Serialized KeyPair"); } } private static <T extends Object> T deserializedCopy(T orig, Class<T> type) throws IOException, ClassNotFoundException { return deserialize(serialize(orig), type); } /** * Deserialize the Key object. */ private static <T extends Object> T deserialize(byte[] serialized, Class<T> type) throws IOException, ClassNotFoundException { T key = null; try (ByteArrayInputStream bis = new ByteArrayInputStream(serialized); ObjectInputStream ois = new ObjectInputStream(bis)) { key = (T) ois.readObject(); } return key; } /** * Serialize the given Key object. */ private static <T extends Object> byte[] serialize(T key) throws IOException { try (ByteArrayOutputStream bos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(bos)) { oos.writeObject(key); return bos.toByteArray(); } } }
14-04-2020