// Copyright 2025 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

//go:build !fips140v1.0

package fipstest

import (
	"crypto/internal/cryptotest"
	"crypto/internal/fips140"
	. "crypto/internal/fips140/mldsa"
	"crypto/internal/fips140/sha3"
	"encoding/hex"
	"flag"
	"math/rand"
	"testing"
)

var sixtyMillionFlag = flag.Bool("60million", false, "run 60M-iterations accumulated test")

// TestMLDSAAccumulated accumulates 10k (or 100, or 60M) random vectors and checks
// the hash of the result, to avoid checking in megabytes of test vectors.
//
// 60M in particular is enough to give a 99.9% chance of hitting every value in
// the base field.
//
//	1-((q-1)/q)^60000000 ~= 0.9992
//
// If setting -60million, remember to also set -timeout 0.
func TestMLDSAAccumulated(t *testing.T) {
	t.Run("ML-DSA-44/100", func(t *testing.T) {
		testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 100,
			"d51148e1f9f4fa1a723a6cf42e25f2a99eb5c1b378b3d2dbbd561b1203beeae4")
	})
	t.Run("ML-DSA-65/100", func(t *testing.T) {
		testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 100,
			"8358a1843220194417cadbc2651295cd8fc65125b5a5c1a239a16dc8b57ca199")
	})
	t.Run("ML-DSA-87/100", func(t *testing.T) {
		testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 100,
			"8c3ad714777622b8f21ce31bb35f71394f23bc0fcf3c78ace5d608990f3b061b")
	})
	if !testing.Short() {
		t.Run("ML-DSA-44/10k", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 10000,
				"e7fd21f6a59bcba60d65adc44404bb29a7c00e5d8d3ec06a732c00a306a7d143")
		})
		t.Run("ML-DSA-65/10k", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 10000,
				"5ff5e196f0b830c3b10a9eb5358e7c98a3a20136cb677f3ae3b90175c3ace329")
		})
		t.Run("ML-DSA-87/10k", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 10000,
				"80a8cf39317f7d0be0e24972c51ac152bd2a3e09bc0c32ce29dd82c4e7385e60")
		})
	}
	if *sixtyMillionFlag {
		t.Run("ML-DSA-44/60M", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey44, NewPublicKey44, 60000000,
				"080b48049257f5cd30dee17d6aa393d6c42fe52a29099df84a460ebaf4b02330")
		})
		t.Run("ML-DSA-65/60M", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey65, NewPublicKey65, 60000000,
				"0af0165db2b180f7a83dbecad1ccb758b9c2d834b7f801fc49dd572a9d4b1e83")
		})
		t.Run("ML-DSA-87/60M", func(t *testing.T) {
			t.Parallel()
			testMLDSAAccumulated(t, NewPrivateKey87, NewPublicKey87, 60000000,
				"011166e9d5032c9bdc5c9bbb5dbb6c86df1c3d9bf3570b65ebae942dd9830057")
		})
	}
}

func testMLDSAAccumulated(t *testing.T, newPrivateKey func([]byte) (*PrivateKey, error), newPublicKey func([]byte) (*PublicKey, error), n int, expected string) {
	s := sha3.NewShake128()
	o := sha3.NewShake128()
	seed := make([]byte, PrivateKeySize)
	msg := make([]byte, 0)

	for i := 0; i < n; i++ {
		s.Read(seed)
		dk, err := newPrivateKey(seed)
		if err != nil {
			t.Fatalf("NewPrivateKey: %v", err)
		}
		pk := dk.PublicKey().Bytes()
		o.Write(pk)
		sig, err := SignDeterministic(dk, msg, "")
		if err != nil {
			t.Fatalf("SignDeterministic: %v", err)
		}
		o.Write(sig)
		pub, err := newPublicKey(pk)
		if err != nil {
			t.Fatalf("NewPublicKey: %v", err)
		}
		if *pub != *dk.PublicKey() {
			t.Fatalf("public key mismatch")
		}
		if err := Verify(dk.PublicKey(), msg, sig, ""); err != nil {
			t.Fatalf("Verify: %v", err)
		}
	}

	got := hex.EncodeToString(o.Sum(nil))
	if got != expected {
		t.Errorf("got %s, expected %s", got, expected)
	}
}

func TestMLDSAGenerateKey(t *testing.T) {
	t.Run("ML-DSA-44", func(t *testing.T) {
		testMLDSAGenerateKey(t, GenerateKey44, NewPrivateKey44)
	})
	t.Run("ML-DSA-65", func(t *testing.T) {
		testMLDSAGenerateKey(t, GenerateKey65, NewPrivateKey65)
	})
	t.Run("ML-DSA-87", func(t *testing.T) {
		testMLDSAGenerateKey(t, GenerateKey87, NewPrivateKey87)
	})
}

func testMLDSAGenerateKey(t *testing.T, generateKey func() *PrivateKey, newPrivateKey func([]byte) (*PrivateKey, error)) {
	k1 := generateKey()
	k2 := generateKey()
	if k1.Equal(k2) {
		t.Errorf("two generated keys are equal")
	}
	k1x, err := newPrivateKey(k1.Bytes())
	if err != nil {
		t.Fatalf("NewPrivateKey: %v", err)
	}
	if !k1.Equal(k1x) {
		t.Errorf("generated key and re-parsed key are not equal")
	}
}

func TestMLDSAAllocations(t *testing.T) {
	// We allocate the PrivateKey (k and kk) and PublicKey (pk) structs and the
	// public key (pkBytes) and signature (sig) byte slices on the heap. They
	// are all large and for the byte slices variable-length. Still, check we
	// are not slipping more allocations in.
	var expected float64 = 5
	if fips140.Enabled {
		// The PCT does a sign/verify cycle, which allocates a signature slice.
		expected += 1
	}
	cryptotest.SkipTestAllocations(t)
	if allocs := testing.AllocsPerRun(100, func() {
		k := GenerateKey44()
		seed := k.Bytes()
		kk, err := NewPrivateKey44(seed)
		if err != nil {
			t.Fatalf("NewPrivateKey44: %v", err)
		}
		if !k.Equal(kk) {
			t.Fatalf("keys not equal")
		}
		pkBytes := k.PublicKey().Bytes()
		pk, err := NewPublicKey44(pkBytes)
		if err != nil {
			t.Fatalf("NewPublicKey44: %v", err)
		}
		message := []byte("Hello, world!")
		context := "test"
		sig, err := Sign(k, message, context)
		if err != nil {
			t.Fatalf("Sign: %v", err)
		}
		if err := Verify(pk, message, sig, context); err != nil {
			t.Fatalf("Verify: %v", err)
		}
	}); allocs > expected {
		t.Errorf("expected %0.0f allocations, got %0.1f", expected, allocs)
	}
}

func BenchmarkMLDSASign(b *testing.B) {
	// Signing works by rejection sampling, which introduces massive variance in
	// individual signing times. To get stable but correct results, we benchmark
	// a series of representative operations, engineered to have the same
	// distribution of rejection counts and reasons as the average case. See also
	// https://words.filippo.io/rsa-keygen-bench/ for a similar approach.
	b.Run("ML-DSA-44", func(b *testing.B) {
		benchmarkMLDSASign(b, NewPrivateKey44, benchmarkMessagesMLDSA44)
	})
	b.Run("ML-DSA-65", func(b *testing.B) {
		benchmarkMLDSASign(b, NewPrivateKey65, benchmarkMessagesMLDSA65)
	})
	b.Run("ML-DSA-87", func(b *testing.B) {
		benchmarkMLDSASign(b, NewPrivateKey87, benchmarkMessagesMLDSA87)
	})
}

func benchmarkMLDSASign(b *testing.B, newPrivateKey func([]byte) (*PrivateKey, error), messages []string) {
	seed := make([]byte, 32)
	priv, err := newPrivateKey(seed)
	if err != nil {
		b.Fatalf("NewPrivateKey: %v", err)
	}
	rand.Shuffle(len(messages), func(i, j int) {
		messages[i], messages[j] = messages[j], messages[i]
	})
	i := 0
	for b.Loop() {
		msg := messages[i]
		if i++; i >= len(messages) {
			i = 0
		}
		SignDeterministic(priv, []byte(msg), "")
	}
}

// BenchmarkMLDSAVerify runs both public key parsing and signature verification,
// since pre-computation can be easily moved between the two, but in practice
// most uses of verification are for fresh public keys (unlike signing).
func BenchmarkMLDSAVerify(b *testing.B) {
	b.Run("ML-DSA-44", func(b *testing.B) {
		benchmarkMLDSAVerify(b, GenerateKey44, NewPublicKey44)
	})
	b.Run("ML-DSA-65", func(b *testing.B) {
		benchmarkMLDSAVerify(b, GenerateKey65, NewPublicKey65)
	})
	b.Run("ML-DSA-87", func(b *testing.B) {
		benchmarkMLDSAVerify(b, GenerateKey87, NewPublicKey87)
	})
}

func benchmarkMLDSAVerify(b *testing.B, generateKey func() *PrivateKey, newPublicKey func([]byte) (*PublicKey, error)) {
	priv := generateKey()
	msg := make([]byte, 128)
	sig, err := SignDeterministic(priv, msg, "context")
	if err != nil {
		b.Fatalf("SignDeterministic: %v", err)
	}
	pub := priv.PublicKey().Bytes()
	for b.Loop() {
		pk, err := newPublicKey(pub)
		if err != nil {
			b.Fatalf("NewPublicKey: %v", err)
		}
		if err := Verify(pk, msg, sig, "context"); err != nil {
			b.Fatalf("Verify: %v", err)
		}
	}
}

func BenchmarkMLDSAKeygen(b *testing.B) {
	b.Run("ML-DSA-44", func(b *testing.B) {
		for b.Loop() {
			NewPrivateKey44(make([]byte, 32))
		}
	})
	b.Run("ML-DSA-65", func(b *testing.B) {
		for b.Loop() {
			NewPrivateKey65(make([]byte, 32))
		}
	})
	b.Run("ML-DSA-87", func(b *testing.B) {
		for b.Loop() {
			NewPrivateKey87(make([]byte, 32))
		}
	})
}

var benchmarkMessagesMLDSA44 = []string{
	"BUS7IAZWYOZ4JHJQYDWRTJL4V7",
	"MK5HFFNP4TB5S6FM4KUFZSIXPD",
	"DBFETUV4O56J57FXTXTIVCDIAR",
	"I4FCMZ7UNLYAE2VVPKTE5ETXKL",
	"56U76XRPOVFX3AU7MB2JHAP6JX",
	"3ER6UPKIIDGCXLGLPU7KI3ODTN",
	"JPQDX2IL3W5CYAFRZ4XUJOHQ3G",
	"6AJOEI33Z3MLEBVC2Q67AYWK5L",
	"WE3U36HYOPJ72RN3C74F6IOTTJ",
	"NMPF5I3B2BKQG5RK26LMPQECCX",
	"JRGAN2FA6IY7ESFGZ7PVI2RGWA",
	"UIKLF6KNSIUHIIVNRKNUFRNR4W",
	"HA252APFYUWHSZZFKP7CWGIBRY",
	"JFY774TXRITQ6CIR56P2ZOTOL6",
	"ZASYLW5Y3RAOC5NDZ2NCH5A4UY",
	"42X4JXNPXMFRCFAE5AKR7XTFO7",
	"YAHQUWUH534MUI2TYEKQR7VR3A",
	"HBP7FGEXGSOZ5HNOVRGXZJU2KG",
	"HG4O7DCRMYMQXASFLMYQ6NMIXK",
	"2KPQMDZKS65CLJU4DHTMVV5WI3",
	"G6YSUTEX4HHL44ISK2JVVK45BV",
	"PUJGPEQUBQM3IK2EXDQFJ2WGBG",
	"PNS6HMQAWA3RORSMSNEUAINMIR",
	"L35MZS4XYIJK453OFXCZG4WHIK",
	"CRY54YZMFRF6JTB3FPNNBWPUOG",
	"Y25TSZBWGU4HJCRMWZHAWXQ2DN",
	"23W64TW3AKZPKCM4HMKEHFI6VQ",
	"PWQAOZ24B4VLNEQR4XKN7LZHDI",
	"YINPDR3ZSAKPPXP6J6VAXHIPYO",
	"JDBB52ZRAB3PYBPNE7P4COY5PJ",
	"4DYU52LQLVG3LTREOTLBCJK3XC",
	"AB45MV6RKUGPCW4EUK7DX23MJX",
	"HEJSITE5K7J6YJ74OEATVTCERV",
	"ZKI5QCFCGM26UK7F5KYTENXKD2",
	"VH5G3ZLF5XC22QAEJ6JDGOBE5Y",
	"HYGXFHH3JW5SENG26MXLL54IGV",
	"MJUCRL36JZ757UYHBFPCJBPZRH",
	"IBH3T6NAVLCJQBYSVHAQFUITYA",
	"VMWCS7JMIMFQB6TPRAMOUXIKWD",
	"SXRPGPNNW2MMBKQS3HJURIQ3XV",
	"YPPYMJZW6WYXPSCZIPI57NTP5L",
	"N3SH6DUH6UOPU7YMQ6BJJEQSPI",
	"Q243DGA6VC6CW66FFUAB5V3VLB",
	"OUUBXEU4NJBRN5XZJ7YQUPIZLA",
	"H5TWHVGC7FXG6MCKJQURD3RNWG",
	"OONG2ZZ7H3P5BREEEURNJHBBQG",
	"HWROSSRTBCQOAIQAY5S4EQG4FX",
	"AJW6PW62JQNU72VKGIQMPBX64C",
	"OXECVUVAWBBBXGGQGQBTYVEP4S",
	"M5XN6V2LQJDEIN3G4Z6WJO6AVT",
	"NHGJUX3WGRTEIRPFWC2I467ST4",
	"SEOADTJDKAYYLDSC4VAES2CRDJ",
	"J5AT674S577ZFGEURNIAGYOHKW",
	"VJQVNMGHG4ITFX2XSPSDEWVZWD",
	"ZWY3KJPXTAVWWVHNAJDUXZ52TG",
	"HY46PBUGP4EMH34C6Q56MO7CJP",
	"MQTUO7CF6R6CRJPVV6F673M6VW",
	"35Z2Z5KV2RBJPQ7OZ24ZJE6BKR",
	"OVUEVXBLCU2BBY25QP5WJACDIX",
	"LNJX7PCLYL35WYJBW6CTXENPUU",
	"IH7E766LCENOQ5ZKZVCMLEPACU",
	"T2HZFGDDSFQ6YADB52NIFLBFEV",
	"RHQUJMN4MB5SYY4FP4ARZH52QJ",
	"W7GZC5ZM63UF2EJ7OC4WJM3OTH",
	"T2NHNFVOMICY33AQZSR53HXFQ6",
	"7ZVB4Y4K4Y2VAM5NC7HHAJNZIB",
	"UX2I4VF62XJGP2XTNN6LDKXTOH",
	"HJAMJR5RQTQW7JMW7ZLPRBZE7E",
	"HKWSKX7MB5346PHYNWNBAYDSYK",
	"BVWSB75HFLLE45MWA6EPHPTCFR",
	"YDH2J6NMM7UINHGUOPIUI7PSSR",
	"SYQPZLK52HMUAQFMVHGRJYKBEY",
	"7AA6UQFGSPBGNUDPLWXSGNKKPP",
	"AYXRJGRWZ5S3QOEDVWYHHCICHV",
	"KFJYAWO7IATSBCSTDUAA5EPFAN",
	"3JABTLB6T2ICHGVT3HXZZ3OAIT",
	"WCM3IBOCQJ36WSG627CCNK3QA7",
	"5FB5H3BZN2J4RGR2DUW7M37NKZ",
	"VKDDAD3BVOMPSNEDGIRHKX5S6R",
	"LFH5HVUR726OSFD3YVYM3ZHEIH",
	"Y4ETQB2KZVFB4M7SALLCTHX2FB",
	"E6SAU3C25MO2WBBVBKCKP2N4ZE",
	"3JA54Q3NEKURB5EAPL2FOFIESD",
	"FZPBW7BIQIW3FTKQD4TLKNWLMD",
	"LY5W6XFA2ZRI53FTUJYGWZ5RX6",
	"QID236JY3ICR55O5YRED33O7YT",
	"HDRU3L6MFEBCBQFNLF5IRPMOAL",
	"232ANKJBDBG4TSKQ7GJMWTHT23",
	"CDWE3CELZM5AOJGYEFHMUNSP5O",
	"7LNJRBOKN6W7RXUU34MDJ2SNKL",
	"S3IZOADTW2A6E5IGRO5WKX7FVH",
	"ZAISTLXC55EBMTN6KZ6QX5S7OS",
	"4Z5ZIVCMFR2PY2PY4Z47T4YPYA",
	"NE36L53Z6AMYQU7Q5REFUF76MK",
	"WND5UP5M6KWPBRFP5WIWTOWV3I",
	"7OC54DLFWMADJEMKEJ3Y2FMMZS",
	"BWJVZHGEN43ULNIOZCPZOB64HG",
	"VDFPQSR7RE54A75GT4JDZY5JK2",
	"HFCD5EPBZBSVMXIDA47DZ6MRD6",
	"RNBVFIUUJUM7EHRE3VNWSTORGO",
	"VO5NLQJBR22CRRYUETGTU6JLMR",
	"RZOMNFHBTL6HMGWH4PEEDASK7U",
	"QL73UBTOLK5O2TW43YWAIKS6T3",
	"NE3QVSMWS5G3W5C3BMKTJNMI2L",
	"YHI6EYQ4GZMB2QPGHPUG2ZUOEL",
	"6MBATW7MFNRUQBFD3GM35B7YPM",
	"AIYRY6P5T4XU44CGVPEV6W43FR",
	"MIAQ2FHXMAPY5NXSS45VRDPRMG",
	"2SNLHQYKK2K6NSWOF6KPGZ3CPC",
	"RVBHIQO5LH77ZWEAO3SVL72M2V",
	"XXTGJCJNRSNLE7ARAH2UU6LVKR",
	"DQMGILY5IDMWN5OYQYYXH26ZGR",
	"627VTXXMM455KMTFNUUTKNFXPY",
	"HC7IBFGLZCWGUR4K7REPMPW6W4",
	"CHL6JRQUS7D4NML3PFT37PPZAA",
	"Y767HXJAGJ75KE3JLO4DTLQIXC",
	"NTIODXI5I7TF2KXXWXOAYGT7G4",
	"PKZYEK2WAI4D4HEYYZH6H5IOMP",
	"FG6J6G7HZDEDF4JQBQOTC7RQGZ",
	"3VHM2VZU77Y25E3UUYZJLB2QLA",
	"WRZQJQW7ARH4DXYHVLCJ4HRTTB",
	"LQXKV5HD2AZHENSJ2VFLJ5YU5L",
	"MF6Q4OA2EN6TG6BUDK7RWCQNPU",
	"3USKYKPC5CB3EC4ZRMZVE3R2UO",
	"3WICO2GVS3IRBFUHNDLNKWVP7N",
	"P6ZR2UZZOVUZKT4KUS5WICW5XE",
	"PYPZUU76RYVOUZGUUX33HLDKYA",
	"2FTSURHV34VYTVIUU7W6V5C3NK",
	"YABDYMGXS2MD2CYF3S4ALG4FLG",
	"MHIBDH25RRPWV3P4VAWT6SAX3I",
	"OINSMWJQ2UTOOKZ3X6ICXXBQR7",
	"PFTQS7JNU2Q3Q6L4CGBXVLOYNE",
	"A4MZ7CCVYQUDJ2AFHNXBBQ3D24",
	"CPUB5R3ORTCMSMCLUQURE6AN5O",
	"NF5E7U3DFTXWFFXXHUXTEP4VZQ",
	"AWB5WDFERWSSJG53YGJMDORQKR",
	"U5JQUILKD6SEL6LXAMNFZP6VSW",
	"M45NLOAFLO74EJKG5EXNET6J5Y",
	"P2KTEUMZ5DZZMYSPOHDR2WJXAN",
	"KVO7AXZNFBUBPYLOTZQQ42TFNS",
	"WGJJ7SAEV6SBBWWYS4BTLD63WM",
	"Y6GURVDV4ESRBPWSTV25T4PE4K",
	"ESK7MPFPUZ5ZAQ52RP4SQIYCCC",
	"623M3CIABZ3RANERQ2IREXAVYO",
	"OQ4CQCFO42RS4BMMSGSDLUTOQO",
	"AMFHRDVGM6G2TIR3TKIFGFSDVM",
	"7VVSGGCVC53PLOYG7YHPFUJM5X",
	"Z3HMESVL7EZUSZNZ33WXEBHA2N",
	"AWWVRQD5W7IBSQPS26XOJVDV5H",
	"OQBZ5ZST3U3NZYHSIWRNROIG6L",
	"II573BW7DJLBYJSPSYIABQWDZD",
	"MOKXOQFOCUCLQQH4UKH2DPE7VN",
	"XR54NGUOU6BBUUTINNWBPJ35HX",
	"DNK36COZGFXI6DY7WLCNUETIRT",
	"R5M2PV7E3EHEM3TLGRCL3HSFMC",
	"ITKENZQYDQMZFCUPOT7VF3BMU7",
	"5GDCB74PPPHEP5N5G3DVRCYT7R",
	"ZMKXVRPLI5PY5BDVEPOA3NQZGN",
	"GBLIALWTHTUDTOMDERQFVB77CS",
	"VKRTTXUTFOK4PJAQQZCCT7TV3T",
	"ZJBUJJ4SW62BXOID3XO2W2M2PF",
	"SKWT5T6QJTCD3FCINIK22KMVBJ",
	"EHINNU6L33HRLOOJ3A2XFJSYQL",
	"N4HRQJEFPAT5SU3YPO74WSMQIR",
	"TGPTZ3ENMFWB5CZKJFR5WHIRI4",
	"O4HNFTAUJJ2LZPQXPXRAXOVABA",
	"4JVB5STP2YG5GYOXDWIF4KCKFB",
	"MY554X3YZHBECLHNNZ7A3SPJTU",
	"ASCJMAH7VCQAD2QJSWXPSVSM3H",
	"NBNGL5DZ623KCG2JNZFGZMZ7KD",
	"KGMZSW35AEQOJ6FA7IR7BHZI52",
	"Q7QUHHS4OJFMJ4I3FY6TDKSMZQ",
	"MZAE7TOEXAS76T7KIC73FEYRU4",
	"2BVESR3REAWADCGYOYM7T646RG",
	"EK3L2ORP4LT3HU3EMXDSQWFOKJ",
	"3X4A6VMGMIDLVK72FZSDHSERWY",
	"I3UHWI6M6HQFRBSQ6W2SABUNUP",
	"REKPXW4DIB4MTKMPHN3RBVHVME",
	"W37FNFZE35NX65Z7CVQ7L5U4L5",
	"4AGYK6U2KP6RAOADCBUDDCBECV",
	"IXM4SFQUDW2NOTXZIPWTNGET3F",
	"6YE4G3VELF27MN3Z5B4VIQ3XYK",
	"LPOZCPZAG3MD47MIWGR4FIOCDH",
	"WGREKUL2LD7C7SYGKH7APIY2A6",
	"WWW277FKTKUXQMP4BECSRHLWJI",
	"UYE4IQPMSTXVQG7EJALKWWEGDN",
	"TIV2L5Z6K7SNGNUVWSNKTAF4UE",
	"I3FQOAW3PINUK26P62HCX657FO",
}

var benchmarkMessagesMLDSA65 = []string{
	"NDGEUBUDWGRJJ3A4UNZZQOEKNL",
	"ACGYQUXN4POOFUENCLNCIPHFAZ",
	"Z3XETEYKROVJH7SIHOIAYCTO42",
	"DXWCVCEFULV7XHRWHJWSEXWES7",
	"BCR2D5PNLGFYX6B3QFQFV23JZP",
	"2DVP5HNG54ES64QK4D37PWUYTJ",
	"UJM4ADPJLURAIQH4XA6QYUGNJ6",
	"B5WRCIPK5IVZW52R6TJOKNPKZH",
	"7QNL6JTSP62IGX6RCM2NHRMTKK",
	"EJSZQYLM7G7AJCGIEVBV2UW7NN",
	"UFNA2NKJ3QFWNHHL5CXZ4R5H46",
	"QZAXRTT3E4DOGVTJCOTBG3WXQV",
	"KH2ETOYZO5UHIHIKATWJMUVG27",
	"V5HVVQTOWRXZ2PB4XWXSEKXUN5",
	"5LA7NAFI2LESMH533XY45QVCQW",
	"SMF4TWPTMJA2Z4F4OVETTLVRAY",
	"FWZ5OJAFMLTQRREPYF4VDRPPGI",
	"OK3QMNO3OZSKSR6Q4BFVOVRWTH",
	"NQOVN6F6AOBOEGMJTVMF67KTIJ",
	"CCLC4Y6YT3AQ3HGT2QNSYAUGNV",
	"CAZJHCHBUYQ6OKZ7DMWMDDLIZQ",
	"LVW5XDTHPKOW5D452SYD7AFO6Q",
	"EYA6O6FTYPC6TRKZPRPX5N2KQ4",
	"Z6SGAEZ2SAAZHPQO7GL7CUMBAG",
	"FKUCKW6JQVF4WQYXUSXYZQMAVY",
	"LN2KDF4DANPE4SC4GKJ4BES3IZ",
	"AVCRTWB6ALOQHY34XI7NTMP2JH",
	"A5WHIS6CBWPCYIEC6N2MBAOEZ6",
	"JC2BH476BXUQFIDA6UCR5V4G4F",
	"NU6XH6VLSSFHVSRZCYXPFYKYCD",
	"GSUXVZBDDYSZYFGXNP6AZW3PTC",
	"XJPRNJ26XP4MIYH2Q7M7MPZ73M",
	"INUTUP3IRFWIIT23DNFTIYKCFY",
	"T4KH7HKLEYGXHBIRFGFCRUZCC4",
	"GGQX4JFVWZHE5Y73YTLMSSOXNS",
	"BUA4Q3TQZGLVHMMJU62GQOSHLV",
	"WXW3SJXLSZO2MYF4YFIMXL2IQP",
	"Q32XBVVGFQTSXAIDJE6XSEPRZG",
	"6TEXT6SA7INRCTDSCSVZJEQ2YG",
	"ZBN4UL43C3SJIG4HYR236PXCVS",
	"TVWPLLC7NROBREWOM75VA3XCR3",
	"CCDGL2FURLBABQ4IJBYCB75JFR",
	"XBZGCOVTZHCPAARBTMAKPIE6GJ",
	"TPRAENJ7I54XRIVH6LL6FDIA3I",
	"RKOM3PHFILPIIQZL4ILQWGRYWI",
	"CEEZIZ2WUXHQQFATYYGQ3ZDBTI",
	"SLKOVAP6WLIVJBVU7VZG3ZGEOW",
	"TWMCLJJSWEEQQPQGGDKEJ5SU2R",
	"IFMUXXCD2LC7IGQLZ2QEK5UOQ2",
	"C7IWFEBHW2CXN4XBJS7VLWH3VK",
	"7KJYUEW3F264727TM4LE6RMGDO",
	"BPG2XAPBMBTA4VMPUM7IZVZPK3",
	"Y5X577BWRZNPLNUHJVSKGMUXYB",
	"ZCKMKM23E4IUPTNQDFN2LTLZVX",
	"4RKK223JNBDAP4G5DOAHHZ3VNO",
	"5UZ3TQZHZT22ISTB4WJEVO6MC4",
	"YMVS4HFSJ32CRZRL23PXZUEJFJ",
	"UQEUJUTPSZLZARNBXWMCTMHPFF",
	"CZAAZ5WK7EIPMW7NA3EZNNBF45",
	"227PBHH23WM7F2QLEZSPFYXVW4",
	"YUYS2J5CRFXZ4J4KJT2ZKIZVW3",
	"MFLHZJOZV44SN4AH6OJ3QZWM2O",
	"H2B3CRBCXYN7QWDGYUPHQZP23A",
	"T4L6YWQUQ3CTACENAJ5WUXZWFH",
	"N723H6MUGPZSRZ72C635OD4BP7",
	"NI4TUMVA6LQPQV2TXPN4QOIGBZ",
	"CQI3S4LSTQASSJJVZXEFPOVW7K",
	"ANPY4HJ64LLSB3GK2R4C6WDBS3",
	"RGWQCZKQLMT5FZRDE4B3VMASVK",
	"Q3WCCF2HA3CA4WWRJBMGBW7WI7",
	"2AKJRXFHXLUQPOXPTLSZN5PW4A",
	"IJWOOTI4N7RWXJIHAPXN6KEWEN",
	"4D53T6N6ATOVTD4LKSTAAWBJMU",
	"B4G5HDD6RITG6NIH6FXCRZDYZM",
	"TJCDFKMRUY2OG6KRSMNVCGQFUP",
	"PB33IHQKALAY6H6GVBVLI6ZRXK",
	"SCCWGW2J5S4WL4FTTMQ435F6DB",
	"ZVJH2HSMTLHGXMGPMXLJCKCLLE",
	"62LG37U6JXR77YRZQQCDSBHVCS",
	"BU4CBWOXQ352TEOKIXO245ID4O",
	"UEZOH7KEIODSEVRUF6GMWGA2RB",
	"IPJWROME4GM66CGLUWP5BJ4SX6",
	"355GDC7TG64AZJ7IJX6K62KZCZ",
	"AHTFKX3V7XUB3EWOMQVCGZYGUE",
	"N4RV2GKXJ4SPHHJ52Z7K5EGLER",
	"ZY7V7NE5F66XHDHWM6YNFEWZA6",
	"DIKFO5KAVT4WAP7BOEFM56ZUSR",
	"4TDFOFKDAPIOM3MU5GD7NPXNWQ",
	"AD7YZO756HDK6YWFILAKW3JWA7",
	"NUA53JS2ZK2BGHH3A7BJTJZYW7",
	"QLCNC3AQNKLRMSYR62WQSQP5VI",
	"SJ7OBS7ZYXSGXOYXPE5KW2XKN6",
	"44HBMOGMIMJS63CEXQU7FCXE2E",
	"KCK3J7ZL6QF4SLHHSWTJURK7PG",
	"HLH4CLUGBSOOBSS3BPO62N5MC3",
	"3FNS4GITO6OEUBAVDDXK4WOBTD",
	"IAC3K3I4AQGY3G6UHG7PL2N6TE",
	"KUKLNH74POJI5DYAEWUD7RABTQ",
	"ETM6N7VU3GBSQ7P5MCD6UF3E3S",
	"IZITM5NYBGJZLSI3BI4VEMW43U",
	"46OPQU4LL6N3Z2U7KYPKUMBAGI",
	"EV7YZ5DMAV7VKYJQUFSRD37GPP",
	"AV7W2PGYDJIAKLFVEBL6BXQSGC",
	"M2FOX5QZEZKV4QXKPI5XUZDHEM",
	"R4IFPLVMOVYCHRTR6LXAUGP3LL",
	"JGH6XJUMP4DRVAM27P2JNOKXVO",
	"D2XN3ZLLU6VFPMDYM7NBHSQEOI",
	"2PO3BYENOMQK6SHQDCFSRPJQI3",
	"IBVQ7U3QEUC6PQRE4PV53JTZTK",
	"ZBCOX4P7NG2IXXFB2R43MG2SLV",
	"5NJDPQVVDO7ADNZ2CV7L6QBNGZ",
	"V7ASFIIYUMXFGW4B7ZM6LOGUTE",
	"PX5IJZ7W2LUPKM6YN4PMZ43ZLM",
	"AYK7SZ23DHC7Q56MWAJXBG76LB",
	"UYCAPXJM4HNGKLIDSZ4NCEDJLN",
	"UWMDZ3C2ODLACKGJPGETNQ3TA4",
	"Q6OI6R3WYYJ4CCZCDJBQMCRCZR",
	"LCMJHLP7354APCEGPKE7HHWTWB",
	"N7T7ZKOYPAMEYTTDOWZNCN6PRD",
	"UZADPU4UNHAF7L7LQDMTKA2EQH",
	"DC2OEPQDECVLRVNNCS6BMH4CRA",
	"37IZ427XHUMZ66EJ62U2YEZDAC",
	"6BCZDQZDPZLS5OGESKNUBPSSFV",
	"ST2LEMJ4OLQ32TJTLH2WCWT4WA",
	"GA2TL4SFLEW4G2B5PQMIKJT5XG",
	"L7PPBIET26EH7LQTLEFC4I4EIA",
	"6YSM7MC2W4DEV6ULAHMX27LH56",
	"QL26Z5KZ4YRRG2BXXGDRRLV357",
	"677TWRAJ5NSNHCE243POQPEG7K",
	"66MEBQJLGAGVXDX3KZ2YFTTVJM",
	"6D4VUWAQD6R65ICSDLFAATC67V",
	"7GXLD5CNU3TDUQSSW42SHL7B5D",
	"RQETUMEBG2ZM2NF2EZAQHGHWWE",
	"DCRX5ANWDMXZFIDVAXYLQZYMRN",
	"5SDWT7YAF7L4WWANAGYINZAYXH",
	"PZILRV7I2S6WKUSHKYRLA2JQY3",
	"2G66TK2PZ5MOTAZDN7BFS3LAIH",
	"QOLJ3WGJ6JS3FMMXBNTNAIKXVK",
	"FMAL67YTHDCCYVZ5CRMN2XJPDN",
	"UOTZDXTJKQ3YAIRKHTYNX6G55P",
	"X3DLNPJ3V62LRHGEY4DTT35H3R",
	"DKU7CHNXPB5QRZVGIQZW46XCKC",
	"RAKBD4LQKEDTVDSK3DVTRWG23B",
	"INTRA7BWHLVQMBRKBJNUSMF7MU",
	"AUYRBNVCOYYHOHUYOOFIZ2FWMD",
	"22EJVDEQ7PASLBAMTVKXOQP5RJ",
	"3S6NATWA57SFTZEW7UZUOUYAEU",
}

var benchmarkMessagesMLDSA87 = []string{
	"LQQPGPNUME6QDNDTQTS4BA7I7M",
	"PTYEEJ7RMI6MXNN6PZH222Y6QI",
	"R6DTHAADKNMEADDK5ECPNOTOAT",
	"S2QM7VDC6UKRQNRETZMNAZ6SJT",
	"EYULPTSJORQJCNYNYVHDFN4N3F",
	"YETZNHZ75SXFU672VQ5WXYEPV2",
	"KTSND3JGA4AN3PCMG4455JEXGR",
	"JGE6HK37O6XMWZQZCHFUPNUEXP",
	"CRYB2FZD2BYNANBFFO2HRZEHGZ",
	"7MLNDZJ7OIEPBJZOMULOMQH2BA",
	"4WQCNTIFVSX2DNALMWUKZRA6CI",
	"Y5NK4OBDSDWC5WLL27CEEXYYOT",
	"C4SSWSPBVCDAWJXH2CDMXR36LH",
	"THDBKXRTKWJUGJMAAYTWTFMX7Z",
	"NWXPUD4DAA6QOREW4AFFYQYQNG",
	"3RQIJXMO7WYHBEBL3G6EOLNZNQ",
	"R7JEOHFP2C7O4AVPRPRELXWOMM",
	"LU6MWR7SZXVIKS54BY62X67NPA",
	"FG2FFM4F2ECKHCSJ75KXK632JP",
	"BF76ZDSVVUSYS5KK4FFD22YPS7",
	"HCLBWZRLHEMYZLFWHLAN2BKCZ7",
	"HGFVS4QC7AWXYPVRSWAK77KTQF",
	"LUZ3C53PUUHBWCDJ7WAHK2UT3K",
	"Y3WR6SMDUBW34N3MUT7EQYIJCV",
	"F2X35AQTXVZBMPXTWNAAH4ZX2W",
	"6MKFFDYWD6ZAKS3C6GRCRLZLRF",
	"AFMZYYFRHKMQRNKU5UTSKQ74H6",
	"TDTN7J3O367OVPWLESRNPLN4M2",
	"WYMLD2X6N4CZ2RDOKF5CFTSYTG",
	"UNPTSBLJ6HZRNR72T2VEEHCFX2",
	"SNCM4R2P27AJOXBS67RMCARS3U",
	"OU7QBE5QOXO7CIYTBJR3KOW2WK",
	"2NNQOBQKZ2OD4ZAXI3SNEURYUP",
	"YQTUPOYBT67XPCHIGKSGSKC3BZ",
	"HGB4ZM3G76IXYWWCMVT3HONRIS",
	"WZC6QUKRZZ2TOVA277JYKQITEW",
	"XO2WT46A5HYL6CUJF7SGJ6YWOG",
	"4QJA35PMYQIDRZ7ZHG7RLZJVGF",
	"BMJZELWZ4I2UWXESU3NR6ATC4M",
	"XWLFB7FN6D5PRY6YUXC5JUIBFM",
	"WRAFFF27AVTIOYIBYA2IPTXI3R",
	"VOXUTYTN2XZ362OJFO2R53UCUF",
	"UHN73ARJ737WUJ6QYEI7U46OPO",
	"3Y3K5E2A4ML3VYVNAFWEEIXTSN",
	"QMU4322NKPRLE7JBGYFGS36H2S",
	"NJAQTNCXPVDICTDVUKTPRCD2AX",
	"OC373ZFBNV2H46T6OY3XRPSUHG",
	"UBLAS6CDWE3A662MLKP7QDEOCC",
	"BKFDLAL2RTPMERYVW3B7UJ5W3H",
	"QFKFGXKGW5SAKLBAWQXUWW77OS",
	"EJNUQHTLLOVB4ARETOGLY4WUTJ",
	"N243OCMVLLAO6I2XLCYOIMQYGY",
	"YRRFLWK7ZASUKYX7ZLQMW2PJ6X",
	"3DGVPBWD2BIK6KQE65K72DNJNM",
	"TJRYMNOAIW33VIHKLJG4GXAVUK",
	"6DSRINAYXL34U54U355U7IVFGS",
	"6CHA4MX7LVS77XKRWG7IYC3XVL",
	"GM2CEGBEPBOHAPIOBUWJ4MJNTG",
	"VJKHGBY33VUIJFEQLX3JVUNQBD",
	"DTOHAD5M2KL46IZHE4TPLJWHTI",
	"IYFG3UDN7ROOY2ZFSLM2BU2LMQ",
	"A5OGJHPOE4PW6QSZYHZ5TKPGIC",
	"FX4BCN67AEGCLUTLFPNDL3SQU5",
	"MWIZQVOZOHTTBUXC3BEX62MNI5",
	"BYHVJHBLK4O6LFSKEIQ3CAAKU7",
	"QJU7P6KWSSKAA5GVA6RH4OV7MX",
	"I3T3XM5Z5TAJHAYDQHFA2ZV7PU",
	"L46MQCHV3TJ6FYIQQ2FCJXES74",
	"QXZRQIYAJMXYR6PU3VDYGCIT5W",
	"MFS53RR2XEYS22NYOJLGTHVTTM",
	"FRWIWJRP4AQMXWX4WJ4WYVKM3E",
	"X6GK6IGVLJWYSHLKHGXSW3TJDP",
	"L5LPJ2HIWA4UY6G6FMZXGDEDAM",
	"GD6FYOYUGDHXEQ5S2KLJEGNSN7",
	"ODAL7ZRKXSPAAN5DVRBWJQCFQX",
	"CV3QFBDXBPT3SCPJGUYSMDN6ZS",
	"IGSLSACRZ6XID466KQIB4YNGYO",
	"WZ2EACBN26RAML2S52YXRYP2OF",
	"LB76VEVNOBYFMKFZ7SDFCBCHQE",
	"TLFA7EU3JJFAP6EMUKNV2ZXRBM",
	"SIIJF6OXAKRP25CBUYFBRCDDVP",
	"TEPNI7TJ7HASJWIQMBS4VFLRQC",
	"VK2JINYWEDV7IQFWH4OTAD4W5O",
	"GILUH5AMVE4TM7EKPXJBZGT6EJ",
	"DV7ALFRAW3TI4WMQQLDTO6RNHN",
	"CAIB5G3NXC5ASPLFIWAFPVHS5B",
	"MLFJXZUOAGN7EGPMXOOVTB2CL4",
	"6MZYT3ANWHBOS67WGHZI3QPEAP",
	"LVJDQB52C2PERSSQJRMRCJ4UBF",
	"QY4VKAZAYQIZOX2L2VO2QHAQVC",
	"UAA5SST2XA76JPKM3XOZ5RUHFI",
	"VLZWF53JSQ6SCRUFDKVPXWAS4L",
	"NX2DZIKMJIYXUNSAHFP23FHTBU",
	"F5OAKDDDA34A2RPIKDPM5CYPMZ",
	"E5PEP3ANIK2L4VLOST4NIYNKBD",
	"IPBGFLHSMP4UFXF6XJX42T6CAL",
	"XHPU7DBFTZB2TX5K34AD6DJTK3",
	"2ZU7EJN2DG2UMT6HX5KGS2RFT6",
	"SD5S7U34WSE4GBPKVDUDZLBIEH",
	"WZFFL3BTQAV4VQMSAGCS45SGG3",
	"QE7ZT2LI4CA5DLSVMHV6CP3E3V",
	"YIWMS6AS72Z5N2ALZNFGCYC5QL",
	"A4QJ5FNY54THAKBOB65K2JBIV7",
	"6LORQGA3QO7TNADHEIINQZEE26",
	"5V45M6RAKOZDMONYY4DIH3ZBL2",
	"SVP7UYIZ5RTLWRKFLCWHAQV3Y2",
	"C2UYQL2BBE4VLUJ3IFNFMHAN7O",
	"P4DS44LGP2ERZB3OB7JISQKBXA",
	"A6B4O5MWALOEHLILSVDOIXHQ4Z",
	"DKQJTW5QF7KDZA3IR4X5R5F3CG",
	"H6QFQX2C2QTH3YKEOO57SQS23J",
	"DIF373ML2RWZMEOIVUHFXKUG7O",
	"Z5PPIA3GJ74QXFFCOSUAQMN5YN",
	"PM6XIDECSS5S77UXMB55VZHZSE",
}
