Source file src/crypto/internal/fips140test/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 fipstest
     8  
     9  import (
    10  	"crypto/internal/cryptotest"
    11  	"crypto/internal/fips140"
    12  	. "crypto/internal/fips140/mldsa"
    13  	"crypto/internal/fips140/sha3"
    14  	"encoding/hex"
    15  	"flag"
    16  	"math/rand"
    17  	"testing"
    18  )
    19  
    20  var sixtyMillionFlag = flag.Bool("60million", false, "run 60M-iterations accumulated test")
    21  
    22  // TestMLDSAAccumulated accumulates 10k (or 100, or 60M) random vectors and checks
    23  // the hash of the result, to avoid checking in megabytes of test vectors.
    24  //
    25  // 60M in particular is enough to give a 99.9% chance of hitting every value in
    26  // the base field.
    27  //
    28  //	1-((q-1)/q)^60000000 ~= 0.9992
    29  //
    30  // If setting -60million, remember to also set -timeout 0.
    31  func TestMLDSAAccumulated(t *testing.T) {
    32  	t.Run("ML-DSA-44/100", func(t *testing.T) {
    33  		testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 100,
    34  			"d51148e1f9f4fa1a723a6cf42e25f2a99eb5c1b378b3d2dbbd561b1203beeae4")
    35  	})
    36  	t.Run("ML-DSA-65/100", func(t *testing.T) {
    37  		testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 100,
    38  			"8358a1843220194417cadbc2651295cd8fc65125b5a5c1a239a16dc8b57ca199")
    39  	})
    40  	t.Run("ML-DSA-87/100", func(t *testing.T) {
    41  		testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 100,
    42  			"8c3ad714777622b8f21ce31bb35f71394f23bc0fcf3c78ace5d608990f3b061b")
    43  	})
    44  	if !testing.Short() {
    45  		t.Run("ML-DSA-44/10k", func(t *testing.T) {
    46  			t.Parallel()
    47  			testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 10000,
    48  				"e7fd21f6a59bcba60d65adc44404bb29a7c00e5d8d3ec06a732c00a306a7d143")
    49  		})
    50  		t.Run("ML-DSA-65/10k", func(t *testing.T) {
    51  			t.Parallel()
    52  			testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 10000,
    53  				"5ff5e196f0b830c3b10a9eb5358e7c98a3a20136cb677f3ae3b90175c3ace329")
    54  		})
    55  		t.Run("ML-DSA-87/10k", func(t *testing.T) {
    56  			t.Parallel()
    57  			testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 10000,
    58  				"80a8cf39317f7d0be0e24972c51ac152bd2a3e09bc0c32ce29dd82c4e7385e60")
    59  		})
    60  	}
    61  	if *sixtyMillionFlag {
    62  		t.Run("ML-DSA-44/60M", func(t *testing.T) {
    63  			t.Parallel()
    64  			testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 60000000,
    65  				"080b48049257f5cd30dee17d6aa393d6c42fe52a29099df84a460ebaf4b02330")
    66  		})
    67  		t.Run("ML-DSA-65/60M", func(t *testing.T) {
    68  			t.Parallel()
    69  			testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 60000000,
    70  				"0af0165db2b180f7a83dbecad1ccb758b9c2d834b7f801fc49dd572a9d4b1e83")
    71  		})
    72  		t.Run("ML-DSA-87/60M", func(t *testing.T) {
    73  			t.Parallel()
    74  			testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 60000000,
    75  				"011166e9d5032c9bdc5c9bbb5dbb6c86df1c3d9bf3570b65ebae942dd9830057")
    76  		})
    77  	}
    78  }
    79  
    80  func testMLDSAAccumulated(t *testing.T, newPrivateKey func([]byte) (*PrivateKey, error), newPublicKey func([]byte) (*PublicKey, error), n int, expected string) {
    81  	s := sha3.NewShake128()
    82  	o := sha3.NewShake128()
    83  	seed := make([]byte, PrivateKeySize)
    84  	msg := make([]byte, 0)
    85  
    86  	for i := 0; i < n; i++ {
    87  		s.Read(seed)
    88  		dk, err := newPrivateKey(seed)
    89  		if err != nil {
    90  			t.Fatalf("NewPrivateKey: %v", err)
    91  		}
    92  		pk := dk.PublicKey().Bytes()
    93  		o.Write(pk)
    94  		sig, err := SignDeterministic(dk, msg, "")
    95  		if err != nil {
    96  			t.Fatalf("SignDeterministic: %v", err)
    97  		}
    98  		o.Write(sig)
    99  		pub, err := newPublicKey(pk)
   100  		if err != nil {
   101  			t.Fatalf("NewPublicKey: %v", err)
   102  		}
   103  		if *pub != *dk.PublicKey() {
   104  			t.Fatalf("public key mismatch")
   105  		}
   106  		if err := Verify(dk.PublicKey(), msg, sig, ""); err != nil {
   107  			t.Fatalf("Verify: %v", err)
   108  		}
   109  	}
   110  
   111  	got := hex.EncodeToString(o.Sum(nil))
   112  	if got != expected {
   113  		t.Errorf("got %s, expected %s", got, expected)
   114  	}
   115  }
   116  
   117  func TestMLDSAGenerateKey(t *testing.T) {
   118  	t.Run("ML-DSA-44", func(t *testing.T) {
   119  		testMLDSAGenerateKey(t, GenerateKey44, NewPrivateKey44)
   120  	})
   121  	t.Run("ML-DSA-65", func(t *testing.T) {
   122  		testMLDSAGenerateKey(t, GenerateKey65, NewPrivateKey65)
   123  	})
   124  	t.Run("ML-DSA-87", func(t *testing.T) {
   125  		testMLDSAGenerateKey(t, GenerateKey87, NewPrivateKey87)
   126  	})
   127  }
   128  
   129  func testMLDSAGenerateKey(t *testing.T, generateKey func() *PrivateKey, newPrivateKey func([]byte) (*PrivateKey, error)) {
   130  	k1 := generateKey()
   131  	k2 := generateKey()
   132  	if k1.Equal(k2) {
   133  		t.Errorf("two generated keys are equal")
   134  	}
   135  	k1x, err := newPrivateKey(k1.Bytes())
   136  	if err != nil {
   137  		t.Fatalf("NewPrivateKey: %v", err)
   138  	}
   139  	if !k1.Equal(k1x) {
   140  		t.Errorf("generated key and re-parsed key are not equal")
   141  	}
   142  }
   143  
   144  func TestMLDSAAllocations(t *testing.T) {
   145  	// We allocate the PrivateKey (k and kk) and PublicKey (pk) structs and the
   146  	// public key (pkBytes) and signature (sig) byte slices on the heap. They
   147  	// are all large and for the byte slices variable-length. Still, check we
   148  	// are not slipping more allocations in.
   149  	var expected float64 = 5
   150  	if fips140.Enabled {
   151  		// The PCT does a sign/verify cycle, which allocates a signature slice.
   152  		expected += 1
   153  	}
   154  	cryptotest.SkipTestAllocations(t)
   155  	if allocs := testing.AllocsPerRun(100, func() {
   156  		k := GenerateKey44()
   157  		seed := k.Bytes()
   158  		kk, err := NewPrivateKey44(seed)
   159  		if err != nil {
   160  			t.Fatalf("NewPrivateKey44: %v", err)
   161  		}
   162  		if !k.Equal(kk) {
   163  			t.Fatalf("keys not equal")
   164  		}
   165  		pkBytes := k.PublicKey().Bytes()
   166  		pk, err := NewPublicKey44(pkBytes)
   167  		if err != nil {
   168  			t.Fatalf("NewPublicKey44: %v", err)
   169  		}
   170  		message := []byte("Hello, world!")
   171  		context := "test"
   172  		sig, err := Sign(k, message, context)
   173  		if err != nil {
   174  			t.Fatalf("Sign: %v", err)
   175  		}
   176  		if err := Verify(pk, message, sig, context); err != nil {
   177  			t.Fatalf("Verify: %v", err)
   178  		}
   179  	}); allocs > expected {
   180  		t.Errorf("expected %0.0f allocations, got %0.1f", expected, allocs)
   181  	}
   182  }
   183  
   184  func BenchmarkMLDSASign(b *testing.B) {
   185  	// Signing works by rejection sampling, which introduces massive variance in
   186  	// individual signing times. To get stable but correct results, we benchmark
   187  	// a series of representative operations, engineered to have the same
   188  	// distribution of rejection counts and reasons as the average case. See also
   189  	// https://words.filippo.io/rsa-keygen-bench/ for a similar approach.
   190  	b.Run("ML-DSA-44", func(b *testing.B) {
   191  		benchmarkMLDSASign(b, NewPrivateKey44, benchmarkMessagesMLDSA44)
   192  	})
   193  	b.Run("ML-DSA-65", func(b *testing.B) {
   194  		benchmarkMLDSASign(b, NewPrivateKey65, benchmarkMessagesMLDSA65)
   195  	})
   196  	b.Run("ML-DSA-87", func(b *testing.B) {
   197  		benchmarkMLDSASign(b, NewPrivateKey87, benchmarkMessagesMLDSA87)
   198  	})
   199  }
   200  
   201  func benchmarkMLDSASign(b *testing.B, newPrivateKey func([]byte) (*PrivateKey, error), messages []string) {
   202  	seed := make([]byte, 32)
   203  	priv, err := newPrivateKey(seed)
   204  	if err != nil {
   205  		b.Fatalf("NewPrivateKey: %v", err)
   206  	}
   207  	rand.Shuffle(len(messages), func(i, j int) {
   208  		messages[i], messages[j] = messages[j], messages[i]
   209  	})
   210  	i := 0
   211  	for b.Loop() {
   212  		msg := messages[i]
   213  		if i++; i >= len(messages) {
   214  			i = 0
   215  		}
   216  		SignDeterministic(priv, []byte(msg), "")
   217  	}
   218  }
   219  
   220  // BenchmarkMLDSAVerify runs both public key parsing and signature verification,
   221  // since pre-computation can be easily moved between the two, but in practice
   222  // most uses of verification are for fresh public keys (unlike signing).
   223  func BenchmarkMLDSAVerify(b *testing.B) {
   224  	b.Run("ML-DSA-44", func(b *testing.B) {
   225  		benchmarkMLDSAVerify(b, GenerateKey44, NewPublicKey44)
   226  	})
   227  	b.Run("ML-DSA-65", func(b *testing.B) {
   228  		benchmarkMLDSAVerify(b, GenerateKey65, NewPublicKey65)
   229  	})
   230  	b.Run("ML-DSA-87", func(b *testing.B) {
   231  		benchmarkMLDSAVerify(b, GenerateKey87, NewPublicKey87)
   232  	})
   233  }
   234  
   235  func benchmarkMLDSAVerify(b *testing.B, generateKey func() *PrivateKey, newPublicKey func([]byte) (*PublicKey, error)) {
   236  	priv := generateKey()
   237  	msg := make([]byte, 128)
   238  	sig, err := SignDeterministic(priv, msg, "context")
   239  	if err != nil {
   240  		b.Fatalf("SignDeterministic: %v", err)
   241  	}
   242  	pub := priv.PublicKey().Bytes()
   243  	for b.Loop() {
   244  		pk, err := newPublicKey(pub)
   245  		if err != nil {
   246  			b.Fatalf("NewPublicKey: %v", err)
   247  		}
   248  		if err := Verify(pk, msg, sig, "context"); err != nil {
   249  			b.Fatalf("Verify: %v", err)
   250  		}
   251  	}
   252  }
   253  
   254  func BenchmarkMLDSAKeygen(b *testing.B) {
   255  	b.Run("ML-DSA-44", func(b *testing.B) {
   256  		for b.Loop() {
   257  			NewPrivateKey44(make([]byte, 32))
   258  		}
   259  	})
   260  	b.Run("ML-DSA-65", func(b *testing.B) {
   261  		for b.Loop() {
   262  			NewPrivateKey65(make([]byte, 32))
   263  		}
   264  	})
   265  	b.Run("ML-DSA-87", func(b *testing.B) {
   266  		for b.Loop() {
   267  			NewPrivateKey87(make([]byte, 32))
   268  		}
   269  	})
   270  }
   271  
   272  var benchmarkMessagesMLDSA44 = []string{
   273  	"BUS7IAZWYOZ4JHJQYDWRTJL4V7",
   274  	"MK5HFFNP4TB5S6FM4KUFZSIXPD",
   275  	"DBFETUV4O56J57FXTXTIVCDIAR",
   276  	"I4FCMZ7UNLYAE2VVPKTE5ETXKL",
   277  	"56U76XRPOVFX3AU7MB2JHAP6JX",
   278  	"3ER6UPKIIDGCXLGLPU7KI3ODTN",
   279  	"JPQDX2IL3W5CYAFRZ4XUJOHQ3G",
   280  	"6AJOEI33Z3MLEBVC2Q67AYWK5L",
   281  	"WE3U36HYOPJ72RN3C74F6IOTTJ",
   282  	"NMPF5I3B2BKQG5RK26LMPQECCX",
   283  	"JRGAN2FA6IY7ESFGZ7PVI2RGWA",
   284  	"UIKLF6KNSIUHIIVNRKNUFRNR4W",
   285  	"HA252APFYUWHSZZFKP7CWGIBRY",
   286  	"JFY774TXRITQ6CIR56P2ZOTOL6",
   287  	"ZASYLW5Y3RAOC5NDZ2NCH5A4UY",
   288  	"42X4JXNPXMFRCFAE5AKR7XTFO7",
   289  	"YAHQUWUH534MUI2TYEKQR7VR3A",
   290  	"HBP7FGEXGSOZ5HNOVRGXZJU2KG",
   291  	"HG4O7DCRMYMQXASFLMYQ6NMIXK",
   292  	"2KPQMDZKS65CLJU4DHTMVV5WI3",
   293  	"G6YSUTEX4HHL44ISK2JVVK45BV",
   294  	"PUJGPEQUBQM3IK2EXDQFJ2WGBG",
   295  	"PNS6HMQAWA3RORSMSNEUAINMIR",
   296  	"L35MZS4XYIJK453OFXCZG4WHIK",
   297  	"CRY54YZMFRF6JTB3FPNNBWPUOG",
   298  	"Y25TSZBWGU4HJCRMWZHAWXQ2DN",
   299  	"23W64TW3AKZPKCM4HMKEHFI6VQ",
   300  	"PWQAOZ24B4VLNEQR4XKN7LZHDI",
   301  	"YINPDR3ZSAKPPXP6J6VAXHIPYO",
   302  	"JDBB52ZRAB3PYBPNE7P4COY5PJ",
   303  	"4DYU52LQLVG3LTREOTLBCJK3XC",
   304  	"AB45MV6RKUGPCW4EUK7DX23MJX",
   305  	"HEJSITE5K7J6YJ74OEATVTCERV",
   306  	"ZKI5QCFCGM26UK7F5KYTENXKD2",
   307  	"VH5G3ZLF5XC22QAEJ6JDGOBE5Y",
   308  	"HYGXFHH3JW5SENG26MXLL54IGV",
   309  	"MJUCRL36JZ757UYHBFPCJBPZRH",
   310  	"IBH3T6NAVLCJQBYSVHAQFUITYA",
   311  	"VMWCS7JMIMFQB6TPRAMOUXIKWD",
   312  	"SXRPGPNNW2MMBKQS3HJURIQ3XV",
   313  	"YPPYMJZW6WYXPSCZIPI57NTP5L",
   314  	"N3SH6DUH6UOPU7YMQ6BJJEQSPI",
   315  	"Q243DGA6VC6CW66FFUAB5V3VLB",
   316  	"OUUBXEU4NJBRN5XZJ7YQUPIZLA",
   317  	"H5TWHVGC7FXG6MCKJQURD3RNWG",
   318  	"OONG2ZZ7H3P5BREEEURNJHBBQG",
   319  	"HWROSSRTBCQOAIQAY5S4EQG4FX",
   320  	"AJW6PW62JQNU72VKGIQMPBX64C",
   321  	"OXECVUVAWBBBXGGQGQBTYVEP4S",
   322  	"M5XN6V2LQJDEIN3G4Z6WJO6AVT",
   323  	"NHGJUX3WGRTEIRPFWC2I467ST4",
   324  	"SEOADTJDKAYYLDSC4VAES2CRDJ",
   325  	"J5AT674S577ZFGEURNIAGYOHKW",
   326  	"VJQVNMGHG4ITFX2XSPSDEWVZWD",
   327  	"ZWY3KJPXTAVWWVHNAJDUXZ52TG",
   328  	"HY46PBUGP4EMH34C6Q56MO7CJP",
   329  	"MQTUO7CF6R6CRJPVV6F673M6VW",
   330  	"35Z2Z5KV2RBJPQ7OZ24ZJE6BKR",
   331  	"OVUEVXBLCU2BBY25QP5WJACDIX",
   332  	"LNJX7PCLYL35WYJBW6CTXENPUU",
   333  	"IH7E766LCENOQ5ZKZVCMLEPACU",
   334  	"T2HZFGDDSFQ6YADB52NIFLBFEV",
   335  	"RHQUJMN4MB5SYY4FP4ARZH52QJ",
   336  	"W7GZC5ZM63UF2EJ7OC4WJM3OTH",
   337  	"T2NHNFVOMICY33AQZSR53HXFQ6",
   338  	"7ZVB4Y4K4Y2VAM5NC7HHAJNZIB",
   339  	"UX2I4VF62XJGP2XTNN6LDKXTOH",
   340  	"HJAMJR5RQTQW7JMW7ZLPRBZE7E",
   341  	"HKWSKX7MB5346PHYNWNBAYDSYK",
   342  	"BVWSB75HFLLE45MWA6EPHPTCFR",
   343  	"YDH2J6NMM7UINHGUOPIUI7PSSR",
   344  	"SYQPZLK52HMUAQFMVHGRJYKBEY",
   345  	"7AA6UQFGSPBGNUDPLWXSGNKKPP",
   346  	"AYXRJGRWZ5S3QOEDVWYHHCICHV",
   347  	"KFJYAWO7IATSBCSTDUAA5EPFAN",
   348  	"3JABTLB6T2ICHGVT3HXZZ3OAIT",
   349  	"WCM3IBOCQJ36WSG627CCNK3QA7",
   350  	"5FB5H3BZN2J4RGR2DUW7M37NKZ",
   351  	"VKDDAD3BVOMPSNEDGIRHKX5S6R",
   352  	"LFH5HVUR726OSFD3YVYM3ZHEIH",
   353  	"Y4ETQB2KZVFB4M7SALLCTHX2FB",
   354  	"E6SAU3C25MO2WBBVBKCKP2N4ZE",
   355  	"3JA54Q3NEKURB5EAPL2FOFIESD",
   356  	"FZPBW7BIQIW3FTKQD4TLKNWLMD",
   357  	"LY5W6XFA2ZRI53FTUJYGWZ5RX6",
   358  	"QID236JY3ICR55O5YRED33O7YT",
   359  	"HDRU3L6MFEBCBQFNLF5IRPMOAL",
   360  	"232ANKJBDBG4TSKQ7GJMWTHT23",
   361  	"CDWE3CELZM5AOJGYEFHMUNSP5O",
   362  	"7LNJRBOKN6W7RXUU34MDJ2SNKL",
   363  	"S3IZOADTW2A6E5IGRO5WKX7FVH",
   364  	"ZAISTLXC55EBMTN6KZ6QX5S7OS",
   365  	"4Z5ZIVCMFR2PY2PY4Z47T4YPYA",
   366  	"NE36L53Z6AMYQU7Q5REFUF76MK",
   367  	"WND5UP5M6KWPBRFP5WIWTOWV3I",
   368  	"7OC54DLFWMADJEMKEJ3Y2FMMZS",
   369  	"BWJVZHGEN43ULNIOZCPZOB64HG",
   370  	"VDFPQSR7RE54A75GT4JDZY5JK2",
   371  	"HFCD5EPBZBSVMXIDA47DZ6MRD6",
   372  	"RNBVFIUUJUM7EHRE3VNWSTORGO",
   373  	"VO5NLQJBR22CRRYUETGTU6JLMR",
   374  	"RZOMNFHBTL6HMGWH4PEEDASK7U",
   375  	"QL73UBTOLK5O2TW43YWAIKS6T3",
   376  	"NE3QVSMWS5G3W5C3BMKTJNMI2L",
   377  	"YHI6EYQ4GZMB2QPGHPUG2ZUOEL",
   378  	"6MBATW7MFNRUQBFD3GM35B7YPM",
   379  	"AIYRY6P5T4XU44CGVPEV6W43FR",
   380  	"MIAQ2FHXMAPY5NXSS45VRDPRMG",
   381  	"2SNLHQYKK2K6NSWOF6KPGZ3CPC",
   382  	"RVBHIQO5LH77ZWEAO3SVL72M2V",
   383  	"XXTGJCJNRSNLE7ARAH2UU6LVKR",
   384  	"DQMGILY5IDMWN5OYQYYXH26ZGR",
   385  	"627VTXXMM455KMTFNUUTKNFXPY",
   386  	"HC7IBFGLZCWGUR4K7REPMPW6W4",
   387  	"CHL6JRQUS7D4NML3PFT37PPZAA",
   388  	"Y767HXJAGJ75KE3JLO4DTLQIXC",
   389  	"NTIODXI5I7TF2KXXWXOAYGT7G4",
   390  	"PKZYEK2WAI4D4HEYYZH6H5IOMP",
   391  	"FG6J6G7HZDEDF4JQBQOTC7RQGZ",
   392  	"3VHM2VZU77Y25E3UUYZJLB2QLA",
   393  	"WRZQJQW7ARH4DXYHVLCJ4HRTTB",
   394  	"LQXKV5HD2AZHENSJ2VFLJ5YU5L",
   395  	"MF6Q4OA2EN6TG6BUDK7RWCQNPU",
   396  	"3USKYKPC5CB3EC4ZRMZVE3R2UO",
   397  	"3WICO2GVS3IRBFUHNDLNKWVP7N",
   398  	"P6ZR2UZZOVUZKT4KUS5WICW5XE",
   399  	"PYPZUU76RYVOUZGUUX33HLDKYA",
   400  	"2FTSURHV34VYTVIUU7W6V5C3NK",
   401  	"YABDYMGXS2MD2CYF3S4ALG4FLG",
   402  	"MHIBDH25RRPWV3P4VAWT6SAX3I",
   403  	"OINSMWJQ2UTOOKZ3X6ICXXBQR7",
   404  	"PFTQS7JNU2Q3Q6L4CGBXVLOYNE",
   405  	"A4MZ7CCVYQUDJ2AFHNXBBQ3D24",
   406  	"CPUB5R3ORTCMSMCLUQURE6AN5O",
   407  	"NF5E7U3DFTXWFFXXHUXTEP4VZQ",
   408  	"AWB5WDFERWSSJG53YGJMDORQKR",
   409  	"U5JQUILKD6SEL6LXAMNFZP6VSW",
   410  	"M45NLOAFLO74EJKG5EXNET6J5Y",
   411  	"P2KTEUMZ5DZZMYSPOHDR2WJXAN",
   412  	"KVO7AXZNFBUBPYLOTZQQ42TFNS",
   413  	"WGJJ7SAEV6SBBWWYS4BTLD63WM",
   414  	"Y6GURVDV4ESRBPWSTV25T4PE4K",
   415  	"ESK7MPFPUZ5ZAQ52RP4SQIYCCC",
   416  	"623M3CIABZ3RANERQ2IREXAVYO",
   417  	"OQ4CQCFO42RS4BMMSGSDLUTOQO",
   418  	"AMFHRDVGM6G2TIR3TKIFGFSDVM",
   419  	"7VVSGGCVC53PLOYG7YHPFUJM5X",
   420  	"Z3HMESVL7EZUSZNZ33WXEBHA2N",
   421  	"AWWVRQD5W7IBSQPS26XOJVDV5H",
   422  	"OQBZ5ZST3U3NZYHSIWRNROIG6L",
   423  	"II573BW7DJLBYJSPSYIABQWDZD",
   424  	"MOKXOQFOCUCLQQH4UKH2DPE7VN",
   425  	"XR54NGUOU6BBUUTINNWBPJ35HX",
   426  	"DNK36COZGFXI6DY7WLCNUETIRT",
   427  	"R5M2PV7E3EHEM3TLGRCL3HSFMC",
   428  	"ITKENZQYDQMZFCUPOT7VF3BMU7",
   429  	"5GDCB74PPPHEP5N5G3DVRCYT7R",
   430  	"ZMKXVRPLI5PY5BDVEPOA3NQZGN",
   431  	"GBLIALWTHTUDTOMDERQFVB77CS",
   432  	"VKRTTXUTFOK4PJAQQZCCT7TV3T",
   433  	"ZJBUJJ4SW62BXOID3XO2W2M2PF",
   434  	"SKWT5T6QJTCD3FCINIK22KMVBJ",
   435  	"EHINNU6L33HRLOOJ3A2XFJSYQL",
   436  	"N4HRQJEFPAT5SU3YPO74WSMQIR",
   437  	"TGPTZ3ENMFWB5CZKJFR5WHIRI4",
   438  	"O4HNFTAUJJ2LZPQXPXRAXOVABA",
   439  	"4JVB5STP2YG5GYOXDWIF4KCKFB",
   440  	"MY554X3YZHBECLHNNZ7A3SPJTU",
   441  	"ASCJMAH7VCQAD2QJSWXPSVSM3H",
   442  	"NBNGL5DZ623KCG2JNZFGZMZ7KD",
   443  	"KGMZSW35AEQOJ6FA7IR7BHZI52",
   444  	"Q7QUHHS4OJFMJ4I3FY6TDKSMZQ",
   445  	"MZAE7TOEXAS76T7KIC73FEYRU4",
   446  	"2BVESR3REAWADCGYOYM7T646RG",
   447  	"EK3L2ORP4LT3HU3EMXDSQWFOKJ",
   448  	"3X4A6VMGMIDLVK72FZSDHSERWY",
   449  	"I3UHWI6M6HQFRBSQ6W2SABUNUP",
   450  	"REKPXW4DIB4MTKMPHN3RBVHVME",
   451  	"W37FNFZE35NX65Z7CVQ7L5U4L5",
   452  	"4AGYK6U2KP6RAOADCBUDDCBECV",
   453  	"IXM4SFQUDW2NOTXZIPWTNGET3F",
   454  	"6YE4G3VELF27MN3Z5B4VIQ3XYK",
   455  	"LPOZCPZAG3MD47MIWGR4FIOCDH",
   456  	"WGREKUL2LD7C7SYGKH7APIY2A6",
   457  	"WWW277FKTKUXQMP4BECSRHLWJI",
   458  	"UYE4IQPMSTXVQG7EJALKWWEGDN",
   459  	"TIV2L5Z6K7SNGNUVWSNKTAF4UE",
   460  	"I3FQOAW3PINUK26P62HCX657FO",
   461  }
   462  
   463  var benchmarkMessagesMLDSA65 = []string{
   464  	"NDGEUBUDWGRJJ3A4UNZZQOEKNL",
   465  	"ACGYQUXN4POOFUENCLNCIPHFAZ",
   466  	"Z3XETEYKROVJH7SIHOIAYCTO42",
   467  	"DXWCVCEFULV7XHRWHJWSEXWES7",
   468  	"BCR2D5PNLGFYX6B3QFQFV23JZP",
   469  	"2DVP5HNG54ES64QK4D37PWUYTJ",
   470  	"UJM4ADPJLURAIQH4XA6QYUGNJ6",
   471  	"B5WRCIPK5IVZW52R6TJOKNPKZH",
   472  	"7QNL6JTSP62IGX6RCM2NHRMTKK",
   473  	"EJSZQYLM7G7AJCGIEVBV2UW7NN",
   474  	"UFNA2NKJ3QFWNHHL5CXZ4R5H46",
   475  	"QZAXRTT3E4DOGVTJCOTBG3WXQV",
   476  	"KH2ETOYZO5UHIHIKATWJMUVG27",
   477  	"V5HVVQTOWRXZ2PB4XWXSEKXUN5",
   478  	"5LA7NAFI2LESMH533XY45QVCQW",
   479  	"SMF4TWPTMJA2Z4F4OVETTLVRAY",
   480  	"FWZ5OJAFMLTQRREPYF4VDRPPGI",
   481  	"OK3QMNO3OZSKSR6Q4BFVOVRWTH",
   482  	"NQOVN6F6AOBOEGMJTVMF67KTIJ",
   483  	"CCLC4Y6YT3AQ3HGT2QNSYAUGNV",
   484  	"CAZJHCHBUYQ6OKZ7DMWMDDLIZQ",
   485  	"LVW5XDTHPKOW5D452SYD7AFO6Q",
   486  	"EYA6O6FTYPC6TRKZPRPX5N2KQ4",
   487  	"Z6SGAEZ2SAAZHPQO7GL7CUMBAG",
   488  	"FKUCKW6JQVF4WQYXUSXYZQMAVY",
   489  	"LN2KDF4DANPE4SC4GKJ4BES3IZ",
   490  	"AVCRTWB6ALOQHY34XI7NTMP2JH",
   491  	"A5WHIS6CBWPCYIEC6N2MBAOEZ6",
   492  	"JC2BH476BXUQFIDA6UCR5V4G4F",
   493  	"NU6XH6VLSSFHVSRZCYXPFYKYCD",
   494  	"GSUXVZBDDYSZYFGXNP6AZW3PTC",
   495  	"XJPRNJ26XP4MIYH2Q7M7MPZ73M",
   496  	"INUTUP3IRFWIIT23DNFTIYKCFY",
   497  	"T4KH7HKLEYGXHBIRFGFCRUZCC4",
   498  	"GGQX4JFVWZHE5Y73YTLMSSOXNS",
   499  	"BUA4Q3TQZGLVHMMJU62GQOSHLV",
   500  	"WXW3SJXLSZO2MYF4YFIMXL2IQP",
   501  	"Q32XBVVGFQTSXAIDJE6XSEPRZG",
   502  	"6TEXT6SA7INRCTDSCSVZJEQ2YG",
   503  	"ZBN4UL43C3SJIG4HYR236PXCVS",
   504  	"TVWPLLC7NROBREWOM75VA3XCR3",
   505  	"CCDGL2FURLBABQ4IJBYCB75JFR",
   506  	"XBZGCOVTZHCPAARBTMAKPIE6GJ",
   507  	"TPRAENJ7I54XRIVH6LL6FDIA3I",
   508  	"RKOM3PHFILPIIQZL4ILQWGRYWI",
   509  	"CEEZIZ2WUXHQQFATYYGQ3ZDBTI",
   510  	"SLKOVAP6WLIVJBVU7VZG3ZGEOW",
   511  	"TWMCLJJSWEEQQPQGGDKEJ5SU2R",
   512  	"IFMUXXCD2LC7IGQLZ2QEK5UOQ2",
   513  	"C7IWFEBHW2CXN4XBJS7VLWH3VK",
   514  	"7KJYUEW3F264727TM4LE6RMGDO",
   515  	"BPG2XAPBMBTA4VMPUM7IZVZPK3",
   516  	"Y5X577BWRZNPLNUHJVSKGMUXYB",
   517  	"ZCKMKM23E4IUPTNQDFN2LTLZVX",
   518  	"4RKK223JNBDAP4G5DOAHHZ3VNO",
   519  	"5UZ3TQZHZT22ISTB4WJEVO6MC4",
   520  	"YMVS4HFSJ32CRZRL23PXZUEJFJ",
   521  	"UQEUJUTPSZLZARNBXWMCTMHPFF",
   522  	"CZAAZ5WK7EIPMW7NA3EZNNBF45",
   523  	"227PBHH23WM7F2QLEZSPFYXVW4",
   524  	"YUYS2J5CRFXZ4J4KJT2ZKIZVW3",
   525  	"MFLHZJOZV44SN4AH6OJ3QZWM2O",
   526  	"H2B3CRBCXYN7QWDGYUPHQZP23A",
   527  	"T4L6YWQUQ3CTACENAJ5WUXZWFH",
   528  	"N723H6MUGPZSRZ72C635OD4BP7",
   529  	"NI4TUMVA6LQPQV2TXPN4QOIGBZ",
   530  	"CQI3S4LSTQASSJJVZXEFPOVW7K",
   531  	"ANPY4HJ64LLSB3GK2R4C6WDBS3",
   532  	"RGWQCZKQLMT5FZRDE4B3VMASVK",
   533  	"Q3WCCF2HA3CA4WWRJBMGBW7WI7",
   534  	"2AKJRXFHXLUQPOXPTLSZN5PW4A",
   535  	"IJWOOTI4N7RWXJIHAPXN6KEWEN",
   536  	"4D53T6N6ATOVTD4LKSTAAWBJMU",
   537  	"B4G5HDD6RITG6NIH6FXCRZDYZM",
   538  	"TJCDFKMRUY2OG6KRSMNVCGQFUP",
   539  	"PB33IHQKALAY6H6GVBVLI6ZRXK",
   540  	"SCCWGW2J5S4WL4FTTMQ435F6DB",
   541  	"ZVJH2HSMTLHGXMGPMXLJCKCLLE",
   542  	"62LG37U6JXR77YRZQQCDSBHVCS",
   543  	"BU4CBWOXQ352TEOKIXO245ID4O",
   544  	"UEZOH7KEIODSEVRUF6GMWGA2RB",
   545  	"IPJWROME4GM66CGLUWP5BJ4SX6",
   546  	"355GDC7TG64AZJ7IJX6K62KZCZ",
   547  	"AHTFKX3V7XUB3EWOMQVCGZYGUE",
   548  	"N4RV2GKXJ4SPHHJ52Z7K5EGLER",
   549  	"ZY7V7NE5F66XHDHWM6YNFEWZA6",
   550  	"DIKFO5KAVT4WAP7BOEFM56ZUSR",
   551  	"4TDFOFKDAPIOM3MU5GD7NPXNWQ",
   552  	"AD7YZO756HDK6YWFILAKW3JWA7",
   553  	"NUA53JS2ZK2BGHH3A7BJTJZYW7",
   554  	"QLCNC3AQNKLRMSYR62WQSQP5VI",
   555  	"SJ7OBS7ZYXSGXOYXPE5KW2XKN6",
   556  	"44HBMOGMIMJS63CEXQU7FCXE2E",
   557  	"KCK3J7ZL6QF4SLHHSWTJURK7PG",
   558  	"HLH4CLUGBSOOBSS3BPO62N5MC3",
   559  	"3FNS4GITO6OEUBAVDDXK4WOBTD",
   560  	"IAC3K3I4AQGY3G6UHG7PL2N6TE",
   561  	"KUKLNH74POJI5DYAEWUD7RABTQ",
   562  	"ETM6N7VU3GBSQ7P5MCD6UF3E3S",
   563  	"IZITM5NYBGJZLSI3BI4VEMW43U",
   564  	"46OPQU4LL6N3Z2U7KYPKUMBAGI",
   565  	"EV7YZ5DMAV7VKYJQUFSRD37GPP",
   566  	"AV7W2PGYDJIAKLFVEBL6BXQSGC",
   567  	"M2FOX5QZEZKV4QXKPI5XUZDHEM",
   568  	"R4IFPLVMOVYCHRTR6LXAUGP3LL",
   569  	"JGH6XJUMP4DRVAM27P2JNOKXVO",
   570  	"D2XN3ZLLU6VFPMDYM7NBHSQEOI",
   571  	"2PO3BYENOMQK6SHQDCFSRPJQI3",
   572  	"IBVQ7U3QEUC6PQRE4PV53JTZTK",
   573  	"ZBCOX4P7NG2IXXFB2R43MG2SLV",
   574  	"5NJDPQVVDO7ADNZ2CV7L6QBNGZ",
   575  	"V7ASFIIYUMXFGW4B7ZM6LOGUTE",
   576  	"PX5IJZ7W2LUPKM6YN4PMZ43ZLM",
   577  	"AYK7SZ23DHC7Q56MWAJXBG76LB",
   578  	"UYCAPXJM4HNGKLIDSZ4NCEDJLN",
   579  	"UWMDZ3C2ODLACKGJPGETNQ3TA4",
   580  	"Q6OI6R3WYYJ4CCZCDJBQMCRCZR",
   581  	"LCMJHLP7354APCEGPKE7HHWTWB",
   582  	"N7T7ZKOYPAMEYTTDOWZNCN6PRD",
   583  	"UZADPU4UNHAF7L7LQDMTKA2EQH",
   584  	"DC2OEPQDECVLRVNNCS6BMH4CRA",
   585  	"37IZ427XHUMZ66EJ62U2YEZDAC",
   586  	"6BCZDQZDPZLS5OGESKNUBPSSFV",
   587  	"ST2LEMJ4OLQ32TJTLH2WCWT4WA",
   588  	"GA2TL4SFLEW4G2B5PQMIKJT5XG",
   589  	"L7PPBIET26EH7LQTLEFC4I4EIA",
   590  	"6YSM7MC2W4DEV6ULAHMX27LH56",
   591  	"QL26Z5KZ4YRRG2BXXGDRRLV357",
   592  	"677TWRAJ5NSNHCE243POQPEG7K",
   593  	"66MEBQJLGAGVXDX3KZ2YFTTVJM",
   594  	"6D4VUWAQD6R65ICSDLFAATC67V",
   595  	"7GXLD5CNU3TDUQSSW42SHL7B5D",
   596  	"RQETUMEBG2ZM2NF2EZAQHGHWWE",
   597  	"DCRX5ANWDMXZFIDVAXYLQZYMRN",
   598  	"5SDWT7YAF7L4WWANAGYINZAYXH",
   599  	"PZILRV7I2S6WKUSHKYRLA2JQY3",
   600  	"2G66TK2PZ5MOTAZDN7BFS3LAIH",
   601  	"QOLJ3WGJ6JS3FMMXBNTNAIKXVK",
   602  	"FMAL67YTHDCCYVZ5CRMN2XJPDN",
   603  	"UOTZDXTJKQ3YAIRKHTYNX6G55P",
   604  	"X3DLNPJ3V62LRHGEY4DTT35H3R",
   605  	"DKU7CHNXPB5QRZVGIQZW46XCKC",
   606  	"RAKBD4LQKEDTVDSK3DVTRWG23B",
   607  	"INTRA7BWHLVQMBRKBJNUSMF7MU",
   608  	"AUYRBNVCOYYHOHUYOOFIZ2FWMD",
   609  	"22EJVDEQ7PASLBAMTVKXOQP5RJ",
   610  	"3S6NATWA57SFTZEW7UZUOUYAEU",
   611  }
   612  
   613  var benchmarkMessagesMLDSA87 = []string{
   614  	"LQQPGPNUME6QDNDTQTS4BA7I7M",
   615  	"PTYEEJ7RMI6MXNN6PZH222Y6QI",
   616  	"R6DTHAADKNMEADDK5ECPNOTOAT",
   617  	"S2QM7VDC6UKRQNRETZMNAZ6SJT",
   618  	"EYULPTSJORQJCNYNYVHDFN4N3F",
   619  	"YETZNHZ75SXFU672VQ5WXYEPV2",
   620  	"KTSND3JGA4AN3PCMG4455JEXGR",
   621  	"JGE6HK37O6XMWZQZCHFUPNUEXP",
   622  	"CRYB2FZD2BYNANBFFO2HRZEHGZ",
   623  	"7MLNDZJ7OIEPBJZOMULOMQH2BA",
   624  	"4WQCNTIFVSX2DNALMWUKZRA6CI",
   625  	"Y5NK4OBDSDWC5WLL27CEEXYYOT",
   626  	"C4SSWSPBVCDAWJXH2CDMXR36LH",
   627  	"THDBKXRTKWJUGJMAAYTWTFMX7Z",
   628  	"NWXPUD4DAA6QOREW4AFFYQYQNG",
   629  	"3RQIJXMO7WYHBEBL3G6EOLNZNQ",
   630  	"R7JEOHFP2C7O4AVPRPRELXWOMM",
   631  	"LU6MWR7SZXVIKS54BY62X67NPA",
   632  	"FG2FFM4F2ECKHCSJ75KXK632JP",
   633  	"BF76ZDSVVUSYS5KK4FFD22YPS7",
   634  	"HCLBWZRLHEMYZLFWHLAN2BKCZ7",
   635  	"HGFVS4QC7AWXYPVRSWAK77KTQF",
   636  	"LUZ3C53PUUHBWCDJ7WAHK2UT3K",
   637  	"Y3WR6SMDUBW34N3MUT7EQYIJCV",
   638  	"F2X35AQTXVZBMPXTWNAAH4ZX2W",
   639  	"6MKFFDYWD6ZAKS3C6GRCRLZLRF",
   640  	"AFMZYYFRHKMQRNKU5UTSKQ74H6",
   641  	"TDTN7J3O367OVPWLESRNPLN4M2",
   642  	"WYMLD2X6N4CZ2RDOKF5CFTSYTG",
   643  	"UNPTSBLJ6HZRNR72T2VEEHCFX2",
   644  	"SNCM4R2P27AJOXBS67RMCARS3U",
   645  	"OU7QBE5QOXO7CIYTBJR3KOW2WK",
   646  	"2NNQOBQKZ2OD4ZAXI3SNEURYUP",
   647  	"YQTUPOYBT67XPCHIGKSGSKC3BZ",
   648  	"HGB4ZM3G76IXYWWCMVT3HONRIS",
   649  	"WZC6QUKRZZ2TOVA277JYKQITEW",
   650  	"XO2WT46A5HYL6CUJF7SGJ6YWOG",
   651  	"4QJA35PMYQIDRZ7ZHG7RLZJVGF",
   652  	"BMJZELWZ4I2UWXESU3NR6ATC4M",
   653  	"XWLFB7FN6D5PRY6YUXC5JUIBFM",
   654  	"WRAFFF27AVTIOYIBYA2IPTXI3R",
   655  	"VOXUTYTN2XZ362OJFO2R53UCUF",
   656  	"UHN73ARJ737WUJ6QYEI7U46OPO",
   657  	"3Y3K5E2A4ML3VYVNAFWEEIXTSN",
   658  	"QMU4322NKPRLE7JBGYFGS36H2S",
   659  	"NJAQTNCXPVDICTDVUKTPRCD2AX",
   660  	"OC373ZFBNV2H46T6OY3XRPSUHG",
   661  	"UBLAS6CDWE3A662MLKP7QDEOCC",
   662  	"BKFDLAL2RTPMERYVW3B7UJ5W3H",
   663  	"QFKFGXKGW5SAKLBAWQXUWW77OS",
   664  	"EJNUQHTLLOVB4ARETOGLY4WUTJ",
   665  	"N243OCMVLLAO6I2XLCYOIMQYGY",
   666  	"YRRFLWK7ZASUKYX7ZLQMW2PJ6X",
   667  	"3DGVPBWD2BIK6KQE65K72DNJNM",
   668  	"TJRYMNOAIW33VIHKLJG4GXAVUK",
   669  	"6DSRINAYXL34U54U355U7IVFGS",
   670  	"6CHA4MX7LVS77XKRWG7IYC3XVL",
   671  	"GM2CEGBEPBOHAPIOBUWJ4MJNTG",
   672  	"VJKHGBY33VUIJFEQLX3JVUNQBD",
   673  	"DTOHAD5M2KL46IZHE4TPLJWHTI",
   674  	"IYFG3UDN7ROOY2ZFSLM2BU2LMQ",
   675  	"A5OGJHPOE4PW6QSZYHZ5TKPGIC",
   676  	"FX4BCN67AEGCLUTLFPNDL3SQU5",
   677  	"MWIZQVOZOHTTBUXC3BEX62MNI5",
   678  	"BYHVJHBLK4O6LFSKEIQ3CAAKU7",
   679  	"QJU7P6KWSSKAA5GVA6RH4OV7MX",
   680  	"I3T3XM5Z5TAJHAYDQHFA2ZV7PU",
   681  	"L46MQCHV3TJ6FYIQQ2FCJXES74",
   682  	"QXZRQIYAJMXYR6PU3VDYGCIT5W",
   683  	"MFS53RR2XEYS22NYOJLGTHVTTM",
   684  	"FRWIWJRP4AQMXWX4WJ4WYVKM3E",
   685  	"X6GK6IGVLJWYSHLKHGXSW3TJDP",
   686  	"L5LPJ2HIWA4UY6G6FMZXGDEDAM",
   687  	"GD6FYOYUGDHXEQ5S2KLJEGNSN7",
   688  	"ODAL7ZRKXSPAAN5DVRBWJQCFQX",
   689  	"CV3QFBDXBPT3SCPJGUYSMDN6ZS",
   690  	"IGSLSACRZ6XID466KQIB4YNGYO",
   691  	"WZ2EACBN26RAML2S52YXRYP2OF",
   692  	"LB76VEVNOBYFMKFZ7SDFCBCHQE",
   693  	"TLFA7EU3JJFAP6EMUKNV2ZXRBM",
   694  	"SIIJF6OXAKRP25CBUYFBRCDDVP",
   695  	"TEPNI7TJ7HASJWIQMBS4VFLRQC",
   696  	"VK2JINYWEDV7IQFWH4OTAD4W5O",
   697  	"GILUH5AMVE4TM7EKPXJBZGT6EJ",
   698  	"DV7ALFRAW3TI4WMQQLDTO6RNHN",
   699  	"CAIB5G3NXC5ASPLFIWAFPVHS5B",
   700  	"MLFJXZUOAGN7EGPMXOOVTB2CL4",
   701  	"6MZYT3ANWHBOS67WGHZI3QPEAP",
   702  	"LVJDQB52C2PERSSQJRMRCJ4UBF",
   703  	"QY4VKAZAYQIZOX2L2VO2QHAQVC",
   704  	"UAA5SST2XA76JPKM3XOZ5RUHFI",
   705  	"VLZWF53JSQ6SCRUFDKVPXWAS4L",
   706  	"NX2DZIKMJIYXUNSAHFP23FHTBU",
   707  	"F5OAKDDDA34A2RPIKDPM5CYPMZ",
   708  	"E5PEP3ANIK2L4VLOST4NIYNKBD",
   709  	"IPBGFLHSMP4UFXF6XJX42T6CAL",
   710  	"XHPU7DBFTZB2TX5K34AD6DJTK3",
   711  	"2ZU7EJN2DG2UMT6HX5KGS2RFT6",
   712  	"SD5S7U34WSE4GBPKVDUDZLBIEH",
   713  	"WZFFL3BTQAV4VQMSAGCS45SGG3",
   714  	"QE7ZT2LI4CA5DLSVMHV6CP3E3V",
   715  	"YIWMS6AS72Z5N2ALZNFGCYC5QL",
   716  	"A4QJ5FNY54THAKBOB65K2JBIV7",
   717  	"6LORQGA3QO7TNADHEIINQZEE26",
   718  	"5V45M6RAKOZDMONYY4DIH3ZBL2",
   719  	"SVP7UYIZ5RTLWRKFLCWHAQV3Y2",
   720  	"C2UYQL2BBE4VLUJ3IFNFMHAN7O",
   721  	"P4DS44LGP2ERZB3OB7JISQKBXA",
   722  	"A6B4O5MWALOEHLILSVDOIXHQ4Z",
   723  	"DKQJTW5QF7KDZA3IR4X5R5F3CG",
   724  	"H6QFQX2C2QTH3YKEOO57SQS23J",
   725  	"DIF373ML2RWZMEOIVUHFXKUG7O",
   726  	"Z5PPIA3GJ74QXFFCOSUAQMN5YN",
   727  	"PM6XIDECSS5S77UXMB55VZHZSE",
   728  }
   729  

View as plain text