Skip to content

Add ML-DSA test vectors that exercise the use_hint function with (1, 0) as input#234

Open
gendx wants to merge 2 commits intoC2SP:mainfrom
gendx:mldsa-use-hint
Open

Add ML-DSA test vectors that exercise the use_hint function with (1, 0) as input#234
gendx wants to merge 2 commits intoC2SP:mainfrom
gendx:mldsa-use-hint

Conversation

@gendx
Copy link
Copy Markdown
Contributor

@gendx gendx commented Apr 17, 2026

Reproduction case for the bug in tink-crypto/tink-go#48.

These hand-crafted tests use:

  • a valid but non-honestly generated public key with t1 set to all zeros,
  • a non-honestly generated signature with z set to all zeros.

These conditions ensure that the verifier obtains a w_approx set to all zeros.

Then all hints in the signature are set to false except the first one, which ensures that a call to use_hint(1, 0) is made.

  • In the valid signature, w1 is computed correctly by using this hint, and a consistent c_tilde is then derived and put in the signature.
  • In the invalid signature, w1 is set to all zeros instead (which is what happens when the using the buggy implementation of use_hint that is fixed in mldsa: fix UseHint edge case for r0=0 per FIPS 204 Algorithm 40 tink-crypto/tink-go#48), and an inconsistent c_tilde is generated. Compliant implementations therefore reject this signature, whereas buggy ones accept it.

(In other words, the difference between the valid and invalid signatures is the value of c_tilde.)

@gendx gendx changed the title Add test vectors that exercise the use_hint function with (1, 0) as input Add ML-DSA test vectors that exercise the use_hint function with (1, 0) as input Apr 17, 2026
},
{
"type": "MlDsaVerify",
"publicKey": "2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b2b0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000",
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vectorlint is failing because these are currently missing publicKeyDer, the SPKI representation. (BoringSSL uses this in one of our test harnesses.)

Copy link
Copy Markdown
Contributor

@davidben davidben Apr 17, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In a pinch you can construct it by just prepending the right prefix to each key. I believe they are:

  • ML-DSA-44: 30820532300b06096086480165030403110382052100
  • ML-DSA-65: 308207b2300b0609608648016503040312038207a100
  • ML-DSA-87: 30820a32300b060960864801650304031303820a2100

And then to spot-check them, you can echo .... | der2ascii -hex with https://github.com/google/der-ascii

@FiloSottile
Copy link
Copy Markdown
Member

Ah! Thank you for generating and contributing this vector!

I had been trying to get coverage for h=1, w_approx={-1, 0, 1} and had found no good way. This covers 0, any way to cover 1 and -1?

Also, I had instead resorted to exhaustively testing all use_hint inputs. Could you check if https://github.com/C2SP/CCTV/tree/main/ML-DSA/accumulated#field-operation-tests would have caught this bug?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants