How jedisct1/cpace works
1. Repository purpose
- This is a small C library implementing CPace over Ristretto255 for deriving shared keys from a low-entropy secret.
- The repo is structured as a reusable cryptographic library plus a standalone test program.
2. Primary architecture
- The codebase is centered around a single public API in src/crypto_cpace.h and its implementation in src/crypto_cpace.c.
- There are no services, daemons, or application layers beyond the library and test harness.
3. Public library boundary
- crypto_cpace.h is the main contract for consumers.
- It exposes:
- initialization (crypto_cpace_init)
- client-side phase 1 and phase 3
- server-side phase 2
- state and shared-key result types
- protocol size constants such as public data, response, and shared-key byte lengths
4. Protocol flow
- The library implements a single round-trip PAKE:
- client computes public data
- server consumes that public data and returns a response
- client consumes the response and derives the final shared keys
- This is a strict client/server interaction boundary, not a bidirectional stream or session manager.
5. Data model
- The important state object is crypto_cpace_state, used by the client across steps 1 and 3.
- The result object crypto_cpace_shared_keys holds two direction-specific 256-bit keys:
- one for client-to-server
- one for server-to-client
- Identifiers, password, and optional additional data are all input parameters to the protocol.
6. Cryptographic dependency boundary
- The implementation depends on libsodium 1.0.17+.
- The README notes it uses:
- Ristretto255 as the group
- SHA-512 as the hash function
- crypto_cpace_init() is effectively a thin wrapper around sodium_init().
7. Client-side responsibilities
- The client is responsible for:
- initializing the protocol state
- generating the outbound public data
- later consuming the server response to finalize the shared keys
- The client does not directly compute the server-side key material; both sides independently derive matching keys from the shared inputs.
8. Server-side responsibilities
- The server takes the client’s public data and the same shared secret/identifiers.
- It computes the shared keys immediately and returns a protocol response for the client.
- This makes the server step a combined “verify + derive + respond” operation.
9. Testing boundary
- test/test.c is a standalone validation program, not a unit-test framework tree.
- Its role is to exercise the full protocol round-trip and confirm that client- and server-computed keys match.
10. Integration surface
- Consumers only need to link against this library and libsodium.
- The README example shows the intended usage pattern: initialize, run the three protocol steps, then compare or use the derived keys.
11. Portability and constraints
- The README explicitly calls out portability goals toward wasm-crypto, which is why the design is lightweight and uses common primitives.
- Input identifiers are bounded to 255 bytes, which is a protocol constraint that affects calling code and data validation.
12. What an architecture diagram should show
- A minimal diagram should include:
- a client component
- a server component
- the CPace library boundary inside both
- the libsodium dependency beneath the library
- the one-round-trip message exchange: public data out, response back, shared keys produced on both sides
Main entry points: test.c Round-trip test · crypto_cpace.c CPace core · crypto_cpace.h Public API
Components 12
CPace library
Public API, implementation, and cryptographic backend.
- Public API · Main contract for consumers: init, protocol phases, state, shared-key types, and size constants.
src/crypto_cpace.h - CPace core · Implements the CPace protocol over Ristretto255 using libsodium primitives.
src/crypto_cpace.c - Init · Wraps sodium_init() to prepare the library for use.
src/crypto_cpace.c - libsodium · External dependency providing sodium_init(), SHA-512, and Ristretto255-backed primitives.
Protocol flow
Client/server round-trip and derived shared keys.
- Client phase 1 · Initializes client state and generates outbound public data.
- Server phase 2 · Consumes client public data, verifies inputs, derives shared keys, and produces the response.
- Client phase 3 · Consumes the server response and finalizes shared keys.
- Session state · Client-side protocol state carried between phases 1 and 3.
- Shared keys · Two direction-specific 256-bit keys for client-to-server and server-to-client traffic.
- Public data · Client-to-server protocol message carrying the outbound public data.
- Response · Server-to-client protocol message carrying the CPace response.
Validation
Standalone round-trip exercise program.
- Round-trip test · Standalone program that runs the full protocol and checks that both sides derive matching keys.
test/test.c
Connections 14
- Public API → CPace core: declares · The public API is implemented by the library core.
- CPace core → libsodium: uses · The implementation depends on libsodium for initialization and cryptographic primitives.
- Init → libsodium: calls · Initialization delegates to sodium_init().
- Client phase 1 → Session state: writes · Phase 1 creates and stores client state.
- Client phase 1 → Public data: emits · The client produces public data for the server.
- Public data → Server phase 2: inputs · The server consumes the client's public data.
- Server phase 2 → Response: emits · The server returns the protocol response.
- Server phase 2 → Shared keys: derives · The server independently derives the shared keys.
- Response → Client phase 3: inputs · The client consumes the server response.
- Client phase 3 → Shared keys: finalizes · The client completes key derivation from the response.
- Session state → Client phase 3: reads · Phase 3 uses the client state from phase 1.
- Round-trip test → Client phase 1: exercises · The test program drives the client side of the protocol.
- Round-trip test → Server phase 2: exercises · The test program drives the server side of the protocol.
- Round-trip test → Shared keys: verifies · The test confirms both sides derive matching keys.