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 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  	// Signing works by rejection sampling, which introduces massive variance in
   746  	// individual signing times. To get stable but correct results, we benchmark
   747  	// a series of representative operations, engineered to have the same
   748  	// distribution of rejection counts and reasons as the average case. See also
   749  	// https://words.filippo.io/rsa-keygen-bench/ for a similar approach.
   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  	// "Whole" runs both public key parsing and signature verification,
   805  	// since pre-computation can be easily moved between the two, but in practice
   806  	// most uses of verification are for fresh public keys (unlike signing).
   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  	// "Precomputed" runs only Verify with a pre-parsed public key.
   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