ACVP ML-DSA Specification Rejection Cases KATs

883 views
Skip to first unread message

Filippo Valsorda

unread,
Nov 3, 2025, 11:20:26 AMNov 3
to pqc-...@list.nist.gov
Hello,

The ACVP ML-DSA JSON Specification includes a table (Table 1) of KATs which are supposed to each "cover all rejection outcomes." It is extremely useful to have these available! However, it looks like only the ML-DSA-44 vectors actually cover all rejection outcomes, while the ML-DSA-65 and ML-DSA-87 ones cover mostly zero to two rejection outcomes.

Below is a mapping of test vector (with the first few bytes of the seed) to rejection reasons. Note how the ML-DSA-44 vectors cover all four outcomes, while only one ML-DSA-65 vector covers all three outcomes (ct0 rejection is only reachable in ML-DSA-44), and no ML-DSA-87 vector covers the h rejection outcome at all.

ML-DSA-44 5C624FCC... -> (h, r0, z, ct0)
ML-DSA-44 836EABED... -> (z, r0, h, ct0)
ML-DSA-44 CA5A01E1... -> (z, h, r0, ct0)
ML-DSA-44 9C005F15... -> (r0, ct0, h, z)
ML-DSA-44 4FAB5485... -> (z, ct0, r0, h)
ML-DSA-65 CCD61917... -> (z, z)
ML-DSA-65 C6315FC7... -> (z, r0)
ML-DSA-65 F005E473... -> ()
ML-DSA-65 F215BA22... -> (h, z, r0)
ML-DSA-65 A8E6C084... -> (r0, z)
ML-DSA-87 5AC68A41... -> (z)
ML-DSA-87 E45F9CC0... -> ()
ML-DSA-87 5E37A143... -> (r0, z)
ML-DSA-87 51DF520B... -> (z)
ML-DSA-87 6857AF5C... -> (z)

Some discrepancy could be explained by the order in which checks are done (although I believe I "adhere strictly to the pseudocode in Algorithm 7 ML-DSA.Sign_internal() [FIPS204]" as suggested in the document), but there is just no way a vector which never rejects, like ML-DSA-65 F005E473..., is covering any checks.

I also doubt I am using the vectors incorrectly, because the signature hashes match (but it's possible I am getting something else wrong!). Were the ML-DSA-65 and ML-DSA-87 vectors generated incorrectly?

Thank you,
Filippo

Filippo Valsorda

unread,
Nov 3, 2025, 12:24:51 PMNov 3
to Stephan Mueller, pqc-...@list.nist.gov
2025-11-03 17:29 GMT+01:00 Stephan Mueller <smue...@chronox.de>:
Am Montag, 3. November 2025, 17:19:53 Mitteleuropäische Normalzeit schrieb 
Filippo Valsorda:

Hi Filippo,

> I also doubt I am using the vectors incorrectly, because the signature
> hashes match (but it's possible I am getting something else wrong!). Were
> the ML-DSA-65 and ML-DSA-87 vectors generated incorrectly?

For my implementation, I also did not trigger all rejection code paths. But 
that may be possible depending on your actual implementation.

Hi Stephan,

While the rejection reasons can be implementation dependent, the rejection count is not. Some of these vectors reject zero times, so I really think they might be wrong.

Given this is a pretty official document, I think the vectors should be fixed if they are broken.

I have created test vectors that hit all rejection code paths for all types of 
ML-DSA (pure, pre-hash and external mu). Maybe they are of help to you? You 
can find them at [1], look for the files *_rejection_vectors*.

A description on how to get to those vectors is given at [2].

Great! Do you mind contributing them to https://github.com/C2SP/wycheproof, or would you mind me doing so?

I am trying to collect vectors from various sources so implementers don’t have to figure out multiple formats.

> Thank you,
> Filippo



Ciao
Stephan




Stephan Mueller

unread,
Nov 3, 2025, 1:19:34 PMNov 3
to pqc-...@list.nist.gov, Filippo Valsorda
Am Montag, 3. November 2025, 18:24:03 Mitteleuropäische Normalzeit schrieb
Filippo Valsorda:

Hi Filippo,

> 2025-11-03 17:29 GMT+01:00 Stephan Mueller <smue...@chronox.de>:
> > Am Montag, 3. November 2025, 17:19:53 Mitteleuropäische Normalzeit schrieb
> > Filippo Valsorda:
> >
> > Hi Filippo,
> >
> > > I also doubt I am using the vectors incorrectly, because the signature
> > > hashes match (but it's possible I am getting something else wrong!).
> > > Were
> > > the ML-DSA-65 and ML-DSA-87 vectors generated incorrectly?
> >
> > For my implementation, I also did not trigger all rejection code paths.
> > But
> > that may be possible depending on your actual implementation.
>
> Hi Stephan,
>
> While the rejection reasons can be implementation dependent, the rejection
> count is not. Some of these vectors reject zero times, so I really think
> they might be wrong.
>
> Given this is a pretty official document, I think the vectors should be
> fixed if they are broken.

I do not want to speak on behalf of NIST, but I was told that in their
implementation all rejection code paths were hit.

> > I have created test vectors that hit all rejection code paths for all
> > types of ML-DSA (pure, pre-hash and external mu). Maybe they are of help
> > to you? You can find them at [1], look for the files
> > *_rejection_vectors*.
> >
> > A description on how to get to those vectors is given at [2].
>
> Great! Do you mind contributing them to https://github.com/C2SP/wycheproof,
> or would you mind me doing so?

If you know how to roll in the patches there, I think I would like to ask you
to do that as I am currently in development to get the Linux secure boot using
leancrypto to be covered with PQC.

>
> I am trying to collect vectors from various sources so implementers don’t
> have to figure out multiple formats.

Feel free to take any number of test vectors from the repo.




Ciao
Stephan


Filippo Valsorda

unread,
Nov 3, 2025, 1:39:15 PMNov 3
to Stephan Mueller, pqc-...@list.nist.gov
2025-11-03 19:19 GMT+01:00 Stephan Mueller <smue...@chronox.de>:
Am Montag, 3. November 2025, 18:24:03 Mitteleuropäische Normalzeit schrieb 
Filippo Valsorda:

Hi Filippo,

> 2025-11-03 17:29 GMT+01:00 Stephan Mueller <smue...@chronox.de>:
> > Am Montag, 3. November 2025, 17:19:53 Mitteleuropäische Normalzeit schrieb
> > Filippo Valsorda:
> > 
> > Hi Filippo,
> > 
> > > I also doubt I am using the vectors incorrectly, because the signature
> > > hashes match (but it's possible I am getting something else wrong!).
> > > Were
> > > the ML-DSA-65 and ML-DSA-87 vectors generated incorrectly?
> > 
> > For my implementation, I also did not trigger all rejection code paths.
> > But
> > that may be possible depending on your actual implementation.
> Hi Stephan,
> While the rejection reasons can be implementation dependent, the rejection
> count is not. Some of these vectors reject zero times, so I really think
> they might be wrong.
> Given this is a pretty official document, I think the vectors should be
> fixed if they are broken.

I do not want to speak on behalf of NIST, but I was told that in their 
implementation all rejection code paths were hit.

If we interpret the text as saying that every vector hits every rejection code paths, I don't think that's possible (unless I have some really non-obvious bug in my test harness). None of the vectors reject more than twice, and the rejection count can't be different between implementations (or the signature hash would come out different).

I also instrumented the code to print all possible rejection reasons at every rejection, and none of the ML-DSA-87 vectors ever produce a hint with more than ω non-zero coefficients, so independently of the implementation, I don't think they can possibly hit that code path.

ML-DSA-87 5AC68A41... -> (z | r0)
ML-DSA-87 E45F9CC0... -> ()
ML-DSA-87 5E37A143... -> (r0, z | r0)
ML-DSA-87 51DF520B... -> (z | r0)
ML-DSA-87 6857AF5C... -> (z | r0)

> > I have created test vectors that hit all rejection code paths for all
> > types of ML-DSA (pure, pre-hash and external mu). Maybe they are of help
> > to you? You can find them at [1], look for the files
> > *_rejection_vectors*.
> > 
> > A description on how to get to those vectors is given at [2].
> Great! Do you mind contributing them to https://github.com/C2SP/wycheproof,
> or would you mind me doing so?

If you know how to roll in the patches there, I think I would like to ask you 
to do that as I am currently in development to get the Linux secure boot using 
leancrypto to be covered with PQC.

> I am trying to collect vectors from various sources so implementers don’t
> have to figure out multiple formats.

Feel free to take any number of test vectors from the repo.

Sweet, thank you. I will credit them to "leancrypto.org".

Filippo Valsorda

unread,
Nov 5, 2025, 11:28:21 AMNov 5
to Stephan Mueller, pqc-...@list.nist.gov
In case NIST wishes to fix the vectors in the ACVP specification (which is also referenced by IG 10.3.A), here is a set of 5+5 vectors for ML-DSA-65 and ML-DSA-87 in the same format as the broken ones. Each of them hits all three conditions exactly once, and each candidate can only reject due to the one condition, so these will test all paths regardless of implementation details.

They are released in the public domain according to the terms of the CC0 text.

ML-DSA-65
C8CD132C4189AFB14B2109F7983CB9965FA71A187CB83451713597A1DF7E2A81
EC61C5B653203677CA4CF39F537D8B38C7AA777A0B0B46130FCD24540861E79C
A543259C30E2CBB447FCFB59E89101EC1315277EC3E6E7E83323F0B550BFE091
04E59B88AAB5DDC2D12BD12A2C0813ECF57A60072FD4BE854E505E6C4824F19A

ML-DSA-65
0BCAA26794DFA6F1D60384D35BA0F21F825BDF5F166A41ED8E2C34CA4AAF30A6
7D35C0F180F2DF7FB3C74BAB828C463BD05CCFA89404A5CA48C73ED3CD3A69A4
293EB65DAD83EA5832FAAD29720583C7D5A0312EEF48FFD43D08D160AFD3E7AA
3572805E4CA991D7E4B5D3D4B41ECC9594FEFE845F9D80CCABDFEB37940EBFAE

ML-DSA-65
22303A0BC7E4EDCB96845B1F5F42F5B57F03288613F975D80A655B9E7A264A5C
E7E8DF282EB402964B4BDA5DAC119C8C924534DD7EC95F2B68F5B6C3BD126E2E
182DA7B7812AF0CCD24F29922C58999FC2B3F1CBFF0C23EE555F1002A4733135
D14EECC68B5C31EDACA3D75B5914087ABC75C8F641FE144011CE31583EFC023D

ML-DSA-65
CCA957BC619DDB76605B9CDC1A5443F74C2ED85BAAF09F056C7A8EAF0F4098EF
DCB5068283BE5543C0A3CD94DE00E87819F038E20EE9F68E2324535CB9CF317A
D686A4B76A5155E6E1AB4584D53D549460E37297930FB951C764FADE2257230F
84CF78398193FAE7F779CBEB5BDEB39DCFCFFAB0476A9E0D19A03A29A74A2BB3

ML-DSA-65
18C158AA15B652EC8D107B2BB31E0CB3B4AEAC8A930D830E857D7DB16BF5695A
79A12A78857C477563CBA9C531B0BEEE9CD4440DC71565CF6D1820787197AC6A
1F69F6B17E98C20D8EFAE04A278BAB91EC4ABDF50EA30F4053A2D62D1D80E2B6
490F8C844DF590DB470B976D4DB5E691448309981053E7EE5BA6199F545D3823

ML-DSA-87
C2E2A69532BD584B13E5E434FBF3510554E25C512305F814FA02B4882745FED9
AFBB226A0517CF0F1B3E4203B1063272510ECA6F94AE0A91018604C4D7E1BA32
38C4C64C5BEB0332C1F633A600D538A8EE727D5C90DED8F5980C3F83FCE1A506
8863840B0736894C4FEF766417C1A655CDB76D41144C431D2BFBA717C6E1D114

ML-DSA-87
57E3605BB8D4158E4F2E1D266FA403AD1D4155C1E93D6C5944DB62D105AD2938
F6E8A062F9C4FB2E909D0AE04738F68B90B984F6E6FE0289E5100562C3ADD323
1D379548CC6D74DBD4184C730B7229770C6413877A142036748A468AF39A8EA2
C70D8458DB2F22BA832DC702FC5112BE15AD9CAA5E3CC2A7D199E7396A4B8122

ML-DSA-87
B640C6759CBFFCB7A6A22F43061B62692AF25E51303AAD1BDA2097F48156112B
3533BC008B32A9FAE59575A292D343270D98A2C7FF49B5EBFD0DD9DB8E6BED0B
480AE04B33FF212A6BC4FC5B8B33E44F2B89636FB602B2132467DB080585E02E
9F14839E17893F88EA549861F24904225338FA30AB6FDD3FC44378039164D465

ML-DSA-87
3D5BECA6A5497E667B70A42A14A6695454AE20FF4FC967A65E0B91AA3C13FDE6
42C47B5233A6015BF729FC3C7594F5388F546F8457D591C0D06CD3589E5EA391
CDEB18F0DCBE7FBE6A2E3826EE493D2BED386775E60BA6B92BD4F61D79B18889
B1F702BF9D4A23C184F79D7747F0BD0F2402C104D6509D49B9C80DABD264D9A9

ML-DSA-87
ECF3B0C79E39BA49075CC03FB82772973166F64B22DFE56E4D42519E170F6654
37C3F4047B0683044762222999864D1D0E1794A107FFC27F37A906662769594A
A2420EA07028D47F8A61D65030FB9AC052BED30E455F80BCF5A593EE8495E324
87A60CCA24A5C7873F5172EAFD5BE3585CE35D46219F433A55A1BF8279DF8F75
--
You received this message because you are subscribed to the Google Groups "pqc-forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pqc-forum+...@list.nist.gov.

Ben Livelsberger

unread,
Nov 6, 2025, 12:11:25 PMNov 6
to pqc-forum, Filippo Valsorda, Stephan Mueller

Hi Filippo,

I just saw this thread. 

One small note that there is more than one group at NIST involved with PQC. The CT Group develops algorithm standards. The Cryptographic Algorithm Validation Program (CAVP) is generally responsible for creating KATs and for writing conformance tests for those algorithm standards. 

CAVP generally does not follow topics on pqc-...@list.nist.gov closely, whereas the CT Group does. But if you raise a CAVP-related topic on this forum, I'd expect the CT Group would forward that topic onto CAVP. As it happens, the CT Group is shutdown and not working right now, but the CAVP team is working full-time. 

The ACVP ML-DSA JSON Specification is a work-product of the CAVP, but now that I'm looking at it, we're not doing a great job of letting people know who they can contact w/ questions. We'll look into improving that.

I'll forward this conversation to Chris Celi. Chris wrote the CAVP ML-KEM testing and JSON Specification and will be able to answer your question. You'll hear back from us shortly.

Best,

Ben

To unsubscribe from this group and stop receiving emails from it, send an email to pqc-forum+unsubscribe@list.nist.gov.

Celi, Christopher T. (Fed)

unread,
Nov 6, 2025, 5:18:06 PMNov 6
to Filippo Valsorda, pqc-forum
Hi Filippo,

Thanks for letting us know. From some initial testing, I’m getting the same. The ct0 test cases appear fine but the others are not. We will update this next week at the latest. 

Thanks,
Chris Celi
CAVP Program Manager

--
You received this message because you are subscribed to the Google Groups "pqc-forum" group.
To unsubscribe from this group and stop receiving emails from it, send an email to pqc-forum+...@list.nist.gov.
To view this discussion visit https://groups.google.com/a/list.nist.gov/d/msgid/pqc-forum/c7a483b3-ec51-4ac4-9f4e-f5de8ff52167%40app.fastmail.com.

Celi, Christopher T. (Fed)

unread,
Nov 13, 2025, 4:57:23 PMNov 13
to Filippo Valsorda, pqc-forum, Stephan Mueller, cavp
Hi Filippo,

Here are some new tables for ML-DSA-65 and ML-DSA-87 for test cases that cover all rejection paths… I will work on adding these to the specification on https://pages.nist.gov/ACVP soon. Additionally, while tracking down the bug, I discovered that the ML-DSA-65 and ML-DSA-87 test cases for the total number of rejections also have issues. Those are harder to regenerate and will take some time for us to update. 

ML-DSA-65
Seed
Hash(pk || sk)
Msg
Hash(sig)
25C3C1CEED69CFDE12427E577880BD5BED091024C3832E003BC6AA3C68514316
530AF0637CA02AC3D3DD6F07C5D7C27A26C5CC8D0C01DFFBA760AB095D3DC0FC
7490020E9E5EE8F6CF3E629007D6C292F382CACFA79DEF37780EF7ADD2327B13
5B2F8B0FA7CAEA4DE53CD78038C38803368C0242D5F81186C7A6B2E209A85C3B
6A4EBFB83146029A16695AAC294E829E4507D3693239239398F836E700B47107
58087EB28270FA8D11348A64546E26C0282805069E5EAD58C53469FA7F658561
2687F0F482714DD717BB9E7A0DFC2CB1CC3B1BE1917558AE05754ED58AC84D95
D3BBE2B6CA8F2904D7960944706773DDCA42F69C6AC88B67B659DFA50C5B309C
30278EF1C04B8285A53561F10AB5F72A7570BB10F2A3C651BC8ECF57EC072399
80DCCEE68C067BED04EED100A6D631C559B7284D126DBF9D6F57FAA7C615EF2A
977C26EA68A4DABE1EA3F5FD9973A608FCBBA0CD5075B64A37E98E2EDE2EC122
7CDC9D0049E3B2EF68AB9AABB48DEE96F0A8BB566E2B0758DB906F476E55CD8F
D4C7EFCAD10C3DF23917D594683C3B37E1930A75A5D31D0A2AE006251F7FB3FB
768C14CF93F1DE8A48A33FC3686747A6FE3C462E7EBA3160BB491AF988931144
54468E50EF4B103A79E616D211A7F7E23784637805F8F733C923835AE9F24751
9042227CFF28EF4ED08C8AC3A65806BFAD325EF8FA58915C83250EDEBAD6F012
142232202912E71ABF015967CBC7D4D8BB0D1991C5124F6DE4C3811FED3710C1
D185C94F2A62B8A681B3034A0103C47CDF7295CF14A657CC0A9EC600520A33D6
1A3FEAA000D767C4358681FE9BC2D0D54B5F52375E94B8BE0ADC960491D87962
AC7F01613E77284266DDFC61E2BCA0BAC93E7CBD54D810DFCC2B18F32C07FA2C


ML-DSA-87
Seed
Hash(pk || sk)
Msg
Hash(sig)
C7D9B536DC97EEE49317BE80F441164E5AAC6306EDFF5EF15582CA7AF3ECF016
3213E5876AD9721E37784D3217B45FC7D37A7F63A709930F0BF068B07B110477
CFAF1944CB7ADD2B225B3E3E2880B831B32B18B463524047B8931CDC7F3E564F
075AC2BC258A22687F5334093E2E48FD77CE5C283313ED5C0A0B4D8516BD208D
8BBF2FC9FC12994D9A8DE928BA44AD2F9F516296ACEDE9A264573D1B6F7350A3
DBC9B0F97361044ECF0073455EB9A7D7FF792A2CD0A1297BF6ACE1454BCA871F
82A554AAA7BBF11F87C52208D42B5E52E468A625C94EC6F5F1A264B77EB83358
0463C0CEE12F73B60C7434F960128387DB30953B22971ABFE1D2BB0E93F24086
0AFABB98CD7D55D7C1014D494C55BD4412272F2A067CA7672C2FE15900F250E8
7C6EA7F44053D82955D8C95C300B3578AA5D90EE61CD139A494A919508F9FFA5
692FC3466F4CD86B30EAAB6A460E98B8E497F5444C0CFCE6D045769F67CDA7C2
72E8F2712157CFDDC7EA0E8498AD8A3897C6CB4ABA47B972211ADA3650DDBC69
75E920BBA91B644E3260987437E5D551B453E4AD4AFE29A313925861192C6744
0A6E545F7EB752B8E5B08C1A464E34C62B55E65A82A331B6450AF92380F6B421
A6C9FABF19DBB285F799967FEE57E296075961AD948B4CB434889433BD63A8AE
AE7421EACCE78203A141EEF3B0EC15FC458FEFE8A842D50C063C9D0F14724DF8

Thanks,
Chris Celi



Reply all
Reply to author
Forward
0 new messages