first commit
This commit is contained in:
65
docs/security-stack/security/srp/src/server/server-m2.md
Normal file
65
docs/security-stack/security/srp/src/server/server-m2.md
Normal file
@@ -0,0 +1,65 @@
|
||||
# `server-m2`
|
||||
|
||||
## Purpose
|
||||
|
||||
Split-roundtrip helper that computes the server proof `M2 = H(A | M1 | K)` independently of `serverFinishHandshake`. Useful for transports that ack `M1` over one HTTP request (server validates client proof, persists the session) and emit `M2` from a different worker or route (perhaps a follow-up acknowledgement endpoint, or a fan-out broadcast confirming successful authentication). The second-half route does not need to redo the `modPow` + KDF chain; it just needs `(A, M1, K)` (which it can fetch from a session store) and this helper.
|
||||
|
||||
## Features
|
||||
|
||||
- Single function call returning `H(A | M1 | K)`.
|
||||
- Byte-identical to the `M2` field returned by `serverFinishHandshake` for the same `(A, M1, K)` triple.
|
||||
- Deterministic — same inputs always produce the same bytes.
|
||||
- Wraps the shared `computeM2` helper in `math/proof.ts` so the proof formula lives in exactly one place.
|
||||
|
||||
## Usage: Basic Example
|
||||
|
||||
```ts
|
||||
import { serverComputeM2 } from "@suaveplan/srp/server";
|
||||
import { params2048Sha256 } from "@suaveplan/srp/params";
|
||||
import { nobleHashBridge } from "@suaveplan/srp/hash";
|
||||
|
||||
const params = params2048Sha256(nobleHashBridge("SHA256"));
|
||||
const A = new Uint8Array(256);
|
||||
const M1 = new Uint8Array(32);
|
||||
const K = new Uint8Array(32);
|
||||
const M2 = serverComputeM2(A, M1, K, params);
|
||||
console.log(M2.byteLength); // 32
|
||||
```
|
||||
|
||||
## Usage: Advanced Example
|
||||
|
||||
```ts
|
||||
import { serverComputeM2, serverFinishHandshake } from "@suaveplan/srp/server";
|
||||
import { clientFinishHandshake, clientStartHandshake } from "@suaveplan/srp/client";
|
||||
import { serverStartHandshake } from "@suaveplan/srp/server";
|
||||
import { computeVerifier } from "@suaveplan/srp/verifier";
|
||||
import { params2048Sha256 } from "@suaveplan/srp/params";
|
||||
import { nobleHashBridge } from "@suaveplan/srp/hash";
|
||||
|
||||
const params = params2048Sha256(nobleHashBridge("SHA256"));
|
||||
const salt = new Uint8Array(16);
|
||||
const rng = {
|
||||
nextUint32: () => 0,
|
||||
nextFloat: () => 0,
|
||||
nextBytes: (n: number) => crypto.getRandomValues(new Uint8Array(n)),
|
||||
};
|
||||
const { v } = computeVerifier("alice", "password123", salt, params);
|
||||
const { a, A } = clientStartHandshake(rng, params);
|
||||
const { b, B } = serverStartHandshake(v, rng, params);
|
||||
const client = clientFinishHandshake("alice", "password123", salt, A, B, a, params);
|
||||
const inline = serverFinishHandshake("alice", salt, A, B, b, v, client.M1, params);
|
||||
const split = serverComputeM2(A, client.M1, inline.K, params);
|
||||
console.log(Buffer.from(inline.M2).equals(Buffer.from(split)));
|
||||
```
|
||||
|
||||
## API Reference
|
||||
|
||||
### `serverComputeM2(A, M1, K, params): Uint8Array`
|
||||
|
||||
Returns `H(A | M1 | K)` of length `params.hash.digestSize`.
|
||||
|
||||
## Implementation Notes
|
||||
|
||||
The split-roundtrip pattern matters operationally: many real deployments separate the "validate client proof" step (which needs the full SRP state machine — `v`, `b`, `B`) from the "ack mutual authentication" step (which only needs `A`, `M1`, and the session key `K`). The first step can run on a stateful auth node with the verifier DB; the second can run on any edge that has been handed the session-key blob. `serverComputeM2` is the API surface that supports that split without forcing the second step to re-derive `S` and `K`.
|
||||
|
||||
The function is intentionally trivial — a single forward to `computeM2`. The wrapper exists for API stability: if RFC 2945 ever extends `M2` (e.g. adds a session-binding field), this entry point is where the change lands, and `serverFinishHandshake` is updated to call into the same helper.
|
||||
Reference in New Issue
Block a user