Source file src/crypto/mldsa/mldsa_test.go

     1  // Copyright 2025 The Go Authors. All rights reserved.
     2  // Use of this source code is governed by a BSD-style
     3  // license that can be found in the LICENSE file.
     4  
     5  //go:build !fips140v1.0
     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  // TestAccumulated accumulates 10k (or 100, or 60M) random vectors and checks
    28  // the hash of the result, to avoid checking in megabytes of test vectors.
    29  //
    30  // 60M in particular is enough to give a 99.9% chance of hitting every value in
    31  // the base field.
    32  //
    33  //	1-((q-1)/q)^60000000 ~= 0.9992
    34  //
    35  // If setting -60million, remember to also set -timeout 0.
    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  	// We allocate
   159  	//
   160  	//   - the PrivateKey (k and kk) structs
   161  	//   - their temporary inner structs (2x)
   162  	//   - the public key (pkBytes) and signature (sig) byte slices
   163  	//   - the Options argument to Sign
   164  	//
   165  	// on the heap. The structs are too large for the stack, the byte slices are
   166  	// variable-sized, and Options is cast into an interface.
   167  	//
   168  	// Still, check we are not slipping more allocations in.
   169  	var expected float64 = 7
   170  	if fips140.Enabled() {
   171  		// The PCT does a sign/verify cycle, which allocates a signature slice.
   172  		expected += 1
   173  	}
   174  	if fips140.Version() == "v1.26.0" {
   175  		// The v1.26.0 implementation precomputes PublicKey, making it large
   176  		// enough to require heap allocation. Add pk, its inner struct, and the
   177  		// return value of k.PublicKey().
   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  	// Per the MLDSA*() docs, repeated calls return the same value, suitable for
   215  	// equality checks and switch statements.
   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  // computeMu reproduces μ = SHAKE256(SHAKE256(pk, 64) || 0x00 || ctxlen || ctx ||
   225  // msg, 64) per FIPS 204, used to drive the External μ signing path.
   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  // fakeSignerOpts is a [crypto.SignerOpts] whose [HashFunc] returns h, used to
   243  // exercise the opts-dispatch paths in [PrivateKey.Sign] without going through
   244  // [Options].
   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  		// nil opts and &Options{} must be equivalent (and both interoperable
   259  		// with a nil/zero Verify opts).
   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  		// A non-*Options crypto.SignerOpts whose HashFunc returns 0 must
   283  		// also sign directly, with empty context.
   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  		// crypto.Hash(0) similarly: HashFunc returns 0.
   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  		// A wrong HashFunc must produce errInvalidSignerOpts.
   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  		// SignDeterministic with nil and &Options{} must agree byte-for-byte.
   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  		// A different Context produces a different deterministic signature
   323  		// and verification with a mismatched context must fail.
   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  		// Context >255 bytes is rejected by the underlying implementation.
   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  		// Tampered signature must not verify.
   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  		// Modified message must not verify against the original signature.
   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  		// Signature from a different key must not verify.
   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  		// Cross-context: μ computed under one ctx must not verify under another.
   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  		// Tampered MLDSAMu signature must not verify.
   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  		// Wrong-length μ must be rejected.
   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  			// Public() returns the same key as PublicKey().
   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  			// Round-trip via NewPrivateKey/NewPublicKey.
   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  	// Distinct keys are not Equal.
   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  	// Cross-parameter mismatch: an MLDSA65 public key encoding is rejected by
   586  	// MLDSA44 (and vice versa), because the lengths differ.
   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 BenchmarkSign(b *testing.B) {
   597  	// Signing works by rejection sampling, which introduces massive variance in
   598  	// individual signing times. To get stable but correct results, we benchmark
   599  	// a series of representative operations, engineered to have the same
   600  	// distribution of rejection counts and reasons as the average case. See also
   601  	// https://words.filippo.io/rsa-keygen-bench/ for a similar approach.
   602  	b.Run("ML-DSA-44", func(b *testing.B) {
   603  		benchmarkSign(b, MLDSA44(), benchmarkMessagesMLDSA44)
   604  	})
   605  	b.Run("ML-DSA-65", func(b *testing.B) {
   606  		benchmarkSign(b, MLDSA65(), benchmarkMessagesMLDSA65)
   607  	})
   608  	b.Run("ML-DSA-87", func(b *testing.B) {
   609  		benchmarkSign(b, MLDSA87(), benchmarkMessagesMLDSA87)
   610  	})
   611  }
   612  
   613  func benchmarkSign(b *testing.B, params Parameters, messages []string) {
   614  	seed := make([]byte, 32)
   615  	priv, err := NewPrivateKey(params, seed)
   616  	if err != nil {
   617  		b.Fatalf("NewPrivateKey: %v", err)
   618  	}
   619  	rand.Shuffle(len(messages), func(i, j int) {
   620  		messages[i], messages[j] = messages[j], messages[i]
   621  	})
   622  	i := 0
   623  	for b.Loop() {
   624  		msg := messages[i]
   625  		if i++; i >= len(messages) {
   626  			i = 0
   627  		}
   628  		priv.SignDeterministic([]byte(msg), nil)
   629  	}
   630  }
   631  
   632  func BenchmarkVerify(b *testing.B) {
   633  	b.Run("ML-DSA-44", func(b *testing.B) {
   634  		benchmarkVerify(b, MLDSA44())
   635  	})
   636  	b.Run("ML-DSA-65", func(b *testing.B) {
   637  		benchmarkVerify(b, MLDSA65())
   638  	})
   639  	b.Run("ML-DSA-87", func(b *testing.B) {
   640  		benchmarkVerify(b, MLDSA87())
   641  	})
   642  }
   643  
   644  func benchmarkVerify(b *testing.B, params Parameters) {
   645  	priv, err := GenerateKey(params)
   646  	if err != nil {
   647  		b.Fatalf("GenerateKey: %v", err)
   648  	}
   649  	msg := make([]byte, 128)
   650  	sig, err := priv.SignDeterministic(msg, &Options{Context: "context"})
   651  	if err != nil {
   652  		b.Fatalf("SignDeterministic: %v", err)
   653  	}
   654  	pub := priv.PublicKey().Bytes()
   655  
   656  	// "Whole" runs both public key parsing and signature verification,
   657  	// since pre-computation can be easily moved between the two, but in practice
   658  	// most uses of verification are for fresh public keys (unlike signing).
   659  	b.Run("Whole", func(b *testing.B) {
   660  		for b.Loop() {
   661  			pk, err := NewPublicKey(params, pub)
   662  			if err != nil {
   663  				b.Fatalf("NewPublicKey: %v", err)
   664  			}
   665  			if err := Verify(pk, msg, sig, &Options{Context: "context"}); err != nil {
   666  				b.Fatalf("Verify: %v", err)
   667  			}
   668  		}
   669  	})
   670  
   671  	// "Precomputed" runs only Verify with a pre-parsed public key.
   672  	b.Run("Precomputed", func(b *testing.B) {
   673  		pk, err := NewPublicKey(params, pub)
   674  		if err != nil {
   675  			b.Fatalf("NewPublicKey: %v", err)
   676  		}
   677  		for b.Loop() {
   678  			if err := Verify(pk, msg, sig, &Options{Context: "context"}); err != nil {
   679  				b.Fatalf("Verify: %v", err)
   680  			}
   681  		}
   682  	})
   683  }
   684  
   685  func BenchmarkKeygen(b *testing.B) {
   686  	b.Run("ML-DSA-44", func(b *testing.B) {
   687  		for b.Loop() {
   688  			NewPrivateKey(MLDSA44(), make([]byte, 32))
   689  		}
   690  	})
   691  	b.Run("ML-DSA-65", func(b *testing.B) {
   692  		for b.Loop() {
   693  			NewPrivateKey(MLDSA65(), make([]byte, 32))
   694  		}
   695  	})
   696  	b.Run("ML-DSA-87", func(b *testing.B) {
   697  		for b.Loop() {
   698  			NewPrivateKey(MLDSA87(), make([]byte, 32))
   699  		}
   700  	})
   701  }
   702  
   703  var benchmarkMessagesMLDSA44 = []string{
   704  	"BUS7IAZWYOZ4JHJQYDWRTJL4V7",
   705  	"MK5HFFNP4TB5S6FM4KUFZSIXPD",
   706  	"DBFETUV4O56J57FXTXTIVCDIAR",
   707  	"I4FCMZ7UNLYAE2VVPKTE5ETXKL",
   708  	"56U76XRPOVFX3AU7MB2JHAP6JX",
   709  	"3ER6UPKIIDGCXLGLPU7KI3ODTN",
   710  	"JPQDX2IL3W5CYAFRZ4XUJOHQ3G",
   711  	"6AJOEI33Z3MLEBVC2Q67AYWK5L",
   712  	"WE3U36HYOPJ72RN3C74F6IOTTJ",
   713  	"NMPF5I3B2BKQG5RK26LMPQECCX",
   714  	"JRGAN2FA6IY7ESFGZ7PVI2RGWA",
   715  	"UIKLF6KNSIUHIIVNRKNUFRNR4W",
   716  	"HA252APFYUWHSZZFKP7CWGIBRY",
   717  	"JFY774TXRITQ6CIR56P2ZOTOL6",
   718  	"ZASYLW5Y3RAOC5NDZ2NCH5A4UY",
   719  	"42X4JXNPXMFRCFAE5AKR7XTFO7",
   720  	"YAHQUWUH534MUI2TYEKQR7VR3A",
   721  	"HBP7FGEXGSOZ5HNOVRGXZJU2KG",
   722  	"HG4O7DCRMYMQXASFLMYQ6NMIXK",
   723  	"2KPQMDZKS65CLJU4DHTMVV5WI3",
   724  	"G6YSUTEX4HHL44ISK2JVVK45BV",
   725  	"PUJGPEQUBQM3IK2EXDQFJ2WGBG",
   726  	"PNS6HMQAWA3RORSMSNEUAINMIR",
   727  	"L35MZS4XYIJK453OFXCZG4WHIK",
   728  	"CRY54YZMFRF6JTB3FPNNBWPUOG",
   729  	"Y25TSZBWGU4HJCRMWZHAWXQ2DN",
   730  	"23W64TW3AKZPKCM4HMKEHFI6VQ",
   731  	"PWQAOZ24B4VLNEQR4XKN7LZHDI",
   732  	"YINPDR3ZSAKPPXP6J6VAXHIPYO",
   733  	"JDBB52ZRAB3PYBPNE7P4COY5PJ",
   734  	"4DYU52LQLVG3LTREOTLBCJK3XC",
   735  	"AB45MV6RKUGPCW4EUK7DX23MJX",
   736  	"HEJSITE5K7J6YJ74OEATVTCERV",
   737  	"ZKI5QCFCGM26UK7F5KYTENXKD2",
   738  	"VH5G3ZLF5XC22QAEJ6JDGOBE5Y",
   739  	"HYGXFHH3JW5SENG26MXLL54IGV",
   740  	"MJUCRL36JZ757UYHBFPCJBPZRH",
   741  	"IBH3T6NAVLCJQBYSVHAQFUITYA",
   742  	"VMWCS7JMIMFQB6TPRAMOUXIKWD",
   743  	"SXRPGPNNW2MMBKQS3HJURIQ3XV",
   744  	"YPPYMJZW6WYXPSCZIPI57NTP5L",
   745  	"N3SH6DUH6UOPU7YMQ6BJJEQSPI",
   746  	"Q243DGA6VC6CW66FFUAB5V3VLB",
   747  	"OUUBXEU4NJBRN5XZJ7YQUPIZLA",
   748  	"H5TWHVGC7FXG6MCKJQURD3RNWG",
   749  	"OONG2ZZ7H3P5BREEEURNJHBBQG",
   750  	"HWROSSRTBCQOAIQAY5S4EQG4FX",
   751  	"AJW6PW62JQNU72VKGIQMPBX64C",
   752  	"OXECVUVAWBBBXGGQGQBTYVEP4S",
   753  	"M5XN6V2LQJDEIN3G4Z6WJO6AVT",
   754  	"NHGJUX3WGRTEIRPFWC2I467ST4",
   755  	"SEOADTJDKAYYLDSC4VAES2CRDJ",
   756  	"J5AT674S577ZFGEURNIAGYOHKW",
   757  	"VJQVNMGHG4ITFX2XSPSDEWVZWD",
   758  	"ZWY3KJPXTAVWWVHNAJDUXZ52TG",
   759  	"HY46PBUGP4EMH34C6Q56MO7CJP",
   760  	"MQTUO7CF6R6CRJPVV6F673M6VW",
   761  	"35Z2Z5KV2RBJPQ7OZ24ZJE6BKR",
   762  	"OVUEVXBLCU2BBY25QP5WJACDIX",
   763  	"LNJX7PCLYL35WYJBW6CTXENPUU",
   764  	"IH7E766LCENOQ5ZKZVCMLEPACU",
   765  	"T2HZFGDDSFQ6YADB52NIFLBFEV",
   766  	"RHQUJMN4MB5SYY4FP4ARZH52QJ",
   767  	"W7GZC5ZM63UF2EJ7OC4WJM3OTH",
   768  	"T2NHNFVOMICY33AQZSR53HXFQ6",
   769  	"7ZVB4Y4K4Y2VAM5NC7HHAJNZIB",
   770  	"UX2I4VF62XJGP2XTNN6LDKXTOH",
   771  	"HJAMJR5RQTQW7JMW7ZLPRBZE7E",
   772  	"HKWSKX7MB5346PHYNWNBAYDSYK",
   773  	"BVWSB75HFLLE45MWA6EPHPTCFR",
   774  	"YDH2J6NMM7UINHGUOPIUI7PSSR",
   775  	"SYQPZLK52HMUAQFMVHGRJYKBEY",
   776  	"7AA6UQFGSPBGNUDPLWXSGNKKPP",
   777  	"AYXRJGRWZ5S3QOEDVWYHHCICHV",
   778  	"KFJYAWO7IATSBCSTDUAA5EPFAN",
   779  	"3JABTLB6T2ICHGVT3HXZZ3OAIT",
   780  	"WCM3IBOCQJ36WSG627CCNK3QA7",
   781  	"5FB5H3BZN2J4RGR2DUW7M37NKZ",
   782  	"VKDDAD3BVOMPSNEDGIRHKX5S6R",
   783  	"LFH5HVUR726OSFD3YVYM3ZHEIH",
   784  	"Y4ETQB2KZVFB4M7SALLCTHX2FB",
   785  	"E6SAU3C25MO2WBBVBKCKP2N4ZE",
   786  	"3JA54Q3NEKURB5EAPL2FOFIESD",
   787  	"FZPBW7BIQIW3FTKQD4TLKNWLMD",
   788  	"LY5W6XFA2ZRI53FTUJYGWZ5RX6",
   789  	"QID236JY3ICR55O5YRED33O7YT",
   790  	"HDRU3L6MFEBCBQFNLF5IRPMOAL",
   791  	"232ANKJBDBG4TSKQ7GJMWTHT23",
   792  	"CDWE3CELZM5AOJGYEFHMUNSP5O",
   793  	"7LNJRBOKN6W7RXUU34MDJ2SNKL",
   794  	"S3IZOADTW2A6E5IGRO5WKX7FVH",
   795  	"ZAISTLXC55EBMTN6KZ6QX5S7OS",
   796  	"4Z5ZIVCMFR2PY2PY4Z47T4YPYA",
   797  	"NE36L53Z6AMYQU7Q5REFUF76MK",
   798  	"WND5UP5M6KWPBRFP5WIWTOWV3I",
   799  	"7OC54DLFWMADJEMKEJ3Y2FMMZS",
   800  	"BWJVZHGEN43ULNIOZCPZOB64HG",
   801  	"VDFPQSR7RE54A75GT4JDZY5JK2",
   802  	"HFCD5EPBZBSVMXIDA47DZ6MRD6",
   803  	"RNBVFIUUJUM7EHRE3VNWSTORGO",
   804  	"VO5NLQJBR22CRRYUETGTU6JLMR",
   805  	"RZOMNFHBTL6HMGWH4PEEDASK7U",
   806  	"QL73UBTOLK5O2TW43YWAIKS6T3",
   807  	"NE3QVSMWS5G3W5C3BMKTJNMI2L",
   808  	"YHI6EYQ4GZMB2QPGHPUG2ZUOEL",
   809  	"6MBATW7MFNRUQBFD3GM35B7YPM",
   810  	"AIYRY6P5T4XU44CGVPEV6W43FR",
   811  	"MIAQ2FHXMAPY5NXSS45VRDPRMG",
   812  	"2SNLHQYKK2K6NSWOF6KPGZ3CPC",
   813  	"RVBHIQO5LH77ZWEAO3SVL72M2V",
   814  	"XXTGJCJNRSNLE7ARAH2UU6LVKR",
   815  	"DQMGILY5IDMWN5OYQYYXH26ZGR",
   816  	"627VTXXMM455KMTFNUUTKNFXPY",
   817  	"HC7IBFGLZCWGUR4K7REPMPW6W4",
   818  	"CHL6JRQUS7D4NML3PFT37PPZAA",
   819  	"Y767HXJAGJ75KE3JLO4DTLQIXC",
   820  	"NTIODXI5I7TF2KXXWXOAYGT7G4",
   821  	"PKZYEK2WAI4D4HEYYZH6H5IOMP",
   822  	"FG6J6G7HZDEDF4JQBQOTC7RQGZ",
   823  	"3VHM2VZU77Y25E3UUYZJLB2QLA",
   824  	"WRZQJQW7ARH4DXYHVLCJ4HRTTB",
   825  	"LQXKV5HD2AZHENSJ2VFLJ5YU5L",
   826  	"MF6Q4OA2EN6TG6BUDK7RWCQNPU",
   827  	"3USKYKPC5CB3EC4ZRMZVE3R2UO",
   828  	"3WICO2GVS3IRBFUHNDLNKWVP7N",
   829  	"P6ZR2UZZOVUZKT4KUS5WICW5XE",
   830  	"PYPZUU76RYVOUZGUUX33HLDKYA",
   831  	"2FTSURHV34VYTVIUU7W6V5C3NK",
   832  	"YABDYMGXS2MD2CYF3S4ALG4FLG",
   833  	"MHIBDH25RRPWV3P4VAWT6SAX3I",
   834  	"OINSMWJQ2UTOOKZ3X6ICXXBQR7",
   835  	"PFTQS7JNU2Q3Q6L4CGBXVLOYNE",
   836  	"A4MZ7CCVYQUDJ2AFHNXBBQ3D24",
   837  	"CPUB5R3ORTCMSMCLUQURE6AN5O",
   838  	"NF5E7U3DFTXWFFXXHUXTEP4VZQ",
   839  	"AWB5WDFERWSSJG53YGJMDORQKR",
   840  	"U5JQUILKD6SEL6LXAMNFZP6VSW",
   841  	"M45NLOAFLO74EJKG5EXNET6J5Y",
   842  	"P2KTEUMZ5DZZMYSPOHDR2WJXAN",
   843  	"KVO7AXZNFBUBPYLOTZQQ42TFNS",
   844  	"WGJJ7SAEV6SBBWWYS4BTLD63WM",
   845  	"Y6GURVDV4ESRBPWSTV25T4PE4K",
   846  	"ESK7MPFPUZ5ZAQ52RP4SQIYCCC",
   847  	"623M3CIABZ3RANERQ2IREXAVYO",
   848  	"OQ4CQCFO42RS4BMMSGSDLUTOQO",
   849  	"AMFHRDVGM6G2TIR3TKIFGFSDVM",
   850  	"7VVSGGCVC53PLOYG7YHPFUJM5X",
   851  	"Z3HMESVL7EZUSZNZ33WXEBHA2N",
   852  	"AWWVRQD5W7IBSQPS26XOJVDV5H",
   853  	"OQBZ5ZST3U3NZYHSIWRNROIG6L",
   854  	"II573BW7DJLBYJSPSYIABQWDZD",
   855  	"MOKXOQFOCUCLQQH4UKH2DPE7VN",
   856  	"XR54NGUOU6BBUUTINNWBPJ35HX",
   857  	"DNK36COZGFXI6DY7WLCNUETIRT",
   858  	"R5M2PV7E3EHEM3TLGRCL3HSFMC",
   859  	"ITKENZQYDQMZFCUPOT7VF3BMU7",
   860  	"5GDCB74PPPHEP5N5G3DVRCYT7R",
   861  	"ZMKXVRPLI5PY5BDVEPOA3NQZGN",
   862  	"GBLIALWTHTUDTOMDERQFVB77CS",
   863  	"VKRTTXUTFOK4PJAQQZCCT7TV3T",
   864  	"ZJBUJJ4SW62BXOID3XO2W2M2PF",
   865  	"SKWT5T6QJTCD3FCINIK22KMVBJ",
   866  	"EHINNU6L33HRLOOJ3A2XFJSYQL",
   867  	"N4HRQJEFPAT5SU3YPO74WSMQIR",
   868  	"TGPTZ3ENMFWB5CZKJFR5WHIRI4",
   869  	"O4HNFTAUJJ2LZPQXPXRAXOVABA",
   870  	"4JVB5STP2YG5GYOXDWIF4KCKFB",
   871  	"MY554X3YZHBECLHNNZ7A3SPJTU",
   872  	"ASCJMAH7VCQAD2QJSWXPSVSM3H",
   873  	"NBNGL5DZ623KCG2JNZFGZMZ7KD",
   874  	"KGMZSW35AEQOJ6FA7IR7BHZI52",
   875  	"Q7QUHHS4OJFMJ4I3FY6TDKSMZQ",
   876  	"MZAE7TOEXAS76T7KIC73FEYRU4",
   877  	"2BVESR3REAWADCGYOYM7T646RG",
   878  	"EK3L2ORP4LT3HU3EMXDSQWFOKJ",
   879  	"3X4A6VMGMIDLVK72FZSDHSERWY",
   880  	"I3UHWI6M6HQFRBSQ6W2SABUNUP",
   881  	"REKPXW4DIB4MTKMPHN3RBVHVME",
   882  	"W37FNFZE35NX65Z7CVQ7L5U4L5",
   883  	"4AGYK6U2KP6RAOADCBUDDCBECV",
   884  	"IXM4SFQUDW2NOTXZIPWTNGET3F",
   885  	"6YE4G3VELF27MN3Z5B4VIQ3XYK",
   886  	"LPOZCPZAG3MD47MIWGR4FIOCDH",
   887  	"WGREKUL2LD7C7SYGKH7APIY2A6",
   888  	"WWW277FKTKUXQMP4BECSRHLWJI",
   889  	"UYE4IQPMSTXVQG7EJALKWWEGDN",
   890  	"TIV2L5Z6K7SNGNUVWSNKTAF4UE",
   891  	"I3FQOAW3PINUK26P62HCX657FO",
   892  }
   893  
   894  var benchmarkMessagesMLDSA65 = []string{
   895  	"NDGEUBUDWGRJJ3A4UNZZQOEKNL",
   896  	"ACGYQUXN4POOFUENCLNCIPHFAZ",
   897  	"Z3XETEYKROVJH7SIHOIAYCTO42",
   898  	"DXWCVCEFULV7XHRWHJWSEXWES7",
   899  	"BCR2D5PNLGFYX6B3QFQFV23JZP",
   900  	"2DVP5HNG54ES64QK4D37PWUYTJ",
   901  	"UJM4ADPJLURAIQH4XA6QYUGNJ6",
   902  	"B5WRCIPK5IVZW52R6TJOKNPKZH",
   903  	"7QNL6JTSP62IGX6RCM2NHRMTKK",
   904  	"EJSZQYLM7G7AJCGIEVBV2UW7NN",
   905  	"UFNA2NKJ3QFWNHHL5CXZ4R5H46",
   906  	"QZAXRTT3E4DOGVTJCOTBG3WXQV",
   907  	"KH2ETOYZO5UHIHIKATWJMUVG27",
   908  	"V5HVVQTOWRXZ2PB4XWXSEKXUN5",
   909  	"5LA7NAFI2LESMH533XY45QVCQW",
   910  	"SMF4TWPTMJA2Z4F4OVETTLVRAY",
   911  	"FWZ5OJAFMLTQRREPYF4VDRPPGI",
   912  	"OK3QMNO3OZSKSR6Q4BFVOVRWTH",
   913  	"NQOVN6F6AOBOEGMJTVMF67KTIJ",
   914  	"CCLC4Y6YT3AQ3HGT2QNSYAUGNV",
   915  	"CAZJHCHBUYQ6OKZ7DMWMDDLIZQ",
   916  	"LVW5XDTHPKOW5D452SYD7AFO6Q",
   917  	"EYA6O6FTYPC6TRKZPRPX5N2KQ4",
   918  	"Z6SGAEZ2SAAZHPQO7GL7CUMBAG",
   919  	"FKUCKW6JQVF4WQYXUSXYZQMAVY",
   920  	"LN2KDF4DANPE4SC4GKJ4BES3IZ",
   921  	"AVCRTWB6ALOQHY34XI7NTMP2JH",
   922  	"A5WHIS6CBWPCYIEC6N2MBAOEZ6",
   923  	"JC2BH476BXUQFIDA6UCR5V4G4F",
   924  	"NU6XH6VLSSFHVSRZCYXPFYKYCD",
   925  	"GSUXVZBDDYSZYFGXNP6AZW3PTC",
   926  	"XJPRNJ26XP4MIYH2Q7M7MPZ73M",
   927  	"INUTUP3IRFWIIT23DNFTIYKCFY",
   928  	"T4KH7HKLEYGXHBIRFGFCRUZCC4",
   929  	"GGQX4JFVWZHE5Y73YTLMSSOXNS",
   930  	"BUA4Q3TQZGLVHMMJU62GQOSHLV",
   931  	"WXW3SJXLSZO2MYF4YFIMXL2IQP",
   932  	"Q32XBVVGFQTSXAIDJE6XSEPRZG",
   933  	"6TEXT6SA7INRCTDSCSVZJEQ2YG",
   934  	"ZBN4UL43C3SJIG4HYR236PXCVS",
   935  	"TVWPLLC7NROBREWOM75VA3XCR3",
   936  	"CCDGL2FURLBABQ4IJBYCB75JFR",
   937  	"XBZGCOVTZHCPAARBTMAKPIE6GJ",
   938  	"TPRAENJ7I54XRIVH6LL6FDIA3I",
   939  	"RKOM3PHFILPIIQZL4ILQWGRYWI",
   940  	"CEEZIZ2WUXHQQFATYYGQ3ZDBTI",
   941  	"SLKOVAP6WLIVJBVU7VZG3ZGEOW",
   942  	"TWMCLJJSWEEQQPQGGDKEJ5SU2R",
   943  	"IFMUXXCD2LC7IGQLZ2QEK5UOQ2",
   944  	"C7IWFEBHW2CXN4XBJS7VLWH3VK",
   945  	"7KJYUEW3F264727TM4LE6RMGDO",
   946  	"BPG2XAPBMBTA4VMPUM7IZVZPK3",
   947  	"Y5X577BWRZNPLNUHJVSKGMUXYB",
   948  	"ZCKMKM23E4IUPTNQDFN2LTLZVX",
   949  	"4RKK223JNBDAP4G5DOAHHZ3VNO",
   950  	"5UZ3TQZHZT22ISTB4WJEVO6MC4",
   951  	"YMVS4HFSJ32CRZRL23PXZUEJFJ",
   952  	"UQEUJUTPSZLZARNBXWMCTMHPFF",
   953  	"CZAAZ5WK7EIPMW7NA3EZNNBF45",
   954  	"227PBHH23WM7F2QLEZSPFYXVW4",
   955  	"YUYS2J5CRFXZ4J4KJT2ZKIZVW3",
   956  	"MFLHZJOZV44SN4AH6OJ3QZWM2O",
   957  	"H2B3CRBCXYN7QWDGYUPHQZP23A",
   958  	"T4L6YWQUQ3CTACENAJ5WUXZWFH",
   959  	"N723H6MUGPZSRZ72C635OD4BP7",
   960  	"NI4TUMVA6LQPQV2TXPN4QOIGBZ",
   961  	"CQI3S4LSTQASSJJVZXEFPOVW7K",
   962  	"ANPY4HJ64LLSB3GK2R4C6WDBS3",
   963  	"RGWQCZKQLMT5FZRDE4B3VMASVK",
   964  	"Q3WCCF2HA3CA4WWRJBMGBW7WI7",
   965  	"2AKJRXFHXLUQPOXPTLSZN5PW4A",
   966  	"IJWOOTI4N7RWXJIHAPXN6KEWEN",
   967  	"4D53T6N6ATOVTD4LKSTAAWBJMU",
   968  	"B4G5HDD6RITG6NIH6FXCRZDYZM",
   969  	"TJCDFKMRUY2OG6KRSMNVCGQFUP",
   970  	"PB33IHQKALAY6H6GVBVLI6ZRXK",
   971  	"SCCWGW2J5S4WL4FTTMQ435F6DB",
   972  	"ZVJH2HSMTLHGXMGPMXLJCKCLLE",
   973  	"62LG37U6JXR77YRZQQCDSBHVCS",
   974  	"BU4CBWOXQ352TEOKIXO245ID4O",
   975  	"UEZOH7KEIODSEVRUF6GMWGA2RB",
   976  	"IPJWROME4GM66CGLUWP5BJ4SX6",
   977  	"355GDC7TG64AZJ7IJX6K62KZCZ",
   978  	"AHTFKX3V7XUB3EWOMQVCGZYGUE",
   979  	"N4RV2GKXJ4SPHHJ52Z7K5EGLER",
   980  	"ZY7V7NE5F66XHDHWM6YNFEWZA6",
   981  	"DIKFO5KAVT4WAP7BOEFM56ZUSR",
   982  	"4TDFOFKDAPIOM3MU5GD7NPXNWQ",
   983  	"AD7YZO756HDK6YWFILAKW3JWA7",
   984  	"NUA53JS2ZK2BGHH3A7BJTJZYW7",
   985  	"QLCNC3AQNKLRMSYR62WQSQP5VI",
   986  	"SJ7OBS7ZYXSGXOYXPE5KW2XKN6",
   987  	"44HBMOGMIMJS63CEXQU7FCXE2E",
   988  	"KCK3J7ZL6QF4SLHHSWTJURK7PG",
   989  	"HLH4CLUGBSOOBSS3BPO62N5MC3",
   990  	"3FNS4GITO6OEUBAVDDXK4WOBTD",
   991  	"IAC3K3I4AQGY3G6UHG7PL2N6TE",
   992  	"KUKLNH74POJI5DYAEWUD7RABTQ",
   993  	"ETM6N7VU3GBSQ7P5MCD6UF3E3S",
   994  	"IZITM5NYBGJZLSI3BI4VEMW43U",
   995  	"46OPQU4LL6N3Z2U7KYPKUMBAGI",
   996  	"EV7YZ5DMAV7VKYJQUFSRD37GPP",
   997  	"AV7W2PGYDJIAKLFVEBL6BXQSGC",
   998  	"M2FOX5QZEZKV4QXKPI5XUZDHEM",
   999  	"R4IFPLVMOVYCHRTR6LXAUGP3LL",
  1000  	"JGH6XJUMP4DRVAM27P2JNOKXVO",
  1001  	"D2XN3ZLLU6VFPMDYM7NBHSQEOI",
  1002  	"2PO3BYENOMQK6SHQDCFSRPJQI3",
  1003  	"IBVQ7U3QEUC6PQRE4PV53JTZTK",
  1004  	"ZBCOX4P7NG2IXXFB2R43MG2SLV",
  1005  	"5NJDPQVVDO7ADNZ2CV7L6QBNGZ",
  1006  	"V7ASFIIYUMXFGW4B7ZM6LOGUTE",
  1007  	"PX5IJZ7W2LUPKM6YN4PMZ43ZLM",
  1008  	"AYK7SZ23DHC7Q56MWAJXBG76LB",
  1009  	"UYCAPXJM4HNGKLIDSZ4NCEDJLN",
  1010  	"UWMDZ3C2ODLACKGJPGETNQ3TA4",
  1011  	"Q6OI6R3WYYJ4CCZCDJBQMCRCZR",
  1012  	"LCMJHLP7354APCEGPKE7HHWTWB",
  1013  	"N7T7ZKOYPAMEYTTDOWZNCN6PRD",
  1014  	"UZADPU4UNHAF7L7LQDMTKA2EQH",
  1015  	"DC2OEPQDECVLRVNNCS6BMH4CRA",
  1016  	"37IZ427XHUMZ66EJ62U2YEZDAC",
  1017  	"6BCZDQZDPZLS5OGESKNUBPSSFV",
  1018  	"ST2LEMJ4OLQ32TJTLH2WCWT4WA",
  1019  	"GA2TL4SFLEW4G2B5PQMIKJT5XG",
  1020  	"L7PPBIET26EH7LQTLEFC4I4EIA",
  1021  	"6YSM7MC2W4DEV6ULAHMX27LH56",
  1022  	"QL26Z5KZ4YRRG2BXXGDRRLV357",
  1023  	"677TWRAJ5NSNHCE243POQPEG7K",
  1024  	"66MEBQJLGAGVXDX3KZ2YFTTVJM",
  1025  	"6D4VUWAQD6R65ICSDLFAATC67V",
  1026  	"7GXLD5CNU3TDUQSSW42SHL7B5D",
  1027  	"RQETUMEBG2ZM2NF2EZAQHGHWWE",
  1028  	"DCRX5ANWDMXZFIDVAXYLQZYMRN",
  1029  	"5SDWT7YAF7L4WWANAGYINZAYXH",
  1030  	"PZILRV7I2S6WKUSHKYRLA2JQY3",
  1031  	"2G66TK2PZ5MOTAZDN7BFS3LAIH",
  1032  	"QOLJ3WGJ6JS3FMMXBNTNAIKXVK",
  1033  	"FMAL67YTHDCCYVZ5CRMN2XJPDN",
  1034  	"UOTZDXTJKQ3YAIRKHTYNX6G55P",
  1035  	"X3DLNPJ3V62LRHGEY4DTT35H3R",
  1036  	"DKU7CHNXPB5QRZVGIQZW46XCKC",
  1037  	"RAKBD4LQKEDTVDSK3DVTRWG23B",
  1038  	"INTRA7BWHLVQMBRKBJNUSMF7MU",
  1039  	"AUYRBNVCOYYHOHUYOOFIZ2FWMD",
  1040  	"22EJVDEQ7PASLBAMTVKXOQP5RJ",
  1041  	"3S6NATWA57SFTZEW7UZUOUYAEU",
  1042  }
  1043  
  1044  var benchmarkMessagesMLDSA87 = []string{
  1045  	"LQQPGPNUME6QDNDTQTS4BA7I7M",
  1046  	"PTYEEJ7RMI6MXNN6PZH222Y6QI",
  1047  	"R6DTHAADKNMEADDK5ECPNOTOAT",
  1048  	"S2QM7VDC6UKRQNRETZMNAZ6SJT",
  1049  	"EYULPTSJORQJCNYNYVHDFN4N3F",
  1050  	"YETZNHZ75SXFU672VQ5WXYEPV2",
  1051  	"KTSND3JGA4AN3PCMG4455JEXGR",
  1052  	"JGE6HK37O6XMWZQZCHFUPNUEXP",
  1053  	"CRYB2FZD2BYNANBFFO2HRZEHGZ",
  1054  	"7MLNDZJ7OIEPBJZOMULOMQH2BA",
  1055  	"4WQCNTIFVSX2DNALMWUKZRA6CI",
  1056  	"Y5NK4OBDSDWC5WLL27CEEXYYOT",
  1057  	"C4SSWSPBVCDAWJXH2CDMXR36LH",
  1058  	"THDBKXRTKWJUGJMAAYTWTFMX7Z",
  1059  	"NWXPUD4DAA6QOREW4AFFYQYQNG",
  1060  	"3RQIJXMO7WYHBEBL3G6EOLNZNQ",
  1061  	"R7JEOHFP2C7O4AVPRPRELXWOMM",
  1062  	"LU6MWR7SZXVIKS54BY62X67NPA",
  1063  	"FG2FFM4F2ECKHCSJ75KXK632JP",
  1064  	"BF76ZDSVVUSYS5KK4FFD22YPS7",
  1065  	"HCLBWZRLHEMYZLFWHLAN2BKCZ7",
  1066  	"HGFVS4QC7AWXYPVRSWAK77KTQF",
  1067  	"LUZ3C53PUUHBWCDJ7WAHK2UT3K",
  1068  	"Y3WR6SMDUBW34N3MUT7EQYIJCV",
  1069  	"F2X35AQTXVZBMPXTWNAAH4ZX2W",
  1070  	"6MKFFDYWD6ZAKS3C6GRCRLZLRF",
  1071  	"AFMZYYFRHKMQRNKU5UTSKQ74H6",
  1072  	"TDTN7J3O367OVPWLESRNPLN4M2",
  1073  	"WYMLD2X6N4CZ2RDOKF5CFTSYTG",
  1074  	"UNPTSBLJ6HZRNR72T2VEEHCFX2",
  1075  	"SNCM4R2P27AJOXBS67RMCARS3U",
  1076  	"OU7QBE5QOXO7CIYTBJR3KOW2WK",
  1077  	"2NNQOBQKZ2OD4ZAXI3SNEURYUP",
  1078  	"YQTUPOYBT67XPCHIGKSGSKC3BZ",
  1079  	"HGB4ZM3G76IXYWWCMVT3HONRIS",
  1080  	"WZC6QUKRZZ2TOVA277JYKQITEW",
  1081  	"XO2WT46A5HYL6CUJF7SGJ6YWOG",
  1082  	"4QJA35PMYQIDRZ7ZHG7RLZJVGF",
  1083  	"BMJZELWZ4I2UWXESU3NR6ATC4M",
  1084  	"XWLFB7FN6D5PRY6YUXC5JUIBFM",
  1085  	"WRAFFF27AVTIOYIBYA2IPTXI3R",
  1086  	"VOXUTYTN2XZ362OJFO2R53UCUF",
  1087  	"UHN73ARJ737WUJ6QYEI7U46OPO",
  1088  	"3Y3K5E2A4ML3VYVNAFWEEIXTSN",
  1089  	"QMU4322NKPRLE7JBGYFGS36H2S",
  1090  	"NJAQTNCXPVDICTDVUKTPRCD2AX",
  1091  	"OC373ZFBNV2H46T6OY3XRPSUHG",
  1092  	"UBLAS6CDWE3A662MLKP7QDEOCC",
  1093  	"BKFDLAL2RTPMERYVW3B7UJ5W3H",
  1094  	"QFKFGXKGW5SAKLBAWQXUWW77OS",
  1095  	"EJNUQHTLLOVB4ARETOGLY4WUTJ",
  1096  	"N243OCMVLLAO6I2XLCYOIMQYGY",
  1097  	"YRRFLWK7ZASUKYX7ZLQMW2PJ6X",
  1098  	"3DGVPBWD2BIK6KQE65K72DNJNM",
  1099  	"TJRYMNOAIW33VIHKLJG4GXAVUK",
  1100  	"6DSRINAYXL34U54U355U7IVFGS",
  1101  	"6CHA4MX7LVS77XKRWG7IYC3XVL",
  1102  	"GM2CEGBEPBOHAPIOBUWJ4MJNTG",
  1103  	"VJKHGBY33VUIJFEQLX3JVUNQBD",
  1104  	"DTOHAD5M2KL46IZHE4TPLJWHTI",
  1105  	"IYFG3UDN7ROOY2ZFSLM2BU2LMQ",
  1106  	"A5OGJHPOE4PW6QSZYHZ5TKPGIC",
  1107  	"FX4BCN67AEGCLUTLFPNDL3SQU5",
  1108  	"MWIZQVOZOHTTBUXC3BEX62MNI5",
  1109  	"BYHVJHBLK4O6LFSKEIQ3CAAKU7",
  1110  	"QJU7P6KWSSKAA5GVA6RH4OV7MX",
  1111  	"I3T3XM5Z5TAJHAYDQHFA2ZV7PU",
  1112  	"L46MQCHV3TJ6FYIQQ2FCJXES74",
  1113  	"QXZRQIYAJMXYR6PU3VDYGCIT5W",
  1114  	"MFS53RR2XEYS22NYOJLGTHVTTM",
  1115  	"FRWIWJRP4AQMXWX4WJ4WYVKM3E",
  1116  	"X6GK6IGVLJWYSHLKHGXSW3TJDP",
  1117  	"L5LPJ2HIWA4UY6G6FMZXGDEDAM",
  1118  	"GD6FYOYUGDHXEQ5S2KLJEGNSN7",
  1119  	"ODAL7ZRKXSPAAN5DVRBWJQCFQX",
  1120  	"CV3QFBDXBPT3SCPJGUYSMDN6ZS",
  1121  	"IGSLSACRZ6XID466KQIB4YNGYO",
  1122  	"WZ2EACBN26RAML2S52YXRYP2OF",
  1123  	"LB76VEVNOBYFMKFZ7SDFCBCHQE",
  1124  	"TLFA7EU3JJFAP6EMUKNV2ZXRBM",
  1125  	"SIIJF6OXAKRP25CBUYFBRCDDVP",
  1126  	"TEPNI7TJ7HASJWIQMBS4VFLRQC",
  1127  	"VK2JINYWEDV7IQFWH4OTAD4W5O",
  1128  	"GILUH5AMVE4TM7EKPXJBZGT6EJ",
  1129  	"DV7ALFRAW3TI4WMQQLDTO6RNHN",
  1130  	"CAIB5G3NXC5ASPLFIWAFPVHS5B",
  1131  	"MLFJXZUOAGN7EGPMXOOVTB2CL4",
  1132  	"6MZYT3ANWHBOS67WGHZI3QPEAP",
  1133  	"LVJDQB52C2PERSSQJRMRCJ4UBF",
  1134  	"QY4VKAZAYQIZOX2L2VO2QHAQVC",
  1135  	"UAA5SST2XA76JPKM3XOZ5RUHFI",
  1136  	"VLZWF53JSQ6SCRUFDKVPXWAS4L",
  1137  	"NX2DZIKMJIYXUNSAHFP23FHTBU",
  1138  	"F5OAKDDDA34A2RPIKDPM5CYPMZ",
  1139  	"E5PEP3ANIK2L4VLOST4NIYNKBD",
  1140  	"IPBGFLHSMP4UFXF6XJX42T6CAL",
  1141  	"XHPU7DBFTZB2TX5K34AD6DJTK3",
  1142  	"2ZU7EJN2DG2UMT6HX5KGS2RFT6",
  1143  	"SD5S7U34WSE4GBPKVDUDZLBIEH",
  1144  	"WZFFL3BTQAV4VQMSAGCS45SGG3",
  1145  	"QE7ZT2LI4CA5DLSVMHV6CP3E3V",
  1146  	"YIWMS6AS72Z5N2ALZNFGCYC5QL",
  1147  	"A4QJ5FNY54THAKBOB65K2JBIV7",
  1148  	"6LORQGA3QO7TNADHEIINQZEE26",
  1149  	"5V45M6RAKOZDMONYY4DIH3ZBL2",
  1150  	"SVP7UYIZ5RTLWRKFLCWHAQV3Y2",
  1151  	"C2UYQL2BBE4VLUJ3IFNFMHAN7O",
  1152  	"P4DS44LGP2ERZB3OB7JISQKBXA",
  1153  	"A6B4O5MWALOEHLILSVDOIXHQ4Z",
  1154  	"DKQJTW5QF7KDZA3IR4X5R5F3CG",
  1155  	"H6QFQX2C2QTH3YKEOO57SQS23J",
  1156  	"DIF373ML2RWZMEOIVUHFXKUG7O",
  1157  	"Z5PPIA3GJ74QXFFCOSUAQMN5YN",
  1158  	"PM6XIDECSS5S77UXMB55VZHZSE",
  1159  }
  1160  

View as plain text