Carried over from SPEC-COVERAGE.md, and now sharper because the crypto draft exists and is being actively edited.
draft-jms-mole-protocols-00 §4.1.2 states the problem and declines to solve it:
Either [CRYPTO] adds a session identifier to its messages or this document mandates connection reuse.
It picks neither. Implementations therefore cannot agree on how an Anchor ties exchange two to exchange one.
Why now: draft-authors-mole-crypto.md was merged upstream on 2026-07-15 (PR #38, closing issue #31), and its two-round issuance is exactly where a session identifier would live. PR #39 ("Add more text to try to define proof") is still open. There is a window in which this lands as a design input rather than a retrofit.
Implementer's evidence, from this crate: the trait boundary in src/crypto.rs hit the ambiguity at the type level before any crypto existed — IhatAnchor::sign returns (Vec<u8>, Self::State) and IhatAnchor::prove consumes that State by value, because the drafts give nothing on the wire to correlate with. The experimental profile inherits this: correlation is implicit in the Rust call sequence, which is exactly what a network protocol cannot rely on.
This interacts with #9: whatever correlation mechanism is chosen must not let a Client replay exchange one against the same Anchor state, or the secret key recovery there becomes reachable.
Action: report to Moderation-of-unLinkable-Endorsements/internet-drafts. Tracked here so the local workaround is documented either way.
Update — upstream PR #39 (open, unmerged): the structures now exist and none carries a session identifier
This is the update that makes the issue concrete.
draft-jms-mole-protocols-00 §4.1.2 offered two ways out:
Either [CRYPTO] adds a session identifier to its messages or this document mandates connection reuse.
PR #39 defines all four grant messages for the first time:
struct { Yprime Point } ClientFirstMessage
struct { Zprime Point Cprime Point T1Prime Point
T2prime Point proof bytes<0..2^16-1> } AnchorFirstMessage
struct { eprime Scalar } ClientSecondMessage
struct { rprime Scalar aprime Scalar bprime Scalar } AnchorSecondMessage
None of them carries a session identifier. So the first branch has now been foreclosed by omission — the messages are specified and the field is not there — which silently forces the second branch, mandating connection reuse, without either document saying so or the HTTP transport draft providing for it.
This is no longer "the drafts have not decided." It is "the drafts have decided by accident, and the consequence is unwritten."
Why it is worth raising now rather than later: adding a session identifier to ClientFirstMessage/ClientSecondMessage is cheap while the structs are new and unimplemented, and expensive once anyone has built against them. PR #39 is open.
Interaction with #9: whatever mechanism is chosen must not let a Client replay ClientFirstMessage and have the Anchor re-derive or reuse the same a', t', or the key-recovery there becomes reachable through the correlation layer. Connection reuse happens to prevent this; a session identifier does not, unless the Anchor also binds its state to it single-use.
Update — the reference implementation confirms the gap
ihat-rs carries the correlation implicitly in its Rust type-state machine:
each step consumes the previous state, so the steps can only run in protocol order.
Its SignatureRequest / Signature / ProofRequest / Proof wire structures carry
no session identifier, exactly as PR #39's do.
That is fine for a library used in-process. It is not a protocol: over a network,
"the call sequence guarantees correlation" is unavailable, which is precisely what
§4.1.2's unresolved choice is about.
crypto::exp_ihat inherits the same shape, and the same limitation.
So the position is now: two independent implementations and the open PR all decline
to put a session identifier on the wire, and none of them says how an Anchor should
correlate the two exchanges. The draft should pick — a session identifier in
ClientFirstMessage/ClientSecondMessage, or a normative requirement of connection
reuse in the HTTP transport draft.
Interaction with #9 still stands: whatever is chosen must not let a Client replay
exchange one against reused Anchor state, or the key recovery there becomes reachable
through the correlation layer.
Carried over from
SPEC-COVERAGE.md, and now sharper because the crypto draft exists and is being actively edited.draft-jms-mole-protocols-00§4.1.2 states the problem and declines to solve it:It picks neither. Implementations therefore cannot agree on how an Anchor ties exchange two to exchange one.
Why now:
draft-authors-mole-crypto.mdwas merged upstream on 2026-07-15 (PR #38, closing issue #31), and its two-round issuance is exactly where a session identifier would live. PR #39 ("Add more text to try to define proof") is still open. There is a window in which this lands as a design input rather than a retrofit.Implementer's evidence, from this crate: the trait boundary in
src/crypto.rshit the ambiguity at the type level before any crypto existed —IhatAnchor::signreturns(Vec<u8>, Self::State)andIhatAnchor::proveconsumes thatStateby value, because the drafts give nothing on the wire to correlate with. The experimental profile inherits this: correlation is implicit in the Rust call sequence, which is exactly what a network protocol cannot rely on.This interacts with #9: whatever correlation mechanism is chosen must not let a Client replay exchange one against the same Anchor state, or the secret key recovery there becomes reachable.
Action: report to
Moderation-of-unLinkable-Endorsements/internet-drafts. Tracked here so the local workaround is documented either way.Update — upstream PR #39 (open, unmerged): the structures now exist and none carries a session identifier
This is the update that makes the issue concrete.
draft-jms-mole-protocols-00§4.1.2 offered two ways out:PR #39 defines all four grant messages for the first time:
None of them carries a session identifier. So the first branch has now been foreclosed by omission — the messages are specified and the field is not there — which silently forces the second branch, mandating connection reuse, without either document saying so or the HTTP transport draft providing for it.
This is no longer "the drafts have not decided." It is "the drafts have decided by accident, and the consequence is unwritten."
Why it is worth raising now rather than later: adding a session identifier to
ClientFirstMessage/ClientSecondMessageis cheap while the structs are new and unimplemented, and expensive once anyone has built against them. PR #39 is open.Interaction with #9: whatever mechanism is chosen must not let a Client replay
ClientFirstMessageand have the Anchor re-derive or reuse the samea',t', or the key-recovery there becomes reachable through the correlation layer. Connection reuse happens to prevent this; a session identifier does not, unless the Anchor also binds its state to it single-use.Update — the reference implementation confirms the gap
ihat-rscarries the correlation implicitly in its Rust type-state machine:each step consumes the previous state, so the steps can only run in protocol order.
Its
SignatureRequest/Signature/ProofRequest/Proofwire structures carryno session identifier, exactly as PR #39's do.
That is fine for a library used in-process. It is not a protocol: over a network,
"the call sequence guarantees correlation" is unavailable, which is precisely what
§4.1.2's unresolved choice is about.
crypto::exp_ihatinherits the same shape, and the same limitation.So the position is now: two independent implementations and the open PR all decline
to put a session identifier on the wire, and none of them says how an Anchor should
correlate the two exchanges. The draft should pick — a session identifier in
ClientFirstMessage/ClientSecondMessage, or a normative requirement of connectionreuse in the HTTP transport draft.
Interaction with #9 still stands: whatever is chosen must not let a Client replay
exchange one against reused Anchor state, or the key recovery there becomes reachable
through the correlation layer.