# `ocra/mutual-auth` ## Purpose RFC 6287 §7.1 mutual authentication helpers. Both sides compute OCRA over the concatenation of the client and server challenges, with the order flipped between the two directions (`Qc || Qs` for the server's proof, `Qs || Qc` for the client's). The module exposes pure functions plus stateful `OcraMutualAuthClient` / `OcraMutualAuthServer` wrappers so consumers don't reinvent the concatenation order. ## Features - `serverProof` / `verifyServerProof` — the server's response and the client-side check. - `clientProof` / `verifyClientProof` — the client's response and the server-side check. - `OcraMutualAuthClient` / `OcraMutualAuthServer` — stateful wrappers that hold the suites + key + own challenge and expose narrow methods. - Optional `extra` parameter for suites that include `C` (counter), `T` (timestamp), `Snnn` (session info), or `PSHA{...}` (password hash). ## Usage: Basic Example ```ts import { OcraMutualAuthClient, OcraMutualAuthServer } from "@suaveplan/otp/ocra"; const server = new OcraMutualAuthServer(suites, key, "Qs"); const client = new OcraMutualAuthClient(suites, key, "Qc"); const Rs = server.respond("Qc"); const Rc = client.respond("Qs", Rs); const ok = server.verify("Qc", Rc); ``` ## Usage: Advanced Example ```ts import { clientProof, serverProof } from "@suaveplan/otp/ocra"; // Counter-bound mutual auth for a session that needs replay protection. const Rs = serverProof({ suites, key, clientChallenge: "Qc", serverChallenge: "Qs", extra: { counter: 7n }, }); ``` ## API Reference - `serverProof(input): string` - `verifyServerProof(input): boolean` - `clientProof(input): string` — verifies server proof first; throws `OtpError(OTP.VERIFY_FAILED)` on mismatch. - `verifyClientProof(input): boolean` - `OcraMutualAuthClient` / `OcraMutualAuthServer` classes. ## Implementation Notes The challenge concatenation order is the most error-prone part of RFC 6287 §7.1 — `Rs` MUST be over `Qc || Qs` and `Rc` MUST be over `Qs || Qc`. Encoding the order in named functions and class methods keeps callers from having to reread the RFC every time they wire a new flow. The class wrappers add a small amount of state (own challenge, own suite, own key) so consumers can keep the per-session context outside the call graph. The `extra` parameter lets the same flow work with counter-bound, timestamp-bound, password-hash-bound, or session-info-bound suites — the mutual-auth shape is the same, only the underlying OCRA inputs differ.