diff --git a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java index 98fa21230091b..9ac01ff8b0eb5 100644 --- a/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java +++ b/src/java.base/share/classes/com/sun/crypto/provider/PBEKey.java @@ -80,6 +80,9 @@ final class PBEKey implements SecretKey { public byte[] getEncoded() { try { + if (isDestroyed()) { + throw new IllegalStateException("Key is destroyed"); + } return key.clone(); } finally { // prevent this from being cleaned for the above block @@ -139,7 +142,6 @@ public boolean equals(Object obj) { /** * Clears the internal copy of the key. - * */ @Override public void destroy() { @@ -202,6 +204,9 @@ private void readObject(java.io.ObjectInputStream s) @java.io.Serial private Object writeReplace() throws java.io.ObjectStreamException { try { + if (isDestroyed()) { + throw new IllegalStateException("Key is destroyed"); + } return new KeyRep(KeyRep.Type.SECRET, getAlgorithm(), getFormat(), diff --git a/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java b/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java index d7163e4d24074..e560f14be5e0b 100644 --- a/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java +++ b/src/java.base/share/classes/javax/crypto/SecretKeyFactory.java @@ -372,9 +372,16 @@ public final SecretKey generateSecret(KeySpec keySpec) * key), or the given key cannot be dealt with * (e.g., the given key has an algorithm or format not supported by this * secret key factory). + * @exception IllegalStateException if the given key is already destroyed. */ public final KeySpec getKeySpec(SecretKey key, Class keySpec) throws InvalidKeySpecException { + if (key == null) { + throw new InvalidKeySpecException("Key is null"); + } + if (key.isDestroyed()) { + throw new IllegalStateException("Key is destroyed"); + } if (serviceIterator == null) { return spi.engineGetKeySpec(key, keySpec); } @@ -407,9 +414,16 @@ public final KeySpec getKeySpec(SecretKey key, Class keySpec) * * @exception InvalidKeyException if the given key cannot be processed * by this secret key factory. + * @exception IllegalStateException if the given key is already destroyed. */ public final SecretKey translateKey(SecretKey key) throws InvalidKeyException { + if (key == null) { + throw new InvalidKeyException("Key is null"); + } + if (key.isDestroyed()) { + throw new IllegalStateException("Key is destroyed"); + } if (serviceIterator == null) { return spi.engineTranslateKey(key); } diff --git a/test/jdk/com/sun/crypto/provider/KeyFactory/PBEKeyDestroyTest.java b/test/jdk/com/sun/crypto/provider/KeyFactory/PBEKeyDestroyTest.java index da266c147fb21..608cf4241d28d 100644 --- a/test/jdk/com/sun/crypto/provider/KeyFactory/PBEKeyDestroyTest.java +++ b/test/jdk/com/sun/crypto/provider/KeyFactory/PBEKeyDestroyTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2023, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,11 +23,17 @@ /* * @test - * @bug 8312306 + * @bug 8312306 8358451 * @summary Check the destroy()/isDestroyed() of the PBEKey impl from SunJCE * @library /test/lib * @run testng/othervm PBEKeyDestroyTest */ +import java.io.ByteArrayOutputStream; +import java.io.NotSerializableException; +import java.io.ObjectOutputStream; +import java.security.InvalidKeyException; +import java.security.spec.InvalidKeySpecException; +import java.util.Arrays; import javax.crypto.*; import javax.crypto.spec.*; import java.nio.charset.StandardCharsets; @@ -36,6 +42,16 @@ public class PBEKeyDestroyTest { + private static final Class ISE = + IllegalStateException.class; + + private static void printKeyInfo(SecretKey k, String name) { + System.out.println(name); + System.out.println("algo: " + k.getAlgorithm()); + System.out.println("format: " + k.getFormat()); + System.out.println("hashCode: " + k.hashCode()); + } + @Test public void test() throws Exception { PBEKeySpec keySpec = new PBEKeySpec("12345678".toCharArray(), @@ -47,18 +63,34 @@ public void test() throws Exception { SecretKey key1 = skf.generateSecret(keySpec); SecretKey key2 = skf.generateSecret(keySpec); - // should be equal + printKeyInfo(key1, "key1"); + + // both keys should be equal Assert.assertFalse(key1.isDestroyed()); Assert.assertFalse(key2.isDestroyed()); Assert.assertTrue(key1.equals(key2)); Assert.assertTrue(key2.equals(key1)); + Assert.assertTrue(key1.hashCode() == key2.hashCode()); // destroy key1 key1.destroy(); + + // make sure no exception when retrieving algo, format, hashCode + printKeyInfo(key1, "destroyed key1"); + Assert.assertTrue(key1.isDestroyed()); Assert.assertFalse(key1.equals(key2)); Assert.assertFalse(key2.equals(key1)); + Assert.assertThrows(ISE, () -> key1.getEncoded()); + + // serialization should fail + ObjectOutputStream oos = new ObjectOutputStream( + new ByteArrayOutputStream()); + Assert.assertThrows(ISE, () -> oos.writeObject(key1)); + Assert.assertThrows(ISE, () -> skf.translateKey(key1)); + Assert.assertThrows(ISE, () -> skf.getKeySpec(key1, PBEKeySpec.class)); + // also destroy key2 key2.destroy(); Assert.assertTrue(key2.isDestroyed()); diff --git a/test/jdk/javax/crypto/SecretKeyFactory/FailOverTest.java b/test/jdk/javax/crypto/SecretKeyFactory/FailOverTest.java index c850a8214a840..e3ed5d476b042 100644 --- a/test/jdk/javax/crypto/SecretKeyFactory/FailOverTest.java +++ b/test/jdk/javax/crypto/SecretKeyFactory/FailOverTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2006, 2007, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2006, 2025, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -23,13 +23,14 @@ /* * test - * @bug 6370923 + * @bug 6370923 8358451 * @summary SecretKeyFactory failover does not work * @author Brad R. Wetmore */ import java.security.*; import javax.crypto.*; +import javax.crypto.spec.SecretKeySpec; public class FailOverTest { @@ -41,7 +42,7 @@ public static void main(String args[]) throws Exception { Security.insertProviderAt(p2, 2); SecretKeyFactory skf = SecretKeyFactory.getInstance("DUMMY"); - skf.translateKey((SecretKey)null); + skf.translateKey(new SecretKeySpec("any".getBytes(), "DUMMY")); if (skf.getProvider() != p2) { throw new Exception("Should have gotten Provider 2");