1
2
3
4
5
6
7 package mldsa_test
8
9 import (
10 "bytes"
11 "crypto"
12 "crypto/fips140"
13 "crypto/internal/cryptotest"
14 . "crypto/mldsa"
15 "crypto/sha3"
16 "encoding/hex"
17 "flag"
18 "math/rand/v2"
19 "strings"
20 "testing"
21 )
22
23 var _ crypto.Signer = (*PrivateKey)(nil)
24
25 var sixtyMillionFlag = flag.Bool("60million", false, "run 60M-iterations accumulated test")
26
27
28
29
30
31
32
33
34
35
36 func TestAccumulated(t *testing.T) {
37 t.Run("ML-DSA-44/100", func(t *testing.T) {
38 testAccumulated(t, MLDSA44(), 100,
39 "d51148e1f9f4fa1a723a6cf42e25f2a99eb5c1b378b3d2dbbd561b1203beeae4")
40 })
41 t.Run("ML-DSA-65/100", func(t *testing.T) {
42 testAccumulated(t, MLDSA65(), 100,
43 "8358a1843220194417cadbc2651295cd8fc65125b5a5c1a239a16dc8b57ca199")
44 })
45 t.Run("ML-DSA-87/100", func(t *testing.T) {
46 testAccumulated(t, MLDSA87(), 100,
47 "8c3ad714777622b8f21ce31bb35f71394f23bc0fcf3c78ace5d608990f3b061b")
48 })
49 if !testing.Short() {
50 t.Run("ML-DSA-44/10k", func(t *testing.T) {
51 t.Parallel()
52 testAccumulated(t, MLDSA44(), 10000,
53 "e7fd21f6a59bcba60d65adc44404bb29a7c00e5d8d3ec06a732c00a306a7d143")
54 })
55 t.Run("ML-DSA-65/10k", func(t *testing.T) {
56 t.Parallel()
57 testAccumulated(t, MLDSA65(), 10000,
58 "5ff5e196f0b830c3b10a9eb5358e7c98a3a20136cb677f3ae3b90175c3ace329")
59 })
60 t.Run("ML-DSA-87/10k", func(t *testing.T) {
61 t.Parallel()
62 testAccumulated(t, MLDSA87(), 10000,
63 "80a8cf39317f7d0be0e24972c51ac152bd2a3e09bc0c32ce29dd82c4e7385e60")
64 })
65 }
66 if *sixtyMillionFlag {
67 t.Run("ML-DSA-44/60M", func(t *testing.T) {
68 t.Parallel()
69 testAccumulated(t, MLDSA44(), 60000000,
70 "080b48049257f5cd30dee17d6aa393d6c42fe52a29099df84a460ebaf4b02330")
71 })
72 t.Run("ML-DSA-65/60M", func(t *testing.T) {
73 t.Parallel()
74 testAccumulated(t, MLDSA65(), 60000000,
75 "0af0165db2b180f7a83dbecad1ccb758b9c2d834b7f801fc49dd572a9d4b1e83")
76 })
77 t.Run("ML-DSA-87/60M", func(t *testing.T) {
78 t.Parallel()
79 testAccumulated(t, MLDSA87(), 60000000,
80 "011166e9d5032c9bdc5c9bbb5dbb6c86df1c3d9bf3570b65ebae942dd9830057")
81 })
82 }
83 }
84
85 func testAccumulated(t *testing.T, params Parameters, n int, expected string) {
86 s := sha3.NewSHAKE128()
87 o := sha3.NewSHAKE128()
88 seed := make([]byte, PrivateKeySize)
89 msg := make([]byte, 0)
90
91 for i := 0; i < n; i++ {
92 s.Read(seed)
93 dk, err := NewPrivateKey(params, seed)
94 if err != nil {
95 t.Fatalf("NewPrivateKey: %v", err)
96 }
97 pk := dk.PublicKey().Bytes()
98 o.Write(pk)
99 sig, err := dk.SignDeterministic(msg, nil)
100 if err != nil {
101 t.Fatalf("SignDeterministic: %v", err)
102 }
103 o.Write(sig)
104 pub, err := NewPublicKey(params, pk)
105 if err != nil {
106 t.Fatalf("NewPublicKey: %v", err)
107 }
108 if *pub != *dk.PublicKey() {
109 t.Fatalf("public key mismatch")
110 }
111 if err := Verify(dk.PublicKey(), msg, sig, nil); err != nil {
112 t.Fatalf("Verify: %v", err)
113 }
114 }
115
116 sum := make([]byte, 32)
117 o.Read(sum)
118 got := hex.EncodeToString(sum)
119 if got != expected {
120 t.Errorf("got %s, expected %s", got, expected)
121 }
122 }
123
124 func testAllParameters(t *testing.T, f func(*testing.T, Parameters)) {
125 for _, params := range []Parameters{MLDSA44(), MLDSA65(), MLDSA87()} {
126 t.Run(params.String(), func(t *testing.T) {
127 f(t, params)
128 })
129 }
130 }
131
132 func TestGenerateKey(t *testing.T) {
133 testAllParameters(t, testGenerateKey)
134 }
135
136 func testGenerateKey(t *testing.T, params Parameters) {
137 k1, err := GenerateKey(params)
138 if err != nil {
139 t.Fatalf("GenerateKey: %v", err)
140 }
141 k2, err := GenerateKey(params)
142 if err != nil {
143 t.Fatalf("GenerateKey: %v", err)
144 }
145 if k1.Equal(k2) {
146 t.Errorf("two generated keys are equal")
147 }
148 k1x, err := NewPrivateKey(params, k1.Bytes())
149 if err != nil {
150 t.Fatalf("NewPrivateKey: %v", err)
151 }
152 if !k1.Equal(k1x) {
153 t.Errorf("generated key and re-parsed key are not equal")
154 }
155 }
156
157 func TestAllocations(t *testing.T) {
158
159
160
161
162
163
164
165
166
167
168
169 var expected float64 = 7
170 if fips140.Enabled() {
171
172 expected += 1
173 }
174 if fips140.Version() == "v1.26.0" {
175
176
177
178 expected += 3
179 }
180 cryptotest.SkipTestAllocations(t)
181 if allocs := testing.AllocsPerRun(100, func() {
182 k, err := GenerateKey(MLDSA44())
183 if err != nil {
184 t.Fatalf("GenerateKey: %v", err)
185 }
186 seed := k.Bytes()
187 kk, err := NewPrivateKey(MLDSA44(), seed)
188 if err != nil {
189 t.Fatalf("NewPrivateKey: %v", err)
190 }
191 if !k.Equal(kk) {
192 t.Fatalf("keys not equal")
193 }
194 pkBytes := k.PublicKey().Bytes()
195 pk, err := NewPublicKey(MLDSA44(), pkBytes)
196 if err != nil {
197 t.Fatalf("NewPublicKey: %v", err)
198 }
199 message := []byte("Hello, world!")
200 context := "test"
201 sig, err := k.Sign(nil, message, &Options{Context: context})
202 if err != nil {
203 t.Fatalf("Sign: %v", err)
204 }
205 if err := Verify(pk, message, sig, &Options{Context: context}); err != nil {
206 t.Fatalf("Verify: %v", err)
207 }
208 }); allocs > expected {
209 t.Errorf("expected %0.0f allocations, got %0.1f", expected, allocs)
210 }
211 }
212
213 func TestParametersIdentity(t *testing.T) {
214
215
216 if MLDSA44() != MLDSA44() || MLDSA65() != MLDSA65() || MLDSA87() != MLDSA87() {
217 t.Errorf("MLDSA*() returned different values across calls")
218 }
219 if MLDSA44() == MLDSA65() || MLDSA65() == MLDSA87() || MLDSA44() == MLDSA87() {
220 t.Errorf("distinct parameter sets compare equal")
221 }
222 }
223
224
225
226 func computeMu(pk, ctx, msg []byte) []byte {
227 tr := sha3.NewSHAKE256()
228 tr.Write(pk)
229 trOut := make([]byte, 64)
230 tr.Read(trOut)
231
232 h := sha3.NewSHAKE256()
233 h.Write(trOut)
234 h.Write([]byte{0x00, byte(len(ctx))})
235 h.Write(ctx)
236 h.Write(msg)
237 out := make([]byte, 64)
238 h.Read(out)
239 return out
240 }
241
242
243
244
245 type fakeSignerOpts struct{ h crypto.Hash }
246
247 func (f fakeSignerOpts) HashFunc() crypto.Hash { return f.h }
248
249 func TestSign(t *testing.T) {
250 testAllParameters(t, func(t *testing.T, params Parameters) {
251 sk, err := GenerateKey(params)
252 if err != nil {
253 t.Fatalf("GenerateKey: %v", err)
254 }
255 pk := sk.PublicKey()
256 msg := []byte("test message")
257
258
259
260 sig1, err := sk.Sign(nil, msg, nil)
261 if err != nil {
262 t.Fatalf("Sign(nil opts): %v", err)
263 }
264 if got := len(sig1); got != params.SignatureSize() {
265 t.Errorf("len(sig) = %d, want %d", got, params.SignatureSize())
266 }
267 if err := Verify(pk, msg, sig1, nil); err != nil {
268 t.Errorf("Verify of nil-opts signature with nil opts: %v", err)
269 }
270 if err := Verify(pk, msg, sig1, &Options{}); err != nil {
271 t.Errorf("Verify of nil-opts signature with empty Options: %v", err)
272 }
273
274 sig2, err := sk.Sign(nil, msg, &Options{})
275 if err != nil {
276 t.Fatalf("Sign(&Options{}): %v", err)
277 }
278 if err := Verify(pk, msg, sig2, nil); err != nil {
279 t.Errorf("Verify of empty-Options signature with nil opts: %v", err)
280 }
281
282
283
284 sig3, err := sk.Sign(nil, msg, fakeSignerOpts{h: 0})
285 if err != nil {
286 t.Fatalf("Sign(fakeSignerOpts{0}): %v", err)
287 }
288 if err := Verify(pk, msg, sig3, nil); err != nil {
289 t.Errorf("Verify of fake-opts signature: %v", err)
290 }
291
292
293 sig4, err := sk.Sign(nil, msg, crypto.Hash(0))
294 if err != nil {
295 t.Fatalf("Sign(crypto.Hash(0)): %v", err)
296 }
297 if err := Verify(pk, msg, sig4, nil); err != nil {
298 t.Errorf("Verify of Hash(0)-opts signature: %v", err)
299 }
300
301
302 if _, err := sk.Sign(nil, msg, crypto.SHA256); err == nil {
303 t.Errorf("Sign with crypto.SHA256 opts: want error, got nil")
304 }
305 if _, err := sk.SignDeterministic(msg, crypto.SHA256); err == nil {
306 t.Errorf("SignDeterministic with crypto.SHA256 opts: want error, got nil")
307 }
308
309
310 detA, err := sk.SignDeterministic(msg, nil)
311 if err != nil {
312 t.Fatalf("SignDeterministic(nil): %v", err)
313 }
314 detB, err := sk.SignDeterministic(msg, &Options{})
315 if err != nil {
316 t.Fatalf("SignDeterministic(&Options{}): %v", err)
317 }
318 if !bytes.Equal(detA, detB) {
319 t.Errorf("SignDeterministic with nil and &Options{} differ")
320 }
321
322
323
324 detCtx, err := sk.SignDeterministic(msg, &Options{Context: "ctx"})
325 if err != nil {
326 t.Fatalf("SignDeterministic(ctx): %v", err)
327 }
328 if string(detCtx) == string(detA) {
329 t.Errorf("SignDeterministic with empty and non-empty context match")
330 }
331 if err := Verify(pk, msg, detCtx, nil); err == nil {
332 t.Errorf("Verify of context signature with empty context: want error, got nil")
333 }
334 if err := Verify(pk, msg, detCtx, &Options{Context: "ctx"}); err != nil {
335 t.Errorf("Verify with matching context: %v", err)
336 }
337
338
339 longCtx := strings.Repeat("x", 256)
340 if _, err := sk.Sign(nil, msg, &Options{Context: longCtx}); err == nil {
341 t.Errorf("Sign with 256-byte context: want error, got nil")
342 }
343 if _, err := sk.SignDeterministic(msg, &Options{Context: longCtx}); err == nil {
344 t.Errorf("SignDeterministic with 256-byte context: want error, got nil")
345 }
346 if err := Verify(pk, msg, detA, &Options{Context: longCtx}); err == nil {
347 t.Errorf("Verify with 256-byte context: want error, got nil")
348 }
349
350
351 sigTampered := bytes.Clone(sig1)
352 sigTampered[len(sigTampered)/2] ^= 0x01
353 if err := Verify(pk, msg, sigTampered, nil); err == nil {
354 t.Errorf("Verify of tampered signature: want error, got nil")
355 }
356
357
358 msgTampered := bytes.Clone(msg)
359 msgTampered[0] ^= 0x01
360 if err := Verify(pk, msgTampered, sig1, nil); err == nil {
361 t.Errorf("Verify of modified message: want error, got nil")
362 }
363
364
365 skOther, err := GenerateKey(params)
366 if err != nil {
367 t.Fatalf("GenerateKey: %v", err)
368 }
369 sigOther, err := skOther.SignDeterministic(msg, nil)
370 if err != nil {
371 t.Fatalf("SignDeterministic: %v", err)
372 }
373 if err := Verify(pk, msg, sigOther, nil); err == nil {
374 t.Errorf("Verify of signature from a different key: want error, got nil")
375 }
376 })
377 }
378
379 func TestExternalMu(t *testing.T) {
380 testAllParameters(t, func(t *testing.T, params Parameters) {
381 sk, err := GenerateKey(params)
382 if err != nil {
383 t.Fatalf("GenerateKey: %v", err)
384 }
385 pk := sk.PublicKey()
386 pkBytes := pk.Bytes()
387 msg := []byte("hello mu")
388
389 for _, ctx := range []string{"", "ctx"} {
390 μ := computeMu(pkBytes, []byte(ctx), msg)
391 sig, err := sk.Sign(nil, μ, crypto.MLDSAMu)
392 if err != nil {
393 t.Fatalf("Sign(MLDSAMu, ctx=%q): %v", ctx, err)
394 }
395 if err := Verify(pk, msg, sig, &Options{Context: ctx}); err != nil {
396 t.Errorf("Verify of MLDSAMu signature, ctx=%q: %v", ctx, err)
397 }
398
399 detSig, err := sk.SignDeterministic(μ, crypto.MLDSAMu)
400 if err != nil {
401 t.Fatalf("SignDeterministic(MLDSAMu, ctx=%q): %v", ctx, err)
402 }
403 if err := Verify(pk, msg, detSig, &Options{Context: ctx}); err != nil {
404 t.Errorf("Verify of deterministic MLDSAMu signature, ctx=%q: %v", ctx, err)
405 }
406 detSig2, err := sk.SignDeterministic(μ, crypto.MLDSAMu)
407 if err != nil {
408 t.Fatalf("SignDeterministic(MLDSAMu) second call: %v", err)
409 }
410 if string(detSig) != string(detSig2) {
411 t.Errorf("SignDeterministic(MLDSAMu) is not deterministic")
412 }
413 }
414
415
416 μA := computeMu(pkBytes, []byte("a"), msg)
417 sigA, err := sk.Sign(nil, μA, crypto.MLDSAMu)
418 if err != nil {
419 t.Fatalf("Sign(MLDSAMu, ctx=a): %v", err)
420 }
421 if err := Verify(pk, msg, sigA, &Options{Context: "b"}); err == nil {
422 t.Errorf("Verify of MLDSAMu(ctx=a) signature with ctx=b: want error, got nil")
423 }
424
425
426 sigTampered := bytes.Clone(sigA)
427 sigTampered[len(sigTampered)/2] ^= 0x01
428 if err := Verify(pk, msg, sigTampered, &Options{Context: "a"}); err == nil {
429 t.Errorf("Verify of tampered MLDSAMu signature: want error, got nil")
430 }
431
432
433 if _, err := sk.Sign(nil, make([]byte, 32), crypto.MLDSAMu); err == nil {
434 t.Errorf("Sign(MLDSAMu) with 32-byte input: want error, got nil")
435 }
436 if _, err := sk.SignDeterministic(make([]byte, 32), crypto.MLDSAMu); err == nil {
437 t.Errorf("SignDeterministic(MLDSAMu) with 32-byte input: want error, got nil")
438 }
439 })
440 }
441
442 func TestPublicKey(t *testing.T) {
443 cases := []struct {
444 params Parameters
445 name string
446 pkSize int
447 sigSize int
448 }{
449 {MLDSA44(), "ML-DSA-44", MLDSA44PublicKeySize, MLDSA44SignatureSize},
450 {MLDSA65(), "ML-DSA-65", MLDSA65PublicKeySize, MLDSA65SignatureSize},
451 {MLDSA87(), "ML-DSA-87", MLDSA87PublicKeySize, MLDSA87SignatureSize},
452 }
453 for _, tc := range cases {
454 t.Run(tc.name, func(t *testing.T) {
455 if got := tc.params.String(); got != tc.name {
456 t.Errorf("Parameters.String() = %q, want %q", got, tc.name)
457 }
458 if got := tc.params.PublicKeySize(); got != tc.pkSize {
459 t.Errorf("Parameters.PublicKeySize() = %d, want %d", got, tc.pkSize)
460 }
461 if got := tc.params.SignatureSize(); got != tc.sigSize {
462 t.Errorf("Parameters.SignatureSize() = %d, want %d", got, tc.sigSize)
463 }
464
465 sk, err := GenerateKey(tc.params)
466 if err != nil {
467 t.Fatalf("GenerateKey: %v", err)
468 }
469 pk := sk.PublicKey()
470 if got := pk.Parameters(); got != tc.params {
471 t.Errorf("PublicKey.Parameters() = %v, want %v", got, tc.params)
472 }
473 if got := len(pk.Bytes()); got != tc.params.PublicKeySize() {
474 t.Errorf("len(PublicKey.Bytes()) = %d, want %d", got, tc.params.PublicKeySize())
475 }
476 if got := len(sk.Bytes()); got != PrivateKeySize {
477 t.Errorf("len(PrivateKey.Bytes()) = %d, want %d", got, PrivateKeySize)
478 }
479
480
481 anyPub := sk.Public()
482 pub2, ok := anyPub.(*PublicKey)
483 if !ok {
484 t.Fatalf("PrivateKey.Public() = %T, want *PublicKey", anyPub)
485 }
486 if !pk.Equal(pub2) {
487 t.Errorf("PrivateKey.Public() does not equal PublicKey()")
488 }
489
490
491 sk2, err := NewPrivateKey(tc.params, sk.Bytes())
492 if err != nil {
493 t.Fatalf("NewPrivateKey round-trip: %v", err)
494 }
495 if !sk.Equal(sk2) {
496 t.Errorf("PrivateKey round-trip not equal")
497 }
498 pk2, err := NewPublicKey(tc.params, pk.Bytes())
499 if err != nil {
500 t.Fatalf("NewPublicKey round-trip: %v", err)
501 }
502 if !pk.Equal(pk2) {
503 t.Errorf("PublicKey round-trip not equal")
504 }
505 })
506 }
507 }
508
509 func TestEqualWrongType(t *testing.T) {
510 sk, err := GenerateKey(MLDSA44())
511 if err != nil {
512 t.Fatalf("GenerateKey: %v", err)
513 }
514 if sk.Equal("not a key") {
515 t.Errorf("PrivateKey.Equal(string) = true, want false")
516 }
517 if sk.Equal((*PublicKey)(nil)) {
518 t.Errorf("PrivateKey.Equal(*PublicKey) = true, want false")
519 }
520 if sk.PublicKey().Equal("not a key") {
521 t.Errorf("PublicKey.Equal(string) = true, want false")
522 }
523 if sk.PublicKey().Equal((*PrivateKey)(nil)) {
524 t.Errorf("PublicKey.Equal(*PrivateKey) = true, want false")
525 }
526
527
528 sk2, err := GenerateKey(MLDSA44())
529 if err != nil {
530 t.Fatalf("GenerateKey: %v", err)
531 }
532 if sk.Equal(sk2) {
533 t.Errorf("two random PrivateKeys are Equal")
534 }
535 if sk.PublicKey().Equal(sk2.PublicKey()) {
536 t.Errorf("two random PublicKeys are Equal")
537 }
538 }
539
540 func TestInvalidParameters(t *testing.T) {
541 var zero Parameters
542 if _, err := GenerateKey(zero); err == nil {
543 t.Errorf("GenerateKey(zero Parameters): want error, got nil")
544 }
545 if _, err := NewPrivateKey(zero, make([]byte, PrivateKeySize)); err == nil {
546 t.Errorf("NewPrivateKey(zero Parameters): want error, got nil")
547 }
548 if _, err := NewPublicKey(zero, make([]byte, MLDSA44PublicKeySize)); err == nil {
549 t.Errorf("NewPublicKey(zero Parameters): want error, got nil")
550 }
551 }
552
553 func TestInvalidSize(t *testing.T) {
554 testAllParameters(t, func(t *testing.T, params Parameters) {
555 if _, err := NewPrivateKey(params, make([]byte, PrivateKeySize-1)); err == nil {
556 t.Errorf("NewPrivateKey with short seed: want error, got nil")
557 }
558 if _, err := NewPrivateKey(params, make([]byte, PrivateKeySize+1)); err == nil {
559 t.Errorf("NewPrivateKey with long seed: want error, got nil")
560 }
561 if _, err := NewPublicKey(params, make([]byte, params.PublicKeySize()-1)); err == nil {
562 t.Errorf("NewPublicKey with short encoding: want error, got nil")
563 }
564 if _, err := NewPublicKey(params, make([]byte, params.PublicKeySize()+1)); err == nil {
565 t.Errorf("NewPublicKey with long encoding: want error, got nil")
566 }
567
568 sk, err := GenerateKey(params)
569 if err != nil {
570 t.Fatalf("GenerateKey: %v", err)
571 }
572 msg := []byte("test message")
573 sig, err := sk.SignDeterministic(msg, nil)
574 if err != nil {
575 t.Fatalf("SignDeterministic: %v", err)
576 }
577 if err := Verify(sk.PublicKey(), msg, sig[:len(sig)-1], nil); err == nil {
578 t.Errorf("Verify with short signature: want error, got nil")
579 }
580 if err := Verify(sk.PublicKey(), msg, append(sig, 0), nil); err == nil {
581 t.Errorf("Verify with long signature: want error, got nil")
582 }
583 })
584
585
586
587 sk65, err := GenerateKey(MLDSA65())
588 if err != nil {
589 t.Fatalf("GenerateKey(MLDSA65): %v", err)
590 }
591 if _, err := NewPublicKey(MLDSA44(), sk65.PublicKey().Bytes()); err == nil {
592 t.Errorf("NewPublicKey(MLDSA44, MLDSA65 encoding): want error, got nil")
593 }
594 }
595
596 func TestUninitialized(t *testing.T) {
597 t.Run("Verify", func(t *testing.T) {
598 msg := []byte("attacker-controlled message")
599 sig := make([]byte, MLDSA44SignatureSize)
600
601 cases := []struct {
602 name string
603 fn func() error
604 }{
605 {"empty signature/nil opts", func() error {
606 var pk PublicKey
607 return Verify(&pk, msg, nil, nil)
608 }},
609 {"empty signature/empty opts", func() error {
610 var pk PublicKey
611 return Verify(&pk, msg, nil, &Options{})
612 }},
613 {"zero length signature", func() error {
614 var pk PublicKey
615 return Verify(&pk, msg, []byte{}, nil)
616 }},
617 {"full length signature", func() error {
618 var pk PublicKey
619 return Verify(&pk, msg, sig, nil)
620 }},
621 {"full length signature/with context", func() error {
622 var pk PublicKey
623 return Verify(&pk, msg, sig, &Options{Context: "ctx"})
624 }},
625 }
626 for _, c := range cases {
627 t.Run(c.name, func(t *testing.T) {
628 err, panicked := call(c.fn)
629 if panicked != nil {
630 t.Errorf("Verify panicked: %v", panicked)
631 }
632 if err == nil {
633 t.Error("Verify accepted uninitialized PublicKey, want error")
634 }
635 })
636 }
637 })
638
639 signFuncs := []struct {
640 name string
641 sign func(sk *PrivateKey, msg []byte, opts crypto.SignerOpts) ([]byte, error)
642 }{
643 {"Sign", func(sk *PrivateKey, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
644 return sk.Sign(nil, msg, opts)
645 }},
646 {"SignDeterministic", func(sk *PrivateKey, msg []byte, opts crypto.SignerOpts) ([]byte, error) {
647 return sk.SignDeterministic(msg, opts)
648 }},
649 }
650 for _, f := range signFuncs {
651 t.Run(f.name, func(t *testing.T) {
652 msg := []byte("message")
653
654 cases := []struct {
655 name string
656 fn func() error
657 }{
658 {"nil opts", func() error {
659 var sk PrivateKey
660 _, err := sk.Sign(nil, msg, nil)
661 return err
662 }},
663 {"empty opts", func() error {
664 var sk PrivateKey
665 _, err := sk.Sign(nil, msg, &Options{})
666 return err
667 }},
668 {"typed nil opts", func() error {
669 var sk PrivateKey
670 _, err := sk.Sign(nil, msg, (*Options)(nil))
671 return err
672 }},
673 {"mu opts", func() error {
674 var sk PrivateKey
675 _, err := sk.Sign(nil, msg, muOptions{})
676 return err
677 }},
678 }
679 for _, c := range cases {
680 t.Run(c.name, func(t *testing.T) {
681 err, panicked := call(c.fn)
682 if panicked != nil {
683 t.Errorf("panicked: %v", panicked)
684 }
685 if err == nil {
686 t.Error("accepted zero-value PrivateKey, want error")
687 }
688 })
689 }
690 })
691 }
692
693 t.Run("TypedNilOptions", func(t *testing.T) {
694 sk, err := GenerateKey(MLDSA44())
695 if err != nil {
696 t.Fatal(err)
697 }
698 msg := []byte("message")
699
700 t.Run("SignDeterministic", func(t *testing.T) {
701 want, err := sk.SignDeterministic(msg, nil)
702 if err != nil {
703 t.Fatalf("SignDeterministic(nil opts): %v", err)
704 }
705 var got []byte
706 _, panicked := call(func() (err error) {
707 got, err = sk.SignDeterministic(msg, (*Options)(nil))
708 return err
709 })
710 if panicked != nil {
711 t.Fatalf("SignDeterministic(typed-nil opts) panicked: %v", panicked)
712 }
713 if !bytes.Equal(got, want) {
714 t.Error("SignDeterministic(typed-nil opts) != SignDeterministic(nil opts)")
715 }
716 })
717
718 t.Run("Sign", func(t *testing.T) {
719 var sig []byte
720 _, panicked := call(func() (err error) {
721 sig, err = sk.Sign(nil, msg, (*Options)(nil))
722 return err
723 })
724 if panicked != nil {
725 t.Fatalf("Sign(typed-nil opts) panicked: %v", panicked)
726 }
727 if err := Verify(sk.PublicKey(), msg, sig, nil); err != nil {
728 t.Errorf("signature made with typed-nil opts does not verify under empty context: %v", err)
729 }
730 })
731 })
732 }
733
734 func call(fn func() error) (err error, panicked any) {
735 defer func() { panicked = recover() }()
736 err = fn()
737 return err, nil
738 }
739
740 type muOptions struct{}
741
742 func (muOptions) HashFunc() crypto.Hash { return crypto.MLDSAMu }
743
744 func BenchmarkSign(b *testing.B) {
745
746
747
748
749
750 b.Run("ML-DSA-44", func(b *testing.B) {
751 benchmarkSign(b, MLDSA44(), benchmarkMessagesMLDSA44)
752 })
753 b.Run("ML-DSA-65", func(b *testing.B) {
754 benchmarkSign(b, MLDSA65(), benchmarkMessagesMLDSA65)
755 })
756 b.Run("ML-DSA-87", func(b *testing.B) {
757 benchmarkSign(b, MLDSA87(), benchmarkMessagesMLDSA87)
758 })
759 }
760
761 func benchmarkSign(b *testing.B, params Parameters, messages []string) {
762 seed := make([]byte, 32)
763 priv, err := NewPrivateKey(params, seed)
764 if err != nil {
765 b.Fatalf("NewPrivateKey: %v", err)
766 }
767 rand.Shuffle(len(messages), func(i, j int) {
768 messages[i], messages[j] = messages[j], messages[i]
769 })
770 i := 0
771 for b.Loop() {
772 msg := messages[i]
773 if i++; i >= len(messages) {
774 i = 0
775 }
776 priv.SignDeterministic([]byte(msg), nil)
777 }
778 }
779
780 func BenchmarkVerify(b *testing.B) {
781 b.Run("ML-DSA-44", func(b *testing.B) {
782 benchmarkVerify(b, MLDSA44())
783 })
784 b.Run("ML-DSA-65", func(b *testing.B) {
785 benchmarkVerify(b, MLDSA65())
786 })
787 b.Run("ML-DSA-87", func(b *testing.B) {
788 benchmarkVerify(b, MLDSA87())
789 })
790 }
791
792 func benchmarkVerify(b *testing.B, params Parameters) {
793 priv, err := GenerateKey(params)
794 if err != nil {
795 b.Fatalf("GenerateKey: %v", err)
796 }
797 msg := make([]byte, 128)
798 sig, err := priv.SignDeterministic(msg, &Options{Context: "context"})
799 if err != nil {
800 b.Fatalf("SignDeterministic: %v", err)
801 }
802 pub := priv.PublicKey().Bytes()
803
804
805
806
807 b.Run("Whole", func(b *testing.B) {
808 for b.Loop() {
809 pk, err := NewPublicKey(params, pub)
810 if err != nil {
811 b.Fatalf("NewPublicKey: %v", err)
812 }
813 if err := Verify(pk, msg, sig, &Options{Context: "context"}); err != nil {
814 b.Fatalf("Verify: %v", err)
815 }
816 }
817 })
818
819
820 b.Run("Precomputed", func(b *testing.B) {
821 pk, err := NewPublicKey(params, pub)
822 if err != nil {
823 b.Fatalf("NewPublicKey: %v", err)
824 }
825 for b.Loop() {
826 if err := Verify(pk, msg, sig, &Options{Context: "context"}); err != nil {
827 b.Fatalf("Verify: %v", err)
828 }
829 }
830 })
831 }
832
833 func BenchmarkKeygen(b *testing.B) {
834 b.Run("ML-DSA-44", func(b *testing.B) {
835 for b.Loop() {
836 NewPrivateKey(MLDSA44(), make([]byte, 32))
837 }
838 })
839 b.Run("ML-DSA-65", func(b *testing.B) {
840 for b.Loop() {
841 NewPrivateKey(MLDSA65(), make([]byte, 32))
842 }
843 })
844 b.Run("ML-DSA-87", func(b *testing.B) {
845 for b.Loop() {
846 NewPrivateKey(MLDSA87(), make([]byte, 32))
847 }
848 })
849 }
850
851 var benchmarkMessagesMLDSA44 = []string{
852 "BUS7IAZWYOZ4JHJQYDWRTJL4V7",
853 "MK5HFFNP4TB5S6FM4KUFZSIXPD",
854 "DBFETUV4O56J57FXTXTIVCDIAR",
855 "I4FCMZ7UNLYAE2VVPKTE5ETXKL",
856 "56U76XRPOVFX3AU7MB2JHAP6JX",
857 "3ER6UPKIIDGCXLGLPU7KI3ODTN",
858 "JPQDX2IL3W5CYAFRZ4XUJOHQ3G",
859 "6AJOEI33Z3MLEBVC2Q67AYWK5L",
860 "WE3U36HYOPJ72RN3C74F6IOTTJ",
861 "NMPF5I3B2BKQG5RK26LMPQECCX",
862 "JRGAN2FA6IY7ESFGZ7PVI2RGWA",
863 "UIKLF6KNSIUHIIVNRKNUFRNR4W",
864 "HA252APFYUWHSZZFKP7CWGIBRY",
865 "JFY774TXRITQ6CIR56P2ZOTOL6",
866 "ZASYLW5Y3RAOC5NDZ2NCH5A4UY",
867 "42X4JXNPXMFRCFAE5AKR7XTFO7",
868 "YAHQUWUH534MUI2TYEKQR7VR3A",
869 "HBP7FGEXGSOZ5HNOVRGXZJU2KG",
870 "HG4O7DCRMYMQXASFLMYQ6NMIXK",
871 "2KPQMDZKS65CLJU4DHTMVV5WI3",
872 "G6YSUTEX4HHL44ISK2JVVK45BV",
873 "PUJGPEQUBQM3IK2EXDQFJ2WGBG",
874 "PNS6HMQAWA3RORSMSNEUAINMIR",
875 "L35MZS4XYIJK453OFXCZG4WHIK",
876 "CRY54YZMFRF6JTB3FPNNBWPUOG",
877 "Y25TSZBWGU4HJCRMWZHAWXQ2DN",
878 "23W64TW3AKZPKCM4HMKEHFI6VQ",
879 "PWQAOZ24B4VLNEQR4XKN7LZHDI",
880 "YINPDR3ZSAKPPXP6J6VAXHIPYO",
881 "JDBB52ZRAB3PYBPNE7P4COY5PJ",
882 "4DYU52LQLVG3LTREOTLBCJK3XC",
883 "AB45MV6RKUGPCW4EUK7DX23MJX",
884 "HEJSITE5K7J6YJ74OEATVTCERV",
885 "ZKI5QCFCGM26UK7F5KYTENXKD2",
886 "VH5G3ZLF5XC22QAEJ6JDGOBE5Y",
887 "HYGXFHH3JW5SENG26MXLL54IGV",
888 "MJUCRL36JZ757UYHBFPCJBPZRH",
889 "IBH3T6NAVLCJQBYSVHAQFUITYA",
890 "VMWCS7JMIMFQB6TPRAMOUXIKWD",
891 "SXRPGPNNW2MMBKQS3HJURIQ3XV",
892 "YPPYMJZW6WYXPSCZIPI57NTP5L",
893 "N3SH6DUH6UOPU7YMQ6BJJEQSPI",
894 "Q243DGA6VC6CW66FFUAB5V3VLB",
895 "OUUBXEU4NJBRN5XZJ7YQUPIZLA",
896 "H5TWHVGC7FXG6MCKJQURD3RNWG",
897 "OONG2ZZ7H3P5BREEEURNJHBBQG",
898 "HWROSSRTBCQOAIQAY5S4EQG4FX",
899 "AJW6PW62JQNU72VKGIQMPBX64C",
900 "OXECVUVAWBBBXGGQGQBTYVEP4S",
901 "M5XN6V2LQJDEIN3G4Z6WJO6AVT",
902 "NHGJUX3WGRTEIRPFWC2I467ST4",
903 "SEOADTJDKAYYLDSC4VAES2CRDJ",
904 "J5AT674S577ZFGEURNIAGYOHKW",
905 "VJQVNMGHG4ITFX2XSPSDEWVZWD",
906 "ZWY3KJPXTAVWWVHNAJDUXZ52TG",
907 "HY46PBUGP4EMH34C6Q56MO7CJP",
908 "MQTUO7CF6R6CRJPVV6F673M6VW",
909 "35Z2Z5KV2RBJPQ7OZ24ZJE6BKR",
910 "OVUEVXBLCU2BBY25QP5WJACDIX",
911 "LNJX7PCLYL35WYJBW6CTXENPUU",
912 "IH7E766LCENOQ5ZKZVCMLEPACU",
913 "T2HZFGDDSFQ6YADB52NIFLBFEV",
914 "RHQUJMN4MB5SYY4FP4ARZH52QJ",
915 "W7GZC5ZM63UF2EJ7OC4WJM3OTH",
916 "T2NHNFVOMICY33AQZSR53HXFQ6",
917 "7ZVB4Y4K4Y2VAM5NC7HHAJNZIB",
918 "UX2I4VF62XJGP2XTNN6LDKXTOH",
919 "HJAMJR5RQTQW7JMW7ZLPRBZE7E",
920 "HKWSKX7MB5346PHYNWNBAYDSYK",
921 "BVWSB75HFLLE45MWA6EPHPTCFR",
922 "YDH2J6NMM7UINHGUOPIUI7PSSR",
923 "SYQPZLK52HMUAQFMVHGRJYKBEY",
924 "7AA6UQFGSPBGNUDPLWXSGNKKPP",
925 "AYXRJGRWZ5S3QOEDVWYHHCICHV",
926 "KFJYAWO7IATSBCSTDUAA5EPFAN",
927 "3JABTLB6T2ICHGVT3HXZZ3OAIT",
928 "WCM3IBOCQJ36WSG627CCNK3QA7",
929 "5FB5H3BZN2J4RGR2DUW7M37NKZ",
930 "VKDDAD3BVOMPSNEDGIRHKX5S6R",
931 "LFH5HVUR726OSFD3YVYM3ZHEIH",
932 "Y4ETQB2KZVFB4M7SALLCTHX2FB",
933 "E6SAU3C25MO2WBBVBKCKP2N4ZE",
934 "3JA54Q3NEKURB5EAPL2FOFIESD",
935 "FZPBW7BIQIW3FTKQD4TLKNWLMD",
936 "LY5W6XFA2ZRI53FTUJYGWZ5RX6",
937 "QID236JY3ICR55O5YRED33O7YT",
938 "HDRU3L6MFEBCBQFNLF5IRPMOAL",
939 "232ANKJBDBG4TSKQ7GJMWTHT23",
940 "CDWE3CELZM5AOJGYEFHMUNSP5O",
941 "7LNJRBOKN6W7RXUU34MDJ2SNKL",
942 "S3IZOADTW2A6E5IGRO5WKX7FVH",
943 "ZAISTLXC55EBMTN6KZ6QX5S7OS",
944 "4Z5ZIVCMFR2PY2PY4Z47T4YPYA",
945 "NE36L53Z6AMYQU7Q5REFUF76MK",
946 "WND5UP5M6KWPBRFP5WIWTOWV3I",
947 "7OC54DLFWMADJEMKEJ3Y2FMMZS",
948 "BWJVZHGEN43ULNIOZCPZOB64HG",
949 "VDFPQSR7RE54A75GT4JDZY5JK2",
950 "HFCD5EPBZBSVMXIDA47DZ6MRD6",
951 "RNBVFIUUJUM7EHRE3VNWSTORGO",
952 "VO5NLQJBR22CRRYUETGTU6JLMR",
953 "RZOMNFHBTL6HMGWH4PEEDASK7U",
954 "QL73UBTOLK5O2TW43YWAIKS6T3",
955 "NE3QVSMWS5G3W5C3BMKTJNMI2L",
956 "YHI6EYQ4GZMB2QPGHPUG2ZUOEL",
957 "6MBATW7MFNRUQBFD3GM35B7YPM",
958 "AIYRY6P5T4XU44CGVPEV6W43FR",
959 "MIAQ2FHXMAPY5NXSS45VRDPRMG",
960 "2SNLHQYKK2K6NSWOF6KPGZ3CPC",
961 "RVBHIQO5LH77ZWEAO3SVL72M2V",
962 "XXTGJCJNRSNLE7ARAH2UU6LVKR",
963 "DQMGILY5IDMWN5OYQYYXH26ZGR",
964 "627VTXXMM455KMTFNUUTKNFXPY",
965 "HC7IBFGLZCWGUR4K7REPMPW6W4",
966 "CHL6JRQUS7D4NML3PFT37PPZAA",
967 "Y767HXJAGJ75KE3JLO4DTLQIXC",
968 "NTIODXI5I7TF2KXXWXOAYGT7G4",
969 "PKZYEK2WAI4D4HEYYZH6H5IOMP",
970 "FG6J6G7HZDEDF4JQBQOTC7RQGZ",
971 "3VHM2VZU77Y25E3UUYZJLB2QLA",
972 "WRZQJQW7ARH4DXYHVLCJ4HRTTB",
973 "LQXKV5HD2AZHENSJ2VFLJ5YU5L",
974 "MF6Q4OA2EN6TG6BUDK7RWCQNPU",
975 "3USKYKPC5CB3EC4ZRMZVE3R2UO",
976 "3WICO2GVS3IRBFUHNDLNKWVP7N",
977 "P6ZR2UZZOVUZKT4KUS5WICW5XE",
978 "PYPZUU76RYVOUZGUUX33HLDKYA",
979 "2FTSURHV34VYTVIUU7W6V5C3NK",
980 "YABDYMGXS2MD2CYF3S4ALG4FLG",
981 "MHIBDH25RRPWV3P4VAWT6SAX3I",
982 "OINSMWJQ2UTOOKZ3X6ICXXBQR7",
983 "PFTQS7JNU2Q3Q6L4CGBXVLOYNE",
984 "A4MZ7CCVYQUDJ2AFHNXBBQ3D24",
985 "CPUB5R3ORTCMSMCLUQURE6AN5O",
986 "NF5E7U3DFTXWFFXXHUXTEP4VZQ",
987 "AWB5WDFERWSSJG53YGJMDORQKR",
988 "U5JQUILKD6SEL6LXAMNFZP6VSW",
989 "M45NLOAFLO74EJKG5EXNET6J5Y",
990 "P2KTEUMZ5DZZMYSPOHDR2WJXAN",
991 "KVO7AXZNFBUBPYLOTZQQ42TFNS",
992 "WGJJ7SAEV6SBBWWYS4BTLD63WM",
993 "Y6GURVDV4ESRBPWSTV25T4PE4K",
994 "ESK7MPFPUZ5ZAQ52RP4SQIYCCC",
995 "623M3CIABZ3RANERQ2IREXAVYO",
996 "OQ4CQCFO42RS4BMMSGSDLUTOQO",
997 "AMFHRDVGM6G2TIR3TKIFGFSDVM",
998 "7VVSGGCVC53PLOYG7YHPFUJM5X",
999 "Z3HMESVL7EZUSZNZ33WXEBHA2N",
1000 "AWWVRQD5W7IBSQPS26XOJVDV5H",
1001 "OQBZ5ZST3U3NZYHSIWRNROIG6L",
1002 "II573BW7DJLBYJSPSYIABQWDZD",
1003 "MOKXOQFOCUCLQQH4UKH2DPE7VN",
1004 "XR54NGUOU6BBUUTINNWBPJ35HX",
1005 "DNK36COZGFXI6DY7WLCNUETIRT",
1006 "R5M2PV7E3EHEM3TLGRCL3HSFMC",
1007 "ITKENZQYDQMZFCUPOT7VF3BMU7",
1008 "5GDCB74PPPHEP5N5G3DVRCYT7R",
1009 "ZMKXVRPLI5PY5BDVEPOA3NQZGN",
1010 "GBLIALWTHTUDTOMDERQFVB77CS",
1011 "VKRTTXUTFOK4PJAQQZCCT7TV3T",
1012 "ZJBUJJ4SW62BXOID3XO2W2M2PF",
1013 "SKWT5T6QJTCD3FCINIK22KMVBJ",
1014 "EHINNU6L33HRLOOJ3A2XFJSYQL",
1015 "N4HRQJEFPAT5SU3YPO74WSMQIR",
1016 "TGPTZ3ENMFWB5CZKJFR5WHIRI4",
1017 "O4HNFTAUJJ2LZPQXPXRAXOVABA",
1018 "4JVB5STP2YG5GYOXDWIF4KCKFB",
1019 "MY554X3YZHBECLHNNZ7A3SPJTU",
1020 "ASCJMAH7VCQAD2QJSWXPSVSM3H",
1021 "NBNGL5DZ623KCG2JNZFGZMZ7KD",
1022 "KGMZSW35AEQOJ6FA7IR7BHZI52",
1023 "Q7QUHHS4OJFMJ4I3FY6TDKSMZQ",
1024 "MZAE7TOEXAS76T7KIC73FEYRU4",
1025 "2BVESR3REAWADCGYOYM7T646RG",
1026 "EK3L2ORP4LT3HU3EMXDSQWFOKJ",
1027 "3X4A6VMGMIDLVK72FZSDHSERWY",
1028 "I3UHWI6M6HQFRBSQ6W2SABUNUP",
1029 "REKPXW4DIB4MTKMPHN3RBVHVME",
1030 "W37FNFZE35NX65Z7CVQ7L5U4L5",
1031 "4AGYK6U2KP6RAOADCBUDDCBECV",
1032 "IXM4SFQUDW2NOTXZIPWTNGET3F",
1033 "6YE4G3VELF27MN3Z5B4VIQ3XYK",
1034 "LPOZCPZAG3MD47MIWGR4FIOCDH",
1035 "WGREKUL2LD7C7SYGKH7APIY2A6",
1036 "WWW277FKTKUXQMP4BECSRHLWJI",
1037 "UYE4IQPMSTXVQG7EJALKWWEGDN",
1038 "TIV2L5Z6K7SNGNUVWSNKTAF4UE",
1039 "I3FQOAW3PINUK26P62HCX657FO",
1040 }
1041
1042 var benchmarkMessagesMLDSA65 = []string{
1043 "NDGEUBUDWGRJJ3A4UNZZQOEKNL",
1044 "ACGYQUXN4POOFUENCLNCIPHFAZ",
1045 "Z3XETEYKROVJH7SIHOIAYCTO42",
1046 "DXWCVCEFULV7XHRWHJWSEXWES7",
1047 "BCR2D5PNLGFYX6B3QFQFV23JZP",
1048 "2DVP5HNG54ES64QK4D37PWUYTJ",
1049 "UJM4ADPJLURAIQH4XA6QYUGNJ6",
1050 "B5WRCIPK5IVZW52R6TJOKNPKZH",
1051 "7QNL6JTSP62IGX6RCM2NHRMTKK",
1052 "EJSZQYLM7G7AJCGIEVBV2UW7NN",
1053 "UFNA2NKJ3QFWNHHL5CXZ4R5H46",
1054 "QZAXRTT3E4DOGVTJCOTBG3WXQV",
1055 "KH2ETOYZO5UHIHIKATWJMUVG27",
1056 "V5HVVQTOWRXZ2PB4XWXSEKXUN5",
1057 "5LA7NAFI2LESMH533XY45QVCQW",
1058 "SMF4TWPTMJA2Z4F4OVETTLVRAY",
1059 "FWZ5OJAFMLTQRREPYF4VDRPPGI",
1060 "OK3QMNO3OZSKSR6Q4BFVOVRWTH",
1061 "NQOVN6F6AOBOEGMJTVMF67KTIJ",
1062 "CCLC4Y6YT3AQ3HGT2QNSYAUGNV",
1063 "CAZJHCHBUYQ6OKZ7DMWMDDLIZQ",
1064 "LVW5XDTHPKOW5D452SYD7AFO6Q",
1065 "EYA6O6FTYPC6TRKZPRPX5N2KQ4",
1066 "Z6SGAEZ2SAAZHPQO7GL7CUMBAG",
1067 "FKUCKW6JQVF4WQYXUSXYZQMAVY",
1068 "LN2KDF4DANPE4SC4GKJ4BES3IZ",
1069 "AVCRTWB6ALOQHY34XI7NTMP2JH",
1070 "A5WHIS6CBWPCYIEC6N2MBAOEZ6",
1071 "JC2BH476BXUQFIDA6UCR5V4G4F",
1072 "NU6XH6VLSSFHVSRZCYXPFYKYCD",
1073 "GSUXVZBDDYSZYFGXNP6AZW3PTC",
1074 "XJPRNJ26XP4MIYH2Q7M7MPZ73M",
1075 "INUTUP3IRFWIIT23DNFTIYKCFY",
1076 "T4KH7HKLEYGXHBIRFGFCRUZCC4",
1077 "GGQX4JFVWZHE5Y73YTLMSSOXNS",
1078 "BUA4Q3TQZGLVHMMJU62GQOSHLV",
1079 "WXW3SJXLSZO2MYF4YFIMXL2IQP",
1080 "Q32XBVVGFQTSXAIDJE6XSEPRZG",
1081 "6TEXT6SA7INRCTDSCSVZJEQ2YG",
1082 "ZBN4UL43C3SJIG4HYR236PXCVS",
1083 "TVWPLLC7NROBREWOM75VA3XCR3",
1084 "CCDGL2FURLBABQ4IJBYCB75JFR",
1085 "XBZGCOVTZHCPAARBTMAKPIE6GJ",
1086 "TPRAENJ7I54XRIVH6LL6FDIA3I",
1087 "RKOM3PHFILPIIQZL4ILQWGRYWI",
1088 "CEEZIZ2WUXHQQFATYYGQ3ZDBTI",
1089 "SLKOVAP6WLIVJBVU7VZG3ZGEOW",
1090 "TWMCLJJSWEEQQPQGGDKEJ5SU2R",
1091 "IFMUXXCD2LC7IGQLZ2QEK5UOQ2",
1092 "C7IWFEBHW2CXN4XBJS7VLWH3VK",
1093 "7KJYUEW3F264727TM4LE6RMGDO",
1094 "BPG2XAPBMBTA4VMPUM7IZVZPK3",
1095 "Y5X577BWRZNPLNUHJVSKGMUXYB",
1096 "ZCKMKM23E4IUPTNQDFN2LTLZVX",
1097 "4RKK223JNBDAP4G5DOAHHZ3VNO",
1098 "5UZ3TQZHZT22ISTB4WJEVO6MC4",
1099 "YMVS4HFSJ32CRZRL23PXZUEJFJ",
1100 "UQEUJUTPSZLZARNBXWMCTMHPFF",
1101 "CZAAZ5WK7EIPMW7NA3EZNNBF45",
1102 "227PBHH23WM7F2QLEZSPFYXVW4",
1103 "YUYS2J5CRFXZ4J4KJT2ZKIZVW3",
1104 "MFLHZJOZV44SN4AH6OJ3QZWM2O",
1105 "H2B3CRBCXYN7QWDGYUPHQZP23A",
1106 "T4L6YWQUQ3CTACENAJ5WUXZWFH",
1107 "N723H6MUGPZSRZ72C635OD4BP7",
1108 "NI4TUMVA6LQPQV2TXPN4QOIGBZ",
1109 "CQI3S4LSTQASSJJVZXEFPOVW7K",
1110 "ANPY4HJ64LLSB3GK2R4C6WDBS3",
1111 "RGWQCZKQLMT5FZRDE4B3VMASVK",
1112 "Q3WCCF2HA3CA4WWRJBMGBW7WI7",
1113 "2AKJRXFHXLUQPOXPTLSZN5PW4A",
1114 "IJWOOTI4N7RWXJIHAPXN6KEWEN",
1115 "4D53T6N6ATOVTD4LKSTAAWBJMU",
1116 "B4G5HDD6RITG6NIH6FXCRZDYZM",
1117 "TJCDFKMRUY2OG6KRSMNVCGQFUP",
1118 "PB33IHQKALAY6H6GVBVLI6ZRXK",
1119 "SCCWGW2J5S4WL4FTTMQ435F6DB",
1120 "ZVJH2HSMTLHGXMGPMXLJCKCLLE",
1121 "62LG37U6JXR77YRZQQCDSBHVCS",
1122 "BU4CBWOXQ352TEOKIXO245ID4O",
1123 "UEZOH7KEIODSEVRUF6GMWGA2RB",
1124 "IPJWROME4GM66CGLUWP5BJ4SX6",
1125 "355GDC7TG64AZJ7IJX6K62KZCZ",
1126 "AHTFKX3V7XUB3EWOMQVCGZYGUE",
1127 "N4RV2GKXJ4SPHHJ52Z7K5EGLER",
1128 "ZY7V7NE5F66XHDHWM6YNFEWZA6",
1129 "DIKFO5KAVT4WAP7BOEFM56ZUSR",
1130 "4TDFOFKDAPIOM3MU5GD7NPXNWQ",
1131 "AD7YZO756HDK6YWFILAKW3JWA7",
1132 "NUA53JS2ZK2BGHH3A7BJTJZYW7",
1133 "QLCNC3AQNKLRMSYR62WQSQP5VI",
1134 "SJ7OBS7ZYXSGXOYXPE5KW2XKN6",
1135 "44HBMOGMIMJS63CEXQU7FCXE2E",
1136 "KCK3J7ZL6QF4SLHHSWTJURK7PG",
1137 "HLH4CLUGBSOOBSS3BPO62N5MC3",
1138 "3FNS4GITO6OEUBAVDDXK4WOBTD",
1139 "IAC3K3I4AQGY3G6UHG7PL2N6TE",
1140 "KUKLNH74POJI5DYAEWUD7RABTQ",
1141 "ETM6N7VU3GBSQ7P5MCD6UF3E3S",
1142 "IZITM5NYBGJZLSI3BI4VEMW43U",
1143 "46OPQU4LL6N3Z2U7KYPKUMBAGI",
1144 "EV7YZ5DMAV7VKYJQUFSRD37GPP",
1145 "AV7W2PGYDJIAKLFVEBL6BXQSGC",
1146 "M2FOX5QZEZKV4QXKPI5XUZDHEM",
1147 "R4IFPLVMOVYCHRTR6LXAUGP3LL",
1148 "JGH6XJUMP4DRVAM27P2JNOKXVO",
1149 "D2XN3ZLLU6VFPMDYM7NBHSQEOI",
1150 "2PO3BYENOMQK6SHQDCFSRPJQI3",
1151 "IBVQ7U3QEUC6PQRE4PV53JTZTK",
1152 "ZBCOX4P7NG2IXXFB2R43MG2SLV",
1153 "5NJDPQVVDO7ADNZ2CV7L6QBNGZ",
1154 "V7ASFIIYUMXFGW4B7ZM6LOGUTE",
1155 "PX5IJZ7W2LUPKM6YN4PMZ43ZLM",
1156 "AYK7SZ23DHC7Q56MWAJXBG76LB",
1157 "UYCAPXJM4HNGKLIDSZ4NCEDJLN",
1158 "UWMDZ3C2ODLACKGJPGETNQ3TA4",
1159 "Q6OI6R3WYYJ4CCZCDJBQMCRCZR",
1160 "LCMJHLP7354APCEGPKE7HHWTWB",
1161 "N7T7ZKOYPAMEYTTDOWZNCN6PRD",
1162 "UZADPU4UNHAF7L7LQDMTKA2EQH",
1163 "DC2OEPQDECVLRVNNCS6BMH4CRA",
1164 "37IZ427XHUMZ66EJ62U2YEZDAC",
1165 "6BCZDQZDPZLS5OGESKNUBPSSFV",
1166 "ST2LEMJ4OLQ32TJTLH2WCWT4WA",
1167 "GA2TL4SFLEW4G2B5PQMIKJT5XG",
1168 "L7PPBIET26EH7LQTLEFC4I4EIA",
1169 "6YSM7MC2W4DEV6ULAHMX27LH56",
1170 "QL26Z5KZ4YRRG2BXXGDRRLV357",
1171 "677TWRAJ5NSNHCE243POQPEG7K",
1172 "66MEBQJLGAGVXDX3KZ2YFTTVJM",
1173 "6D4VUWAQD6R65ICSDLFAATC67V",
1174 "7GXLD5CNU3TDUQSSW42SHL7B5D",
1175 "RQETUMEBG2ZM2NF2EZAQHGHWWE",
1176 "DCRX5ANWDMXZFIDVAXYLQZYMRN",
1177 "5SDWT7YAF7L4WWANAGYINZAYXH",
1178 "PZILRV7I2S6WKUSHKYRLA2JQY3",
1179 "2G66TK2PZ5MOTAZDN7BFS3LAIH",
1180 "QOLJ3WGJ6JS3FMMXBNTNAIKXVK",
1181 "FMAL67YTHDCCYVZ5CRMN2XJPDN",
1182 "UOTZDXTJKQ3YAIRKHTYNX6G55P",
1183 "X3DLNPJ3V62LRHGEY4DTT35H3R",
1184 "DKU7CHNXPB5QRZVGIQZW46XCKC",
1185 "RAKBD4LQKEDTVDSK3DVTRWG23B",
1186 "INTRA7BWHLVQMBRKBJNUSMF7MU",
1187 "AUYRBNVCOYYHOHUYOOFIZ2FWMD",
1188 "22EJVDEQ7PASLBAMTVKXOQP5RJ",
1189 "3S6NATWA57SFTZEW7UZUOUYAEU",
1190 }
1191
1192 var benchmarkMessagesMLDSA87 = []string{
1193 "LQQPGPNUME6QDNDTQTS4BA7I7M",
1194 "PTYEEJ7RMI6MXNN6PZH222Y6QI",
1195 "R6DTHAADKNMEADDK5ECPNOTOAT",
1196 "S2QM7VDC6UKRQNRETZMNAZ6SJT",
1197 "EYULPTSJORQJCNYNYVHDFN4N3F",
1198 "YETZNHZ75SXFU672VQ5WXYEPV2",
1199 "KTSND3JGA4AN3PCMG4455JEXGR",
1200 "JGE6HK37O6XMWZQZCHFUPNUEXP",
1201 "CRYB2FZD2BYNANBFFO2HRZEHGZ",
1202 "7MLNDZJ7OIEPBJZOMULOMQH2BA",
1203 "4WQCNTIFVSX2DNALMWUKZRA6CI",
1204 "Y5NK4OBDSDWC5WLL27CEEXYYOT",
1205 "C4SSWSPBVCDAWJXH2CDMXR36LH",
1206 "THDBKXRTKWJUGJMAAYTWTFMX7Z",
1207 "NWXPUD4DAA6QOREW4AFFYQYQNG",
1208 "3RQIJXMO7WYHBEBL3G6EOLNZNQ",
1209 "R7JEOHFP2C7O4AVPRPRELXWOMM",
1210 "LU6MWR7SZXVIKS54BY62X67NPA",
1211 "FG2FFM4F2ECKHCSJ75KXK632JP",
1212 "BF76ZDSVVUSYS5KK4FFD22YPS7",
1213 "HCLBWZRLHEMYZLFWHLAN2BKCZ7",
1214 "HGFVS4QC7AWXYPVRSWAK77KTQF",
1215 "LUZ3C53PUUHBWCDJ7WAHK2UT3K",
1216 "Y3WR6SMDUBW34N3MUT7EQYIJCV",
1217 "F2X35AQTXVZBMPXTWNAAH4ZX2W",
1218 "6MKFFDYWD6ZAKS3C6GRCRLZLRF",
1219 "AFMZYYFRHKMQRNKU5UTSKQ74H6",
1220 "TDTN7J3O367OVPWLESRNPLN4M2",
1221 "WYMLD2X6N4CZ2RDOKF5CFTSYTG",
1222 "UNPTSBLJ6HZRNR72T2VEEHCFX2",
1223 "SNCM4R2P27AJOXBS67RMCARS3U",
1224 "OU7QBE5QOXO7CIYTBJR3KOW2WK",
1225 "2NNQOBQKZ2OD4ZAXI3SNEURYUP",
1226 "YQTUPOYBT67XPCHIGKSGSKC3BZ",
1227 "HGB4ZM3G76IXYWWCMVT3HONRIS",
1228 "WZC6QUKRZZ2TOVA277JYKQITEW",
1229 "XO2WT46A5HYL6CUJF7SGJ6YWOG",
1230 "4QJA35PMYQIDRZ7ZHG7RLZJVGF",
1231 "BMJZELWZ4I2UWXESU3NR6ATC4M",
1232 "XWLFB7FN6D5PRY6YUXC5JUIBFM",
1233 "WRAFFF27AVTIOYIBYA2IPTXI3R",
1234 "VOXUTYTN2XZ362OJFO2R53UCUF",
1235 "UHN73ARJ737WUJ6QYEI7U46OPO",
1236 "3Y3K5E2A4ML3VYVNAFWEEIXTSN",
1237 "QMU4322NKPRLE7JBGYFGS36H2S",
1238 "NJAQTNCXPVDICTDVUKTPRCD2AX",
1239 "OC373ZFBNV2H46T6OY3XRPSUHG",
1240 "UBLAS6CDWE3A662MLKP7QDEOCC",
1241 "BKFDLAL2RTPMERYVW3B7UJ5W3H",
1242 "QFKFGXKGW5SAKLBAWQXUWW77OS",
1243 "EJNUQHTLLOVB4ARETOGLY4WUTJ",
1244 "N243OCMVLLAO6I2XLCYOIMQYGY",
1245 "YRRFLWK7ZASUKYX7ZLQMW2PJ6X",
1246 "3DGVPBWD2BIK6KQE65K72DNJNM",
1247 "TJRYMNOAIW33VIHKLJG4GXAVUK",
1248 "6DSRINAYXL34U54U355U7IVFGS",
1249 "6CHA4MX7LVS77XKRWG7IYC3XVL",
1250 "GM2CEGBEPBOHAPIOBUWJ4MJNTG",
1251 "VJKHGBY33VUIJFEQLX3JVUNQBD",
1252 "DTOHAD5M2KL46IZHE4TPLJWHTI",
1253 "IYFG3UDN7ROOY2ZFSLM2BU2LMQ",
1254 "A5OGJHPOE4PW6QSZYHZ5TKPGIC",
1255 "FX4BCN67AEGCLUTLFPNDL3SQU5",
1256 "MWIZQVOZOHTTBUXC3BEX62MNI5",
1257 "BYHVJHBLK4O6LFSKEIQ3CAAKU7",
1258 "QJU7P6KWSSKAA5GVA6RH4OV7MX",
1259 "I3T3XM5Z5TAJHAYDQHFA2ZV7PU",
1260 "L46MQCHV3TJ6FYIQQ2FCJXES74",
1261 "QXZRQIYAJMXYR6PU3VDYGCIT5W",
1262 "MFS53RR2XEYS22NYOJLGTHVTTM",
1263 "FRWIWJRP4AQMXWX4WJ4WYVKM3E",
1264 "X6GK6IGVLJWYSHLKHGXSW3TJDP",
1265 "L5LPJ2HIWA4UY6G6FMZXGDEDAM",
1266 "GD6FYOYUGDHXEQ5S2KLJEGNSN7",
1267 "ODAL7ZRKXSPAAN5DVRBWJQCFQX",
1268 "CV3QFBDXBPT3SCPJGUYSMDN6ZS",
1269 "IGSLSACRZ6XID466KQIB4YNGYO",
1270 "WZ2EACBN26RAML2S52YXRYP2OF",
1271 "LB76VEVNOBYFMKFZ7SDFCBCHQE",
1272 "TLFA7EU3JJFAP6EMUKNV2ZXRBM",
1273 "SIIJF6OXAKRP25CBUYFBRCDDVP",
1274 "TEPNI7TJ7HASJWIQMBS4VFLRQC",
1275 "VK2JINYWEDV7IQFWH4OTAD4W5O",
1276 "GILUH5AMVE4TM7EKPXJBZGT6EJ",
1277 "DV7ALFRAW3TI4WMQQLDTO6RNHN",
1278 "CAIB5G3NXC5ASPLFIWAFPVHS5B",
1279 "MLFJXZUOAGN7EGPMXOOVTB2CL4",
1280 "6MZYT3ANWHBOS67WGHZI3QPEAP",
1281 "LVJDQB52C2PERSSQJRMRCJ4UBF",
1282 "QY4VKAZAYQIZOX2L2VO2QHAQVC",
1283 "UAA5SST2XA76JPKM3XOZ5RUHFI",
1284 "VLZWF53JSQ6SCRUFDKVPXWAS4L",
1285 "NX2DZIKMJIYXUNSAHFP23FHTBU",
1286 "F5OAKDDDA34A2RPIKDPM5CYPMZ",
1287 "E5PEP3ANIK2L4VLOST4NIYNKBD",
1288 "IPBGFLHSMP4UFXF6XJX42T6CAL",
1289 "XHPU7DBFTZB2TX5K34AD6DJTK3",
1290 "2ZU7EJN2DG2UMT6HX5KGS2RFT6",
1291 "SD5S7U34WSE4GBPKVDUDZLBIEH",
1292 "WZFFL3BTQAV4VQMSAGCS45SGG3",
1293 "QE7ZT2LI4CA5DLSVMHV6CP3E3V",
1294 "YIWMS6AS72Z5N2ALZNFGCYC5QL",
1295 "A4QJ5FNY54THAKBOB65K2JBIV7",
1296 "6LORQGA3QO7TNADHEIINQZEE26",
1297 "5V45M6RAKOZDMONYY4DIH3ZBL2",
1298 "SVP7UYIZ5RTLWRKFLCWHAQV3Y2",
1299 "C2UYQL2BBE4VLUJ3IFNFMHAN7O",
1300 "P4DS44LGP2ERZB3OB7JISQKBXA",
1301 "A6B4O5MWALOEHLILSVDOIXHQ4Z",
1302 "DKQJTW5QF7KDZA3IR4X5R5F3CG",
1303 "H6QFQX2C2QTH3YKEOO57SQS23J",
1304 "DIF373ML2RWZMEOIVUHFXKUG7O",
1305 "Z5PPIA3GJ74QXFFCOSUAQMN5YN",
1306 "PM6XIDECSS5S77UXMB55VZHZSE",
1307 }
1308
View as plain text