From 494ef6cb8cff7f29a7346364e7620eebcec48d3b Mon Sep 17 00:00:00 2001 From: Weijun Wang Date: Thu, 1 May 2025 23:34:35 +0000 Subject: [PATCH] 8354305: SHAKE128 and SHAKE256 MessageDigest algorithms Reviewed-by: valeriep, mullan --- .../classes/sun/security/provider/SHA3.java | 21 ++++++- .../sun/security/provider/SunEntries.java | 6 +- .../classes/sun/security/util/KnownOIDs.java | 4 +- .../provider/MessageDigest/SHAKEhash.java | 58 +++++++++++++++++++ .../provider/MessageDigest/SHAKEsqueeze.java | 14 ++++- 5 files changed, 98 insertions(+), 5 deletions(-) create mode 100644 test/jdk/sun/security/provider/MessageDigest/SHAKEhash.java diff --git a/src/java.base/share/classes/sun/security/provider/SHA3.java b/src/java.base/share/classes/sun/security/provider/SHA3.java index 5f974bc6ea6..a096cac5f50 100644 --- a/src/java.base/share/classes/sun/security/provider/SHA3.java +++ b/src/java.base/share/classes/sun/security/provider/SHA3.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2016, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2016, 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 @@ -476,9 +476,28 @@ public abstract class SHA3 extends DigestBase { public void reset() { engineReset(); + // engineReset (final in DigestBase) skips implReset if there's + // no update. This works for MessageDigest, since digest() always + // resets. But for XOF, squeeze() may be called without update, + // and still modifies state. So we always call implReset here + // to ensure correct behavior. + implReset(); } } + public static final class SHAKE128Hash extends SHA3 { + public SHAKE128Hash() { + super("SHAKE128-256", 32, (byte) 0x1F, 32); + } + } + + public static final class SHAKE256Hash extends SHA3 { + public SHAKE256Hash() { + super("SHAKE256-512", 64, (byte) 0x1F, 64); + } + } + + /* * The SHAKE128 extendable output function. */ diff --git a/src/java.base/share/classes/sun/security/provider/SunEntries.java b/src/java.base/share/classes/sun/security/provider/SunEntries.java index 9f5e3447aeb..bfc702ec6a2 100644 --- a/src/java.base/share/classes/sun/security/provider/SunEntries.java +++ b/src/java.base/share/classes/sun/security/provider/SunEntries.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1996, 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 @@ -264,6 +264,10 @@ public final class SunEntries { "sun.security.provider.SHA3$SHA384", attrs); addWithAlias(p, "MessageDigest", "SHA3-512", "sun.security.provider.SHA3$SHA512", attrs); + addWithAlias(p, "MessageDigest", "SHAKE128-256", + "sun.security.provider.SHA3$SHAKE128Hash", attrs); + addWithAlias(p, "MessageDigest", "SHAKE256-512", + "sun.security.provider.SHA3$SHAKE256Hash", attrs); /* * Certificates diff --git a/src/java.base/share/classes/sun/security/util/KnownOIDs.java b/src/java.base/share/classes/sun/security/util/KnownOIDs.java index 223dddb7f61..9435a7a9d39 100644 --- a/src/java.base/share/classes/sun/security/util/KnownOIDs.java +++ b/src/java.base/share/classes/sun/security/util/KnownOIDs.java @@ -152,8 +152,8 @@ public enum KnownOIDs { SHA3_256("2.16.840.1.101.3.4.2.8", "SHA3-256"), SHA3_384("2.16.840.1.101.3.4.2.9", "SHA3-384"), SHA3_512("2.16.840.1.101.3.4.2.10", "SHA3-512"), - SHAKE128("2.16.840.1.101.3.4.2.11"), - SHAKE256("2.16.840.1.101.3.4.2.12"), + SHAKE128_256("2.16.840.1.101.3.4.2.11", "SHAKE128-256", "SHAKE128"), + SHAKE256_512("2.16.840.1.101.3.4.2.12", "SHAKE256-512", "SHAKE256"), HmacSHA3_224("2.16.840.1.101.3.4.2.13", "HmacSHA3-224"), HmacSHA3_256("2.16.840.1.101.3.4.2.14", "HmacSHA3-256"), HmacSHA3_384("2.16.840.1.101.3.4.2.15", "HmacSHA3-384"), diff --git a/test/jdk/sun/security/provider/MessageDigest/SHAKEhash.java b/test/jdk/sun/security/provider/MessageDigest/SHAKEhash.java new file mode 100644 index 00000000000..1f4cbbf034a --- /dev/null +++ b/test/jdk/sun/security/provider/MessageDigest/SHAKEhash.java @@ -0,0 +1,58 @@ +/* + * Copyright (c) 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 + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8354305 + * @summary Ensure SHAKE message digest algorithms behave the same + * as correspondent XOF of the same output size + * @library /test/lib + * @modules java.base/sun.security.provider + */ + +import jdk.test.lib.Asserts; +import jdk.test.lib.security.SeededSecureRandom; +import sun.security.provider.SHA3; + +import java.security.MessageDigest; + +public class SHAKEhash { + public static void main(String[] args) throws Exception { + var random = SeededSecureRandom.one(); + var s1 = new SHA3.SHAKE128(); + var m1 = MessageDigest.getInstance("SHAKE128-256"); // use standard name + var s2 = new SHA3.SHAKE256(); + var m2 = MessageDigest.getInstance("SHAKE256"); // use alias + for (var i = 0; i < 1_000_000; i++) { + var msg = random.nBytes(random.nextInt(100)); + s1.update(msg); + m1.update(msg); + Asserts.assertEqualsByteArray(s1.squeeze(32), m1.digest()); + s2.update(msg); + m2.update(msg); + Asserts.assertEqualsByteArray(s2.squeeze(64), m2.digest()); + s1.reset(); + s2.reset(); + } + } +} diff --git a/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java b/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java index 5cdcce00e35..30edb9dbf13 100644 --- a/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java +++ b/test/jdk/sun/security/provider/MessageDigest/SHAKEsqueeze.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2024, 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 @@ -38,6 +38,18 @@ import java.util.Arrays; public class SHAKEsqueeze { public static void main(String[] args) throws Exception { + resetFix(); + random(); + } + + static void resetFix() throws Exception { + var s = new SHA3.SHAKE256(); + var d1 = s.squeeze(10); + s.reset(); + Asserts.assertEqualsByteArray(d1, s.squeeze(10)); + } + + static void random() throws Exception { var r = SeededSecureRandom.one(); var atlast = 0; // Random test on SHAKE