Skip to content

Composite ML DSA Signatures - #1690

Draft
johnpeck-us-ibm wants to merge 6 commits into
IBM:mainfrom
johnpeck-us-ibm:CompositeMLDSASigs
Draft

Composite ML DSA Signatures#1690
johnpeck-us-ibm wants to merge 6 commits into
IBM:mainfrom
johnpeck-us-ibm:CompositeMLDSASigs

Conversation

@johnpeck-us-ibm

Copy link
Copy Markdown
Member

This adds the Composite ML DSA Signatures which are a combination of ML DSA and traditional Signatures like RSA, EC-DSA, etc.

Signed-off-by: johnpeck-us-ibm <johnpeck@us.ibm.com>
Signed-off-by: johnpeck-us-ibm <johnpeck@us.ibm.com>
Signed-off-by: johnpeck-us-ibm <johnpeck@us.ibm.com>
Signed-off-by: johnpeck-us-ibm <johnpeck@us.ibm.com>
Signed-off-by: johnpeck-us-ibm <johnpeck@us.ibm.com>
@johnpeck-us-ibm johnpeck-us-ibm self-assigned this Jul 31, 2026
@johnpeck-us-ibm
johnpeck-us-ibm marked this pull request as draft July 31, 2026 18:00
Comment on lines +312 to +316
buf.write(DOMAIN_PREFIX);
buf.write(0x00); // separator
buf.write(oidDer);
buf.write(0x00); // len(ctx) = 0 (empty context)
buf.write(msg);

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

I have been implementing this draft, so I looked closely at the domain separation here. This M' does not match draft-ietf-lamps-pq-composite-sigs (currently -19, section 2.2), which specifies:

M' = Prefix || Label || len(ctx) || ctx || PH(M)

Three points on the construction in this method:

  1. Prefix: the draft fixes it to the ASCII string "CompositeAlgorithmSignatures2025" (32 bytes), but DOMAIN_PREFIX here is "CompositeAlgorithm" (18 bytes).

  2. The buf.write(0x00) marked "separator" is not in the draft: Prefix and Label (the DER OID) are concatenated directly. The next 0x00, standing for len(ctx) of an empty context, is correct.

  3. buf.write(msg) signs the raw message, but the draft signs PH(M), the per-algorithm pre-hash from section 6 (for example SHA-512 or SHAKE-256 depending on the pairing).

The effect is that these signatures are self-consistent, since sign and verify use the same construction, but they would not verify against another conforming implementation or against the draft's test vectors. The current tests are self round trips, so they pass without surfacing it. Adding the draft's Known Answer Test vectors as a test would catch all three and keep the construction pinned to the spec as it evolves.

I have a working construction and the vectors on my side, so I am glad to help wire up a KAT test or sanity-check the M' bytes if useful. (The verify side, for what it is worth, correctly requires both components.)

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.

2 participants