Luminous-Dynamics / Luminous-Dynamics/symthaea
security(control-plane): make attestation algorithm IDs exact wire profiles
Nobody has claimed this yet.
- Dominant language
- Rust
- Stars
- 9
- Forks
- 1
- Avg merge
- 15m
- Merged PRs (30d)
- 8
Description
Finding
The new generic control-plane attestation candidate #746 currently defines semantic algorithm variants:
Ed25519
MlDsa65
MlDsa87
and delegates concrete verification to AttestationTrustVerifierV1.
That is not precise enough for an authority/evidence protocol.
The portfolio already has a concrete counterexample: Mycelix #252 found one AlgorithmId::MlDsa65 denoting both legacy Dilithium3 and final FIPS 204 ML-DSA-65 representations. Final FIPS 204 signatures are 3309 bytes for ML-DSA-65 and 4627 bytes for ML-DSA-87, whereas the earlier draft/Dilithium-compatible sizes were 3293 and 4595 bytes.
Therefore a provider convention such as “I interpret MlDsa65 correctly” is insufficient.
Required invariant
one attestation algorithm/profile ID
=
one exact signature scheme
+ one exact wire representation
+ one exact message/prehash/context mode
No compatibility aliases may satisfy the same ID.
Recommended v1 direction
Either:
Option A — exact profiles now
Rename/freeze variants along the lines of:
Ed25519Rfc8032Pure
MlDsa65Fips204Pure
MlDsa87Fips204Pure
and explicitly define any context/prehash semantics used by the control-plane signer profile.
Each profile should expose/freeze at minimum:
stable canonical tag
canonical protocol name
exact signature byte length
message mode (pure/prehash)
context policy
For FIPS 204 pure profiles, the control-plane contract should explicitly state whether ML-DSA's context parameter is empty/fixed or separately bound. Do not leave that to provider convention.
DetachedAttestationSignatureV1::validate_protocol_bounds() should reject a signature whose wire length is not exactly the selected profile's required length before provider verification.
Option B — PQ unrepresentable in v1
If we do not want to freeze the full FIPS profile now, keep only an exact Ed25519 profile in v1 and add ML-DSA through a later protocol revision after the wire/profile contract is qualified.
Do not ship ambiguous MlDsa65/MlDsa87 tags merely for future-proofing.
Required regressions
- exact profile tag/name/size values are frozen;
- FIPS ML-DSA-65 accepts exactly 3309 signature bytes and rejects 3293;
- FIPS ML-DSA-87 accepts exactly 4627 and rejects 4595;
- a legacy Dilithium3 signature cannot satisfy an ML-DSA-65 profile;
- prehash/hash-ML-DSA cannot silently satisfy a pure-ML-DSA profile;
- wrong context semantics cannot silently satisfy the selected profile;
- signer alias/relabel tests from #746 remain valid after profile tightening;
- provider implementations are tested against the exact profile rather than a free-form algorithm name.
Relationship to #746
Treat this as a merge blocker for concrete cryptographic use of #746.
#746's lifecycle/currentness/domain/signature-identity semantics remain valuable, but its provider boundary must not become an escape hatch from exact crypto wire identity.
A green #746 CI run would qualify only the current semantic software contract, not an ML-DSA provider profile, until this issue is resolved.
Cross-repository alignment
This should align with the same invariant as Mycelix #252:
one algorithm identifier
=
one exact cryptographic scheme + wire representation
Prefer shared normative names/test vectors where appropriate, but do not introduce a runtime dependency merely to make implementations agree.
Non-scope
No private-key storage; no provider implementation required in this issue; no requirement to select PQ for every attestation; no claim that ML-DSA is currently qualified in Symthaea; no effect authority.
Related: #733, #746, #628, Mycelix #252; Luminous-Dynamics/luminous-dynamics#44.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with candidate #746 and DetachedAttestationSignatureV1::validate_protocol_bounds(). Define and freeze exact profile tags, names, sizes, message modes, and context semantics, then cover the listed ML-DSA length, legacy, prehash, context, alias, and provider-profile regressions. Confirm that #746's signer-alias tests remain valid after tightening.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- rust
- Domain
- backend-api-design, cryptography, security
- Issue type
- Feature
- Difficulty
- 5/5
- Estimated time
- Over a week
- Activity status
- Active
- Clarity
- Mostly clear
- Newbie friendliness
- 30/100