Luminous-Dynamics / Luminous-Dynamics/symthaea

security(control-plane): make attestation algorithm IDs exact wire profiles

Open
#751 1 comment 0 reactions 0 assignees View on GitHub

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

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. 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

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.