4 Commits
Author SHA1 Message Date
zeekayandHanzo Dev b30bb58a22 test(mpcd): point the dispatcher round-trip at a scheme thresholdd still serves
TestEmbeddedDispatcher_BLSRoundTrip and _AuthGate drove "bls". thresholdd
stopped serving that scheme — trusted-dealer threshold-BLS custody was ripped
for security (H-2), and luxfi/threshold v1.12.5's dispatcher exposes exactly
cggmp21, frost, pulsar, corona, magnetar and doerner (pkg/thresholdd/zap_schema.go;
there is no bls.go). So both tests had been failing on every run:

    bls.keygen: zapclient: unknown procedure "bls.keygen"
    wrong-id: error zapclient: unknown procedure "bls.keygen" does not name unauthorized

The second line is the damaging one. _AuthGate asserts a wrong NodeID is refused
with "unauthorized"; it was instead getting "unknown procedure" back from a
scheme lookup that failed before auth was ever consulted. The auth gate has not
actually been exercised for as long as the scheme has been gone.

FROST is a live production scheme on the same ZAP wire and keygens as fast, so
the calls move to it and every assertion is kept verbatim — pubkey non-empty,
3 shares, non-empty signature, verify true, forgery rejected, wrong NodeID
refused with "unauthorized". Nothing is skipped, softened or dropped; the
round-trip now lands on a surface that exists. _UnknownScheme still drives
"bogus" and still proves the unknown-procedure contract.

Renamed to TestEmbeddedDispatcher_FROSTRoundTrip so the name states what it runs.

go test ./... is green across the module.

Co-authored-by: Hanzo Dev <[email protected]>
2026-07-27 12:25:56 -07:00
zeekay ba4995dcf5 WIP: session checkpoint 2026-06-05 (codec rip in flight) 2026-06-05 15:33:58 -07:00
zeekay 3cfea562f9 mpcd: gate embedded threshold dispatcher with bearer-token + loopback bind
Red round 5 finding B1. The embedded dispatcher on --threshold-listen
was an anonymous local signing oracle:

  1. Any process on the host could POST `{"method":"frost.sign",...}`
     and obtain signatures with no auth gate (only the API on :9800
     enforced MPC_INTERNAL_API_KEY).
  2. An operator typo `MPC_THRESHOLD_LISTEN=0.0.0.0:7300` exposed it
     cluster-wide.
  3. Any SSRF inside mpcd pivoted into the dispatcher.

Fix mirrors the existing internal-API auth pattern (cmd/mpcd/main.go
line ~456):

  - Auth token: read MPC_THRESHOLD_AUTH_TOKEN; if unset, derive a
    deterministic per-cluster token from the node Ed25519 seed
    (SHA-256(seed || "mpc-threshold-rpc") hex). All nodes share the
    same key without extra config; log warns when derivation is used.
    Server.SetAuthToken installs the gate.
  - Loopback bind: refuse non-loopback addr unless
    MPC_THRESHOLD_ALLOW_REMOTE=1 — operators must explicitly
    acknowledge the exposure. Bare `:port` (= 0.0.0.0) is NOT loopback.

Also picks up luxfi/threshold v1.6.10 which removes the pulsar/corona
in-memory-token surface (Red HIGH B2) — pulsar.*/corona.* now return a
typed "not yet implemented" error.

Tests:
  - TestIsThresholdLoopback locks the loopback predicate (8 cases:
    127.0.0.1, [::1], localhost OK; 0.0.0.0, :port, RFC1918 refused).
  - TestEmbeddedDispatcher_AuthGate proves 401 on missing/wrong token,
    200 on valid token through the dispatcher mpcd installs.

4 tests pass in cmd/mpcd (was 2, +2).
2026-05-13 16:46:22 -07:00
zeekay 7bcad9343d mpcd: embed luxfi/threshold/pkg/thresholdd dispatcher (six schemes)
mpcd is the production threshold daemon. With this commit it embeds
the JSON-RPC dispatcher from luxfi/threshold/pkg/thresholdd on a new
--threshold-listen flag (default 127.0.0.1:7300, MPC_THRESHOLD_LISTEN
env var). The dispatcher exposes every supported scheme:

  cggmp21 (secp256k1 ECDSA, CGGMP21 fork)
  frost   (secp256k1 Schnorr, RFC 9591)
  bls     (BLS12-381 Shamir/Lagrange)
  sr25519 (Ristretto255, via mpc node's own session — separate path)
  pulsar  (M-LWE / FIPS 204 ML-DSA-65 threshold, via luxfi/corona/threshold)
  corona  (R-LWE / Corona, via luxfi/corona/threshold)
  doerner (reserved; upstream protocol non-functional, returns explicit error)

Wire format matches teleport/mpc/src/signers/rpc.ts byte-for-byte:

  POST /  {"jsonrpc":"2.0","id":N,"method":"<scheme>.<op>","params":{...}}

Methods per scheme: keygen / sign / verify. Public-key handles are
returned by keygen and bound on sign/verify.

Decomplecting note: the dispatcher carries zero policy. Profile
gating, auth, audit, and rate-limiting live on mpcd's existing API
surface (and on the cluster ingress in front of it). The threshold
listener is loopback by default; production exposure happens via the
KMS-facing ZAP server or the gateway.

There is no separate thresholdd daemon to deploy. The luxfi/threshold
repo's cmd/thresholdd remains as a developer / CI binary that imports
the same package — one wire, one implementation, two startup paths.

Tests: TestEmbeddedDispatcher_BLSRoundTrip (full keygen → sign →
verify → forgery rejection) and TestEmbeddedDispatcher_UnknownScheme
(-32601 method-not-found contract) both pass. README updated with the
new protocol table; full surface documented in
luxfi/threshold/LLM.md "thresholdd — unified JSON-RPC dispatcher".
2026-05-13 15:56:56 -07:00