8353478: Update crypto microbenchmarks to cover ML-DSA, ML-KEM, and HSS algorithms

Reviewed-by: ecaspole
This commit is contained in:
Sergey Kuksenko 2025-04-23 17:03:37 +00:00
parent ac41bc31c9
commit 35716647b5
10 changed files with 245 additions and 1731 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -21,12 +21,11 @@
* questions.
*/
package org.openjdk.bench.java.security;
package org.openjdk.bench.javax.crypto.full;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Level;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
@ -35,29 +34,27 @@ import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Warmup;
import java.io.IOException;
import java.util.HexFormat;
import java.security.ProviderException;
import java.security.PublicKey;
import java.security.Security;
import java.security.Provider;
import java.security.KeyFactory;
import java.security.Signature;
import java.util.concurrent.TimeUnit;
import sun.security.util.RawKeySpec;
import java.security.KeyFactory;
import java.security.Security;
import java.security.Signature;
import java.util.HexFormat;
import java.util.concurrent.TimeUnit;
/**
* Benchmark measuring HSS/LMS
*/
@BenchmarkMode(Mode.AverageTime)
@OutputTimeUnit(TimeUnit.MICROSECONDS)
@Warmup(iterations = 5, time = 1)
@Measurement(iterations = 5, time = 1)
@Fork(value = 3, jvmArgs = {"--add-exports", "java.base/sun.security.util=ALL-UNNAMED"})
@Warmup(iterations = 3, time = 3)
@Measurement(iterations = 8, time = 2)
@Fork(value = 5, jvmArgs = {"-XX:+AlwaysPreTouch", "--add-exports", "java.base/sun.security.util=ALL-UNNAMED"})
@OutputTimeUnit(TimeUnit.SECONDS)
@State(Scope.Thread)
@BenchmarkMode(Mode.Throughput)
public class HSSBench {
public class HSS {
@Param({"HSS/LMS"})
private String algorithm; // do not change. Added for visibility
static byte[] decode(String s) {
return HexFormat.of().parseHex(s
@ -74,7 +71,7 @@ public class HSS {
return vv;
}
public static void verify(Signature v, byte[] pk, byte[] msg, byte[] sig)
public static void verify(Signature v, byte[] msg, byte[] sig)
throws Exception {
v.update(msg);
if (!v.verify(sig)) {
@ -82,30 +79,20 @@ public class HSS {
}
}
@State(Scope.Benchmark)
public static class test01 {
byte[] pk;
byte[] msg;
byte[] sig;
@Param({"Test 1"})
private String test;
@Setup
public void setup() throws Exception {
pk = decode("""
public static class TestData01 {
static final byte[] pk = decode("""
00000002
00000005
00000004
0e975b10a6b33473d01baa138c155e81d7b7156b389b2a6a09d49f42c1ac4984
2d977e65fceb6bc80e06eace38ce0116
""");
msg = decode("""
static final byte[] msg = decode("""
312e20546869732069732061207465737420666f72204853532f4c4d53207768
6963682069732076657279206c6f6e6720616e64206e6f74206d65616e742074
6f207265616420627920612068756d616e206265696e672e
""");
sig = decode("""
static final byte[] sig = decode("""
00000001
00000005
00000004
@ -198,33 +185,22 @@ public class HSS {
85f294d491c47fb90d3ce9046d2f05da6a723ac342a32154d1c18b465b49308f
41ca2f0475adf5ed46413766a6057bc810aeb6dd593691b84752b883c8a1a422
""");
}
}
@State(Scope.Benchmark)
public static class test02 {
byte[] pk;
byte[] msg;
byte[] sig;
@Param({"Test 2"})
private String test;
@Setup
public void setup() throws Exception {
pk = decode("""
public static class TestData02 {
static final byte[] pk = decode("""
00000002
00000006
00000003
ff466afe664c2581845b2c6af92aeb6e5c4dd15affc86c82ef4e807ad3c648a6
4561666c975fd9cb150d6c7acd6e577f
""");
msg = decode("""
static final byte[] msg = decode("""
322e20546869732069732061207465737420666f72204853532f4c4d53207768
6963682069732076657279206c6f6e6720616e64206e6f74206d65616e742074
6f207265616420627920612068756d616e206265696e672e
""");
sig = decode("""
static final byte[] sig = decode("""
00000001
00000003
00000003
@ -355,34 +331,33 @@ public class HSS {
b4a0bb3b72197d2d5b2111da8647be1675983e8ed1c0d8ec7cada282dc698656
95f1e8806c7892b65fc17103ee3b5366b3fe31e57e653336be283962f488eaa5
""");
}
}
@State(Scope.Thread)
public static class verifier01 {
public static class Verifier01 {
Signature v;
@Setup
public void setup(test01 test) throws Exception {
v = getVerifier(test.pk);
public void setup() throws Exception {
v = getVerifier(TestData01.pk);
}
}
@State(Scope.Thread)
public static class verifier02 {
public static class Verifier02 {
Signature v;
@Setup
public void setup(test02 test) throws Exception {
v = getVerifier(test.pk);
public void setup() throws Exception {
v = getVerifier(TestData02.pk);
}
}
@Benchmark
public void verify01(test01 test, verifier01 v) throws Exception {
HSS.verify(v.v, test.pk, test.msg, test.sig);
public void verify01(Verifier01 v) throws Exception {
verify(v.v, TestData01.msg, TestData01.sig);
}
@Benchmark
public void verify02(test02 test, verifier02 v) throws Exception {
HSS.verify(v.v, test.pk, test.msg, test.sig);
public void verify02(Verifier02 v) throws Exception {
verify(v.v, TestData02.msg, TestData02.sig);
}
}

View File

@ -0,0 +1,82 @@
/*
* 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.
*/
package org.openjdk.bench.javax.crypto.full;
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.OperationsPerInvocation;
import org.openjdk.jmh.annotations.Param;
import org.openjdk.jmh.annotations.Setup;
import org.openjdk.jmh.infra.Blackhole;
import javax.crypto.DecapsulateException;
import javax.crypto.KEM;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
public class KEMBench extends CryptoBase {
public static final int SET_SIZE = 128;
@Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024" })
private String algorithm;
private KeyPair[] keys;
private byte[][] messages;
private KEM kem;
@Setup
public void setup() throws NoSuchAlgorithmException, InvalidKeyException {
kem = (prov == null) ? KEM.getInstance(algorithm) : KEM.getInstance(algorithm, prov);
KeyPairGenerator generator = (prov == null) ? KeyPairGenerator.getInstance(algorithm) : KeyPairGenerator.getInstance(algorithm, prov);
keys = new KeyPair[SET_SIZE];
for (int i = 0; i < keys.length; i++) {
keys[i] = generator.generateKeyPair();
}
messages = new byte[SET_SIZE][];
for (int i = 0; i < messages.length; i++) {
KEM.Encapsulator enc = kem.newEncapsulator(keys[i].getPublic());
KEM.Encapsulated encap = enc.encapsulate();
messages[i] = encap.encapsulation();
}
}
@Benchmark
@OperationsPerInvocation(SET_SIZE)
public void encapsulate(Blackhole bh) throws InvalidKeyException {
for (KeyPair kp : keys) {
bh.consume(kem.newEncapsulator(kp.getPublic()).encapsulate().encapsulation());
}
}
@Benchmark
@OperationsPerInvocation(SET_SIZE)
public void decapsulate(Blackhole bh) throws InvalidKeyException, DecapsulateException {
for (int i = 0; i < messages.length; i++) {
bh.consume(kem.newDecapsulator(keys[i].getPrivate()).decapsulate(messages[i]));
}
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -45,7 +45,9 @@ public class KeyPairGeneratorBench extends CryptoBase {
setupProvider();
generator = (prov == null) ? KeyPairGenerator.getInstance(algorithm)
: KeyPairGenerator.getInstance(algorithm, prov);
generator.initialize(keyLength);
if (keyLength > 0) { // not all key pair generators allow the use of key length
generator.initialize(keyLength);
}
}
@Benchmark
@ -97,4 +99,23 @@ public class KeyPairGeneratorBench extends CryptoBase {
@Param({"255", "448"})
private int keyLength;
}
public static class MLDSA extends KeyPairGeneratorBench {
@Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87" })
private String algorithm;
@Param({"0"}) // ML-DSA key length is not supported
private int keyLength;
}
public static class MLKEM extends KeyPairGeneratorBench {
@Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024" })
private String algorithm;
@Param({"0"}) // ML-KEM key length is not supported
private int keyLength;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -69,7 +69,9 @@ public class SignatureBench extends CryptoBase {
public void setup() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
setupProvider();
KeyPairGenerator kpg = KeyPairGenerator.getInstance(getKeyPairGeneratorName());
kpg.initialize(keyLength);
if (keyLength > 0) { // not all key pair generators allow the use of key length
kpg.initialize(keyLength);
}
KeyPair keys = kpg.generateKeyPair();
this.privateKey = keys.getPrivate();
this.publicKey = keys.getPublic();
@ -136,4 +138,13 @@ public class SignatureBench extends CryptoBase {
}
public static class MLDSA extends SignatureBench {
@Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87" })
private String algorithm;
@Param({"0"}) // ML-DSA key length is not supported
private int keyLength;
}
}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
package org.openjdk.bench.javax.crypto.small;
public class HSSBench extends org.openjdk.bench.javax.crypto.full.HSSBench {
}

View File

@ -0,0 +1,32 @@
/*
* 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.
*/
package org.openjdk.bench.javax.crypto.small;
import org.openjdk.jmh.annotations.Param;
public class KEMBench extends org.openjdk.bench.javax.crypto.full.KEMBench {
@Param({"ML-KEM-768"})
private String algorithm;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -32,4 +32,22 @@ public class KeyPairGeneratorBench extends org.openjdk.bench.javax.crypto.full.K
@Param({"2048"})
private int keyLength;
public static class MLDSA extends KeyPairGeneratorBench {
@Param({"ML-DSA-65"})
private String algorithm;
@Param({"0"}) // ML_DSA key length is not supported
private int keyLength;
}
public static class MLKEM extends KeyPairGeneratorBench {
@Param({"ML-KEM-768"})
private String algorithm;
@Param({"0"}) // ML-KEM key length is not supported
private int keyLength;
}
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (c) 2015, 2018, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2015, 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
@ -52,4 +52,17 @@ public abstract class SignatureBench extends org.openjdk.bench.javax.crypto.full
}
public static class MLDSA extends SignatureBench {
@Param({"ML-DSA-65" })
private String algorithm;
@Param({"1024"})
int dataSize;
@Param({"0"}) // ML-DSA key length is not supported
private int keyLength;
}
}