How the-sarge/cpace works
1. Repository shape
This is a single-package Go cryptography library, not an application service. The root package implements the CPace draft-21 PAKE profile CPACE-RISTR255-SHA512, with the public API centered in api.go and the protocol/state machinery split across small internal files.
2. Top-level protocol boundary
The public surface is an initiator/responder exchange with mandatory explicit key confirmation: Start creates initiator state and message A, Respond consumes A and emits responder state and message B, Initiator.Finish verifies B and emits message C plus a Session, and Responder.Finish verifies C and yields its Session. Authentication only exists after the finish calls succeed; Respond alone is not authentication.
3. Core data flow
The main flow is: caller supplies Input and role identity data → the library constructs CPace CI and transcript state → the peer message is framed/unframed → confirmation tags are checked during finish → a shared session key is derived and exposed through Session.Export. Message bytes are intended to be opaque to applications.
4. Protocol state and lifecycle
core.go, session.go, and terminal_state.go appear to implement the protocol state machine and lifecycle rules. The design is intentionally single-use for finish operations, with explicit Close methods to release local secrets if a half-finished exchange is abandoned. Value copies share terminal state, so lifecycle is tied to the underlying state rather than the Go value copy.
5. Input and identity binding
input.go defines the role-local input contract. Each side provides SelfID, PeerID, password, context, session ID, and local associated data. The library binds stable application identities into CI; it does not infer identities from wire messages. The README stresses that session IDs must be fresh and non-secret, and that outer negotiation/downgrade protection is out of scope.
6. Framing and wire format
framing.go, length_value.go, peer_share.go, and transcript.go handle the package-owned binary encoding. The wire format is versioned by this module and begins with a fixed prefix byte 0xc1. Validation includes exact public-share/tag lengths plus an aggregate decoder backstop before deeper field parsing, so malformed framed inputs fail early.
7. Cryptographic operations
crypto.go and caps.go cover the cryptographic primitives and capability/cipher-suite constraints for the chosen draft profile. Randomness is sourced only from Go’s crypto/rand.Reader; callers do not supply entropy. Session.Export is a deterministic, domain-separated KDF-style export from the confirmed shared secret, not a randomness source.
8. Error and invariant handling
errors.go and caps.go encode package-specific failure modes and bounds. The library enforces per-field size limits on passwords, party IDs, context, session IDs, and local associated data. Empty session IDs are rejected by default, malformed or failed confirmation messages consume one-time state, and closed sessions later reject export operations.
9. Tests and evidence
The repository has broad unit, vector, fuzz, and benchmark coverage in *_test.go, plus draft test vectors in testdata/. This is a crypto repository that relies heavily on correctness evidence: tests for framing, caps, strings, vectors, and examples help validate both protocol semantics and boundary conditions.
10. Tooling, CI, and release governance
The repo includes a substantial security/release pipeline under .github/workflows, Taskfile.yml, scripts/, and tools/. There are custom helper tools for evidence-baseline checks and release-policy checks, plus OSS-Fuzz integration under ossfuzz/. The documentation tree is unusually important to the architecture because it records threat model, security gates, fuzz evidence, release policy, and ADRs that constrain future changes.
11. Architectural summary
This is a tightly scoped, security-driven protocol library: one protocol profile, one wire format, one authenticated key-exchange flow, and a strong emphasis on explicit lifecycle and validation boundaries. If you are drawing the architecture, the key boxes are: caller input, protocol state machine, framing/validation, cryptographic derivation, session export, and the surrounding verification/release infrastructure.
Main entry points: core.go State core · framing.go Framing · api.go API · terminal_state.go Terminal state
Components 18
Protocol core
Public API, state machine, and session lifecycle for CPace exchanges.
- API · Start/Respond/Finish entry points for the CPace exchange.
api.go - Input · Caller-supplied identities, password, context, session ID, and AAD.
input.go - State core · Protocol coordination and exchange progression.
core.go - Terminal state · Single-use finish semantics, closure, and shared terminal ownership.
terminal_state.go - Session · Confirmed shared secret and export operations.
session.go
Wire format
Package-owned encoding, framing, and transcript handling.
- Framing · Module-owned message prefixing and validation.
framing.go - Peer share · Encoded peer public-share and confirmation-tag payloads.
peer_share.go - Transcript · Transcript state bound into confirmation and key derivation.
transcript.go - L/V codec · Length-value framing and aggregate decode bounds.
length_value.go
Crypto engine
Primitive operations, suite constraints, and export derivation.
- Primitives · Randomness, hashing, and profile-specific cryptographic operations.
crypto.go - Caps · Draft-profile capability and size constraints.
caps.go - Errors · Package-specific failure modes and state-rejection behavior.
errors.go
Assurance
Tests, vectors, fuzzing, docs, and release/security governance.
- API tests · Integration tests for the exchange flow and semantics.
api_test.go - Vectors · Draft-profile test vectors and correctness checks.
vectors_test.go - Fuzzing · Fuzz coverage for framing, parsing, and protocol boundaries.
fuzz_test.go - Docs · Threat model, ADRs, security gates, release policy, and evidence records.
docs - CI and release · Workflows, scripts, tools, and release/security checks.
.github/workflows - OSS-Fuzz · External fuzz integration and build harness.
ossfuzz
Connections 20
- API → Input: consumes · Caller-provided role identity and secret inputs are bound into the exchange.
- API → State core: starts · Start/Respond/Finish drive the protocol state machine.
- State core → Framing: frames · Protocol messages are encoded and decoded through package-owned framing.
- State core → Transcript: updates · Each step contributes to the transcript bound into confirmation.
- State core → Primitives: derives · Protocol steps use cryptographic operations and randomness.
- State core → Terminal state: finalizes · Finish transitions create terminal state and enforce single-use semantics.
- Terminal state → Session: yields · Successful completion exposes a confirmed shared session.
- Session → Primitives: exports · Session export is a deterministic derivation from the confirmed secret.
- Framing → Peer share: encodes · Peer shares and confirmation tags are wrapped in module-owned wire bytes.
- Framing → L/V codec: uses · Framing depends on length-value bounds and decode backstops.
- Peer share → Caps: bounds · Encoded shares are constrained by profile-specific lengths.
- Primitives → Caps: constrained by · Primitive use is restricted by suite and size caps.
- Errors → Terminal state: guards · Invalid or failed finalization consumes one-time state and rejects reuse.
- Errors → Session: blocks · Closed or invalid sessions reject later export operations.
- API tests → API: exercises · Tests cover the public exchange API and lifecycle semantics.
- Vectors → Framing: verifies · Draft vectors validate wire format and confirmation behavior.
- Fuzzing → Framing: hammers · Fuzz targets stress malformed encodings and protocol boundaries.
- Docs → CI and release: guides · Documentation records security gates, evidence, and release policy enforced by automation.
- CI and release → OSS-Fuzz: integrates · Automation includes fuzzing and security/release checks.
- Docs → API: specifies · Architecture and threat-model documents constrain the public protocol contract.