How jedisct1/rust-cpace works
1. This repository is a single Rust library crate: pake_cpace. There is no application binary, service layer, or workspace structure; the entire implementation lives in src/lib.rs, with CI and dependency automation in GitHub Actions/Dependabot.
2. The core subsystem is a CPace balanced PAKE implementation over Ristretto255. The library’s job is to let two peers who share a low-entropy secret derive the same strong shared keys after one round trip, without revealing the password or enabling offline dictionary attacks.
3. The public API is intentionally small and protocol-shaped. The README shows a three-step flow:
- CPace::step1(...) on the initiating side,
- CPace::step2(...) on the responding side,
- step3(...) on the initiating side to finish key agreement.
This is the main interaction boundary for all consumers of the crate.
4. The protocol data flow is asymmetric but balanced: both sides must supply the same password plus matching identities (client, server) and optional associated data. The exchanged packets carry the transcript data needed to validate the peer and bind the session.
5. The output of the protocol is not a single session key but a pair of 256-bit shared keys (k1 and k2). That indicates the library is designed for bidirectional authenticated communication after the handshake, rather than just a one-way secret.
6. Cryptographically, the implementation is centered on Ristretto255 and SHA-512. This choice is important architecturally because it makes the crate compatible with the C reference implementation and keeps the algorithm portable to environments like WebAssembly.
7. The repository explicitly targets no_std and WebAssembly-compatible use. That means the library boundary avoids assuming an operating system, allocator-heavy runtime, or network stack; callers provide the transport for the handshake packets.
8. The code likely has a protocol-state abstraction even though only lib.rs is visible: step1 returns an object that can serialize its packet, step2 consumes the incoming packet and produces the responder packet plus derived keys, and step3 finalizes the initiator state. This state machine is the main internal architectural boundary.
9. Error handling is part of the library contract because each step in the README returns unwrap()-able results. In practice, this means malformed packets, mismatched identities, bad passwords, or invalid inputs are handled as protocol failures rather than panics in normal use.
10. The implementation also has explicit input constraints that affect system design: client and server identifiers are capped at 255 bytes, and the API supports optional associated data. Those constraints matter when drawing the protocol box around external inputs and transcript binding.
11. From a deployment perspective, this crate is a crypto primitive rather than an end-user product. Its consumers would be higher-level pairing or authentication systems, such as IoT/mobile pairing with PINs, QR codes, or serial numbers, which sit outside this repository.
12. The repo’s non-library files are operational only: .github/workflows/ci.yml suggests automated build/test checks, and dependabot.yml manages dependency updates. They support the crate but do not add runtime architecture.
Main entry points: lib.rs Protocol state · ci.yml CI · dependabot.yml Dependabot
Components 17
Library crate
Core CPace balanced PAKE implementation and its public protocol boundary.
- pake_cpace · Single no_std Rust library crate implementing CPace over Ristretto255.
src/lib.rs - CPace API · Three-step public interface: step1, step2, step3.
src/lib.rs - Protocol state · Internal step-by-step state that carries the initiator and responder through the exchange.
src/lib.rs - Step 1 · Starts the handshake and produces the first packet.
src/lib.rs - Step 2 · Consumes the incoming packet, validates the transcript, and produces the responder reply.
src/lib.rs - Step 3 · Completes the initiator side and finalizes key agreement.
src/lib.rs - Transcript · Binds client, server, and associated data into the protocol exchange.
src/lib.rs - Handshake packets · Serialized protocol messages exchanged between peers over caller-provided transport.
src/lib.rs - Peer inputs · Password, client identity, server identity, and optional associated data.
src/lib.rs - Input limits · Constraints such as 255-byte identity caps and protocol-shaped parameter checks.
src/lib.rs - Protocol errors · Malformed packets, mismatched identities, or invalid inputs are surfaced as handshake failures.
src/lib.rs - Shared keys · Derives two 256-bit shared keys for bidirectional authenticated communication.
src/lib.rs - Ristretto255 · Primary elliptic-curve group used by the CPace construction.
src/lib.rs - SHA-512 · Hash primitive used by the implementation and compatible with the C reference design.
src/lib.rs - Portability · Designed for no_std and WebAssembly-compatible environments without assuming OS services.
src/lib.rs
Repo automation
CI and dependency maintenance files supporting the crate.
- CI · Automated build and test checks for the crate.
.github/workflows/ci.yml - Dependabot · Automated dependency update configuration.
.github/dependabot.yml
Connections 20
- CPace API → Step 1: exposes · Public API entrypoint for the initiator start step.
- CPace API → Step 2: exposes · Public API entrypoint for the responder step.
- CPace API → Step 3: exposes · Public API entrypoint for the initiator finish step.
- Step 1 → Protocol state: creates · Initializes the handshake state on the initiating side.
- Step 2 → Protocol state: consumes · Advances the handshake state using the peer packet.
- Step 3 → Protocol state: finalizes · Completes the initiator state machine.
- Step 1 → Peer inputs: reads · Uses password, identities, and optional associated data.
- Step 2 → Peer inputs: reads · Uses the same shared inputs to validate and respond.
- Step 3 → Peer inputs: reads · Uses shared inputs to complete key agreement.
- Protocol state → Transcript: binds · Binds identities and associated data into the transcript.
- Protocol state → Handshake packets: serializes · Produces and consumes handshake packets.
- Protocol state → Input limits: checks · Enforces protocol input constraints.
- Input limits → Protocol errors: rejects · Invalid sizes or malformed parameters become protocol errors.
- Handshake packets → Protocol errors: parses to · Malformed or inconsistent packets are surfaced as failures.
- Protocol state → Ristretto255: uses · Performs the CPace group operations over Ristretto255.
- Protocol state → SHA-512: uses · Derives protocol values with SHA-512.
- Protocol state → Shared keys: derives · Outputs the pair of shared 256-bit keys k1 and k2.
- pake_cpace → Portability: targets · The crate is intended for no_std and WebAssembly use.
- CI → pake_cpace: checks · Runs automated validation of the library crate.
- Dependabot → pake_cpace: updates · Keeps dependencies current for the library crate.