Skip to content

registry: verify registration proof-of-possession signature (PPA-003 server-side)#104

Open
TeoSlayer wants to merge 2 commits into
mainfrom
security/ppa003-register-verify
Open

registry: verify registration proof-of-possession signature (PPA-003 server-side)#104
TeoSlayer wants to merge 2 commits into
mainfrom
security/ppa003-register-verify

Conversation

@TeoSlayer

Copy link
Copy Markdown
Contributor

Completes PPA-003. The common client (v0.5.8) now signs register:<listen_addr>:<public_key>; this verifies it server-side.

  • Verify-if-present: a registration with no signature still succeeds (old daemons unaffected, wire-compatible); a present-but-invalid signature is always rejected. New TestHandleRegisterSignatureVerifyIfPresent covers valid / forged / wrong-addr / unsigned-compat / required.
  • -require-register-signature / RENDEZVOUS_REQUIRE_REGISTER_SIGNATURE (default OFF) makes the signature mandatory — flip only after the signing client has rolled out fleet-wide.

Branch is based on the perf work (#100); merge #100 first. Full go test ./... green (20 pkgs), -race clean.

🤖 Generated with Claude Code

teovl and others added 2 commits July 24, 2026 17:27
…k-free telemetry, chunked reaper, single-write framing

Production profiling on the live registry (207K conns, reconnect storm)
showed ~30% of CPU in repeat ed25519 verifications of deterministic
challenges, ~26% in per-message write syscalls, and reader pile-ups
behind the reaper's full-map sweep under the write lock.

- authz.VerifyCached: sharded memoization of successful (pubkey,
  message, sig) verifications; ed25519 is deterministic and registry
  challenges are static per node/request shape, so identical tuples
  always re-verify identically. Failures are never cached. Wired into
  VerifyNodeSignature and the binary heartbeat/resolve paths.
- handleMessage: drop the s.mu wrap around walStore.IsStandby (wal has
  its own lock); per-network request counters use TryRLock and skip a
  telemetry tick instead of queueing behind writers.
- ReapStaleNodes: collect+sort+scan under RLock, write-lock only to
  delete confirmed-stale nodes (re-checked under the lock), Save()
  signalled outside the lock. Common no-reap sweep takes no write lock.
- accept.writeMessage: single buffered write per frame instead of
  prefix+body (halves write syscalls).

Deployed 2026-07-24: storm-phase CPU dropped from ~1000% to ~240% at
equivalent connection counts.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The register op is the one write that establishes the node_id↔pubkey↔
endpoint binding, and it was the only signed-operation sibling that
carried no signature — so anyone reaching the registry could register a
key or repoint an endpoint they do not own. The common client now signs
register:<listen_addr>:<public_key>; this verifies it.

Verify-if-present, so old daemons that send no signature still register
(wire-compatible); a present-but-invalid signature is always rejected.
RequireRegisterSignature (flag -require-register-signature /
RENDEZVOUS_REQUIRE_REGISTER_SIGNATURE, default OFF) upgrades this to
mandatory once the signing client has rolled out fleet-wide.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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