Skip to content

Commit 3571664

Browse files
author
Sergey Kuksenko
committed
8353478: Update crypto microbenchmarks to cover ML-DSA, ML-KEM, and HSS algorithms
Reviewed-by: ecaspole
1 parent ac41bc3 commit 3571664

File tree

10 files changed

+242
-1728
lines changed

10 files changed

+242
-1728
lines changed

test/micro/org/openjdk/bench/java/security/MLDSA.java

Lines changed: 0 additions & 830 deletions
This file was deleted.

test/micro/org/openjdk/bench/java/security/MLKEMBench.java

Lines changed: 0 additions & 835 deletions
This file was deleted.

test/micro/org/openjdk/bench/java/security/HSS.java renamed to test/micro/org/openjdk/bench/javax/crypto/full/HSSBench.java

Lines changed: 32 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,11 @@
2121
* questions.
2222
*/
2323

24-
package org.openjdk.bench.java.security;
24+
package org.openjdk.bench.javax.crypto.full;
2525

2626
import org.openjdk.jmh.annotations.Benchmark;
2727
import org.openjdk.jmh.annotations.BenchmarkMode;
2828
import org.openjdk.jmh.annotations.Fork;
29-
import org.openjdk.jmh.annotations.Level;
3029
import org.openjdk.jmh.annotations.Measurement;
3130
import org.openjdk.jmh.annotations.Mode;
3231
import org.openjdk.jmh.annotations.OutputTimeUnit;
@@ -35,29 +34,27 @@
3534
import org.openjdk.jmh.annotations.Setup;
3635
import org.openjdk.jmh.annotations.State;
3736
import org.openjdk.jmh.annotations.Warmup;
37+
import sun.security.util.RawKeySpec;
3838

39-
import java.io.IOException;
40-
import java.util.HexFormat;
41-
import java.security.ProviderException;
42-
import java.security.PublicKey;
43-
import java.security.Security;
44-
import java.security.Provider;
4539
import java.security.KeyFactory;
40+
import java.security.Security;
4641
import java.security.Signature;
42+
import java.util.HexFormat;
4743
import java.util.concurrent.TimeUnit;
4844

49-
import sun.security.util.RawKeySpec;
50-
5145
/**
5246
* Benchmark measuring HSS/LMS
5347
*/
54-
@BenchmarkMode(Mode.AverageTime)
55-
@OutputTimeUnit(TimeUnit.MICROSECONDS)
56-
@Warmup(iterations = 5, time = 1)
57-
@Measurement(iterations = 5, time = 1)
58-
@Fork(value = 3, jvmArgs = {"--add-exports", "java.base/sun.security.util=ALL-UNNAMED"})
48+
@Warmup(iterations = 3, time = 3)
49+
@Measurement(iterations = 8, time = 2)
50+
@Fork(value = 5, jvmArgs = {"-XX:+AlwaysPreTouch", "--add-exports", "java.base/sun.security.util=ALL-UNNAMED"})
51+
@OutputTimeUnit(TimeUnit.SECONDS)
52+
@State(Scope.Thread)
53+
@BenchmarkMode(Mode.Throughput)
54+
public class HSSBench {
5955

60-
public class HSS {
56+
@Param({"HSS/LMS"})
57+
private String algorithm; // do not change. Added for visibility
6158

6259
static byte[] decode(String s) {
6360
return HexFormat.of().parseHex(s
@@ -74,38 +71,28 @@ public static Signature getVerifier(byte[] pk) throws Exception {
7471
return vv;
7572
}
7673

77-
public static void verify(Signature v, byte[] pk, byte[] msg, byte[] sig)
74+
public static void verify(Signature v, byte[] msg, byte[] sig)
7875
throws Exception {
7976
v.update(msg);
8077
if (!v.verify(sig)) {
8178
throw new RuntimeException();
8279
}
8380
}
8481

85-
@State(Scope.Benchmark)
86-
public static class test01 {
87-
byte[] pk;
88-
byte[] msg;
89-
byte[] sig;
90-
91-
@Param({"Test 1"})
92-
private String test;
93-
94-
@Setup
95-
public void setup() throws Exception {
96-
pk = decode("""
82+
public static class TestData01 {
83+
static final byte[] pk = decode("""
9784
00000002
9885
00000005
9986
00000004
10087
0e975b10a6b33473d01baa138c155e81d7b7156b389b2a6a09d49f42c1ac4984
10188
2d977e65fceb6bc80e06eace38ce0116
10289
""");
103-
msg = decode("""
90+
static final byte[] msg = decode("""
10491
312e20546869732069732061207465737420666f72204853532f4c4d53207768
10592
6963682069732076657279206c6f6e6720616e64206e6f74206d65616e742074
10693
6f207265616420627920612068756d616e206265696e672e
10794
""");
108-
sig = decode("""
95+
static final byte[] sig = decode("""
10996
00000001
11097
00000005
11198
00000004
@@ -198,33 +185,22 @@ public void setup() throws Exception {
198185
85f294d491c47fb90d3ce9046d2f05da6a723ac342a32154d1c18b465b49308f
199186
41ca2f0475adf5ed46413766a6057bc810aeb6dd593691b84752b883c8a1a422
200187
""");
201-
}
202188
}
203189

204-
@State(Scope.Benchmark)
205-
public static class test02 {
206-
byte[] pk;
207-
byte[] msg;
208-
byte[] sig;
209-
210-
@Param({"Test 2"})
211-
private String test;
212-
213-
@Setup
214-
public void setup() throws Exception {
215-
pk = decode("""
190+
public static class TestData02 {
191+
static final byte[] pk = decode("""
216192
00000002
217193
00000006
218194
00000003
219195
ff466afe664c2581845b2c6af92aeb6e5c4dd15affc86c82ef4e807ad3c648a6
220196
4561666c975fd9cb150d6c7acd6e577f
221197
""");
222-
msg = decode("""
198+
static final byte[] msg = decode("""
223199
322e20546869732069732061207465737420666f72204853532f4c4d53207768
224200
6963682069732076657279206c6f6e6720616e64206e6f74206d65616e742074
225201
6f207265616420627920612068756d616e206265696e672e
226202
""");
227-
sig = decode("""
203+
static final byte[] sig = decode("""
228204
00000001
229205
00000003
230206
00000003
@@ -355,34 +331,33 @@ public void setup() throws Exception {
355331
b4a0bb3b72197d2d5b2111da8647be1675983e8ed1c0d8ec7cada282dc698656
356332
95f1e8806c7892b65fc17103ee3b5366b3fe31e57e653336be283962f488eaa5
357333
""");
358-
}
359334
}
360335

361336
@State(Scope.Thread)
362-
public static class verifier01 {
337+
public static class Verifier01 {
363338
Signature v;
364339

365340
@Setup
366-
public void setup(test01 test) throws Exception {
367-
v = getVerifier(test.pk);
341+
public void setup() throws Exception {
342+
v = getVerifier(TestData01.pk);
368343
}
369344
}
370345
@State(Scope.Thread)
371-
public static class verifier02 {
346+
public static class Verifier02 {
372347
Signature v;
373348

374349
@Setup
375-
public void setup(test02 test) throws Exception {
376-
v = getVerifier(test.pk);
350+
public void setup() throws Exception {
351+
v = getVerifier(TestData02.pk);
377352
}
378353
}
379354

380355
@Benchmark
381-
public void verify01(test01 test, verifier01 v) throws Exception {
382-
HSS.verify(v.v, test.pk, test.msg, test.sig);
356+
public void verify01(Verifier01 v) throws Exception {
357+
verify(v.v, TestData01.msg, TestData01.sig);
383358
}
384359
@Benchmark
385-
public void verify02(test02 test, verifier02 v) throws Exception {
386-
HSS.verify(v.v, test.pk, test.msg, test.sig);
360+
public void verify02(Verifier02 v) throws Exception {
361+
verify(v.v, TestData02.msg, TestData02.sig);
387362
}
388363
}
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package org.openjdk.bench.javax.crypto.full;
24+
25+
import org.openjdk.jmh.annotations.Benchmark;
26+
import org.openjdk.jmh.annotations.OperationsPerInvocation;
27+
import org.openjdk.jmh.annotations.Param;
28+
import org.openjdk.jmh.annotations.Setup;
29+
import org.openjdk.jmh.infra.Blackhole;
30+
31+
import javax.crypto.DecapsulateException;
32+
import javax.crypto.KEM;
33+
import java.security.InvalidKeyException;
34+
import java.security.KeyPair;
35+
import java.security.KeyPairGenerator;
36+
import java.security.NoSuchAlgorithmException;
37+
38+
public class KEMBench extends CryptoBase {
39+
40+
public static final int SET_SIZE = 128;
41+
42+
@Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024" })
43+
private String algorithm;
44+
45+
private KeyPair[] keys;
46+
private byte[][] messages;
47+
48+
private KEM kem;
49+
50+
@Setup
51+
public void setup() throws NoSuchAlgorithmException, InvalidKeyException {
52+
kem = (prov == null) ? KEM.getInstance(algorithm) : KEM.getInstance(algorithm, prov);
53+
KeyPairGenerator generator = (prov == null) ? KeyPairGenerator.getInstance(algorithm) : KeyPairGenerator.getInstance(algorithm, prov);
54+
keys = new KeyPair[SET_SIZE];
55+
for (int i = 0; i < keys.length; i++) {
56+
keys[i] = generator.generateKeyPair();
57+
}
58+
messages = new byte[SET_SIZE][];
59+
for (int i = 0; i < messages.length; i++) {
60+
KEM.Encapsulator enc = kem.newEncapsulator(keys[i].getPublic());
61+
KEM.Encapsulated encap = enc.encapsulate();
62+
messages[i] = encap.encapsulation();
63+
}
64+
}
65+
66+
@Benchmark
67+
@OperationsPerInvocation(SET_SIZE)
68+
public void encapsulate(Blackhole bh) throws InvalidKeyException {
69+
for (KeyPair kp : keys) {
70+
bh.consume(kem.newEncapsulator(kp.getPublic()).encapsulate().encapsulation());
71+
}
72+
}
73+
74+
@Benchmark
75+
@OperationsPerInvocation(SET_SIZE)
76+
public void decapsulate(Blackhole bh) throws InvalidKeyException, DecapsulateException {
77+
for (int i = 0; i < messages.length; i++) {
78+
bh.consume(kem.newDecapsulator(keys[i].getPrivate()).decapsulate(messages[i]));
79+
}
80+
}
81+
82+
}

test/micro/org/openjdk/bench/javax/crypto/full/KeyPairGeneratorBench.java

Lines changed: 23 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -45,7 +45,9 @@ public void setup() throws NoSuchAlgorithmException {
4545
setupProvider();
4646
generator = (prov == null) ? KeyPairGenerator.getInstance(algorithm)
4747
: KeyPairGenerator.getInstance(algorithm, prov);
48-
generator.initialize(keyLength);
48+
if (keyLength > 0) { // not all key pair generators allow the use of key length
49+
generator.initialize(keyLength);
50+
}
4951
}
5052

5153
@Benchmark
@@ -97,4 +99,23 @@ public static class XDH extends KeyPairGeneratorBench {
9799
@Param({"255", "448"})
98100
private int keyLength;
99101
}
102+
103+
public static class MLDSA extends KeyPairGeneratorBench {
104+
105+
@Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87" })
106+
private String algorithm;
107+
108+
@Param({"0"}) // ML-DSA key length is not supported
109+
private int keyLength;
110+
}
111+
112+
public static class MLKEM extends KeyPairGeneratorBench {
113+
114+
@Param({"ML-KEM-512", "ML-KEM-768", "ML-KEM-1024" })
115+
private String algorithm;
116+
117+
@Param({"0"}) // ML-KEM key length is not supported
118+
private int keyLength;
119+
}
120+
100121
}

test/micro/org/openjdk/bench/javax/crypto/full/SignatureBench.java

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2015, 2020, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2015, 2025, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* This code is free software; you can redistribute it and/or modify it
@@ -69,7 +69,9 @@ private String getKeyPairGeneratorName() {
6969
public void setup() throws NoSuchAlgorithmException, InvalidKeyException, SignatureException {
7070
setupProvider();
7171
KeyPairGenerator kpg = KeyPairGenerator.getInstance(getKeyPairGeneratorName());
72-
kpg.initialize(keyLength);
72+
if (keyLength > 0) { // not all key pair generators allow the use of key length
73+
kpg.initialize(keyLength);
74+
}
7375
KeyPair keys = kpg.generateKeyPair();
7476
this.privateKey = keys.getPrivate();
7577
this.publicKey = keys.getPublic();
@@ -136,4 +138,13 @@ public static class EdDSA extends SignatureBench {
136138

137139
}
138140

141+
public static class MLDSA extends SignatureBench {
142+
143+
@Param({"ML-DSA-44", "ML-DSA-65", "ML-DSA-87" })
144+
private String algorithm;
145+
146+
@Param({"0"}) // ML-DSA key length is not supported
147+
private int keyLength;
148+
}
149+
139150
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
/*
2+
* Copyright (c) 2025, Oracle and/or its affiliates. All rights reserved.
3+
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+
*
5+
* This code is free software; you can redistribute it and/or modify it
6+
* under the terms of the GNU General Public License version 2 only, as
7+
* published by the Free Software Foundation.
8+
*
9+
* This code is distributed in the hope that it will be useful, but WITHOUT
10+
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11+
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12+
* version 2 for more details (a copy is included in the LICENSE file that
13+
* accompanied this code).
14+
*
15+
* You should have received a copy of the GNU General Public License version
16+
* 2 along with this work; if not, write to the Free Software Foundation,
17+
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18+
*
19+
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20+
* or visit www.oracle.com if you need additional information or have any
21+
* questions.
22+
*/
23+
package org.openjdk.bench.javax.crypto.small;
24+
25+
public class HSSBench extends org.openjdk.bench.javax.crypto.full.HSSBench {
26+
27+
}

0 commit comments

Comments
 (0)