29 KiB
29 KiB
@suaveplan/srp - SRP-6a zero-knowledge password proof (RFC 5054 / RFC 2945) — universal client+server roles, bundled 2048-bit safe-prime group, optional 1024/1536/3072/4096/6144/8192 groups under subpaths, augmented PAKE bridge for future OPAQUE drop-in.
Summary
SRP-6a zero-knowledge password proof per RFC 5054 / RFC 2945. Universal — client and server roles in one package, bundled 2048-bit safe-prime group, optional 1024 / 1536 / 3072 / 4096 / 6144 / 8192-bit groups under tree-shakeable subpaths, augmented-PAKE bridge (PakeProvider) for future OPAQUE drop-in, dual sync / async hash backends.
Documentation tree
- client-finish — Complete the SRP-6a handshake on the client side after the server has emitted its public value
B. Derives the shared… - client-start — Kick off the SRP-6a handshake on the client side. Draws a private exponent
a ≥ 256bits from an injectableRngand… - client-verify — Verify the server's proof
M2 = H(A | M1 | K)per RFC 2945 §3 on the client side. After the client emitsM1and the… - errors — (no submodules)
- errors — (no submodules)
- groups — (no submodules) - groups-1024 — _(no submodul…
- 1024 — (no submodules)
- groups-1024 — (no submodules)
- 1536 — (no submodules)
- groups-1536 — (no submodules)
- 3072 — (no submodules)
- groups-3072 — (no submodules)
- 4096 — (no submodules)
- groups-4096 — (no submodules)
- 6144 — (no submodules)
- groups-6144 — (no submodules)
- 8192 — (no submodules)
- groups-8192 — (no submodules)
- groups-2048 — (no submodules) - groups-1024 — _(no submodul…
- 1024 — (no submodules)
- hash — (no submodules)
- hash-bridge — (no submodules)
- k — Compute the SRP-6a multiplier parameter
k = H(N | PAD(g))per RFC 5054 §2.5.3. The multiplier is the structural chang… - modpow — Modular exponentiation primitive for
@suaveplan/srp. This is a thin wrapper over@noble/curves's hardened `pow(num,… - pad — The
PAD(x, N)helper from RFC 5054 §2.5.3. Returns a left-zero-extended copy ofxwhose length equals `N.byteLength… - proof — Internal helpers for computing the SRP-6a / RFC 2945 §3 mutual-authentication proofs
M1andM2. Both client and ser… - rng-bytes — Adapter helper that draws
nbytes from anyRngimplementing the@suaveplan/typescontract. TheRnginterface ma… - u — Compute the SRP-6a scrambling value
u = H(PAD(A) | PAD(B))per RFC 5054 §2.5.4.umixes the two ephemeral public va… - (./src/math/x.md) — Compute the SRP-6a private exponent
x = H(salt | H(I | ":" | P))per RFC 5054 §2.6.xties username + password + sa… - observability — (no submodules)
- metrics — (no submodules)
- pake — (no submodules)
- pake-provider — (no submodules)
- params — (no submodules)
- params — (no submodules)
- schemas — (no submodules)
- schemas — (no submodules)
- server-finish — Complete the SRP-6a handshake on the server side after receiving the client's public value
Aand proofM1. Validate… - server-m2 — Split-roundtrip helper that computes the server proof
M2 = H(A | M1 | K)independently ofserverFinishHandshake. Us… - server-start — Begin the SRP-6a handshake on the server side. Loads the stored verifier
v(alongside the user's(I, salt)), draws… - verifier — (no submodules)
- verifier — (no submodules)
- modpow — Modular exponentiation primitive for
@suaveplan/srp. This is a thin wrapper over@noble/curves's hardened `pow(num,… - pad — The
PAD(x, N)helper from RFC 5054 §2.5.3. Returns a left-zero-extended copy ofxwhose length equals `N.byteLength… - proof — Internal helpers for computing the SRP-6a / RFC 2945 §3 mutual-authentication proofs
M1andM2. Both client and ser… - rng-bytes — Adapter helper that draws
nbytes from anyRngimplementing the@suaveplan/typescontract. TheRnginterface ma… - u — Compute the SRP-6a scrambling value
u = H(PAD(A) | PAD(B))per RFC 5054 §2.5.4.umixes the two ephemeral public va… - (./src/math/x.md) — Compute the SRP-6a private exponent
x = H(salt | H(I | ":" | P))per RFC 5054 §2.6.xties username + password + sa… - observability — (no submodules)- metrics — (no submodules)- pake — (no submodules)- pake-provider — (no submodules)- params — (no submodules)- params — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- server-finish — Complete the SRP-6a handshake on the server side after receiving the client's public value
Aand proofM1. Validate… - server-m2 — Split-roundtrip helper that computes the server proof
M2 = H(A | M1 | K)independently ofserverFinishHandshake. Us… - server-start — Begin the SRP-6a handshake on the server side. Loads the stored verifier
v(alongside the user's(I, salt)), draws… - verifier — (no submodules)- verifier — (no submodules)- errors — (no submodules)- groups — (no submodules)- groups-1024 — <!-- begin:aut…
- 1024 — (no submodules)- groups-1024 — (no submodules)- 1536 — (no submodules)- groups-1536 — (no submodules)- 3072 — (no submodules)- groups-3072 — (no submodules)- 4096 — (no submodules)- groups-4096 — (no submodules)- 6144 — (no submodules)- groups-6144 — (no submodules)- 8192 — (no submodules)- groups-8192 — (no submodules)- groups-2048 — (no submodules)- groups-1024 — <!-- begin:aut…
- hash — (no submodules)- hash-bridge — (no submodules)- k — Compute the SRP-6a multiplier parameter
k = H(N | PAD(g))per RFC 5054 §2.5.3. The multiplier is the structural chang… - modpow — Modular exponentiation primitive for
@suaveplan/srp. This is a thin wrapper over@noble/curves's hardened `pow(num,… - pad — The
PAD(x, N)helper from RFC 5054 §2.5.3. Returns a left-zero-extended copy ofxwhose length equals `N.byteLength… - proof — Internal helpers for computing the SRP-6a / RFC 2945 §3 mutual-authentication proofs
M1andM2. Both client and ser… - rng-bytes — Adapter helper that draws
nbytes from anyRngimplementing the@suaveplan/typescontract. TheRnginterface ma… - u — Compute the SRP-6a scrambling value
u = H(PAD(A) | PAD(B))per RFC 5054 §2.5.4.umixes the two ephemeral public va… - (./src/math/x.md) — Compute the SRP-6a private exponent
x = H(salt | H(I | ":" | P))per RFC 5054 §2.6.xties username + password + sa… - observability — (no submodules)- metrics — (no submodules)- pake — (no submodules)- pake-provider — (no submodules)- params — (no submodules)- params — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- server-finish — Complete the SRP-6a handshake on the server side after receiving the client's public value
Aand proofM1. Validate… - server-m2 — Split-roundtrip helper that computes the server proof
M2 = H(A | M1 | K)independently ofserverFinishHandshake. Us… - server-start — Begin the SRP-6a handshake on the server side. Loads the stored verifier
v(alongside the user's(I, salt)), draws… - verifier — (no submodules)- verifier — (no submodules)- errors — (no submodules)- groups — (no submodules)- groups-1024 — _(no submodu…
- 1024 — (no submodules)- groups-1024 — (no submodules)- 1536 — (no submodules)- groups-1536 — (no submodules)- 3072 — (no submodules)- groups-3072 — (no submodules)- 4096 — (no submodules)- groups-4096 — (no submodules)- 6144 — (no submodules)- groups-6144 — (no submodules)- 8192 — (no submodules)- groups-8192 — (no submodules)- groups-2048 — (no submodules)- groups-1024 — _(no submodu…
- hash — (no submodules)- hash-bridge — (no submodules)- k — Compute the SRP-6a multiplier parameter
k = H(N | PAD(g))per RFC 5054 §2.5.3. The multiplier is the structural chang… - modpow — Modular exponentiation primitive for
@suaveplan/srp. This is a thin wrapper over@noble/curves's hardened `pow(num,… - pad — The
PAD(x, N)helper from RFC 5054 §2.5.3. Returns a left-zero-extended copy ofxwhose length equals `N.byteLength… - proof — Internal helpers for computing the SRP-6a / RFC 2945 §3 mutual-authentication proofs
M1andM2. Both client and ser… - rng-bytes — Adapter helper that draws
nbytes from anyRngimplementing the@suaveplan/typescontract. TheRnginterface ma… - u — Compute the SRP-6a scrambling value
u = H(PAD(A) | PAD(B))per RFC 5054 §2.5.4.umixes the two ephemeral public va… - (./src/math/x.md) — Compute the SRP-6a private exponent
x = H(salt | H(I | ":" | P))per RFC 5054 §2.6.xties username + password + sa… - observability — (no submodules)- metrics — (no submodules)- pake — (no submodules)- pake-provider — (no submodules)- params — (no submodules)- params — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- server-finish — Complete the SRP-6a handshake on the server side after receiving the client's public value
Aand proofM1. Validate… - server-m2 — Split-roundtrip helper that computes the server proof
M2 = H(A | M1 | K)independently ofserverFinishHandshake. Us… - server-start — Begin the SRP-6a handshake on the server side. Loads the stored verifier
v(alongside the user's(I, salt)), draws… - verifier — (no submodules)- verifier — (no submodules)- errors — (no submodules)- groups — (no submodules) - 1024 — (no submodules) - groups-1024 — (no submodules) - 1536 — (no submodules) - groups-1536 — (no submodules) - 3072 — (no submodules) - groups-3072 — (no submodules) - 4096 — (no submodules) - groups-4096 — (no submodules) - 6144 — (no submodules) - groups-6144 — (no submodules) - 8192 — (no submodules) - groups-8192 — (no submodules) - groups-2048 — (no submodules)- hash — (no submodules) - hash-bridge — (no submodules)- k — Compute the SRP-6a multiplier parameter
k = H(N | PAD(g))per RFC 5054 §2.5.3. The multiplier is the structural chang… - modpow — Modular exponentiation primitive for
@suaveplan/srp. This is a thin wrapper over@noble/curves's hardened `pow(num,… - pad — The
PAD(x, N)helper from RFC 5054 §2.5.3. Returns a left-zero-extended copy ofxwhose length equals `N.byteLength… - proof — Internal helpers for computing the SRP-6a / RFC 2945 §3 mutual-authentication proofs
M1andM2. Both client and ser… - rng-bytes — Adapter helper that draws
nbytes from anyRngimplementing the@suaveplan/typescontract. TheRnginterface ma… - u — Compute the SRP-6a scrambling value
u = H(PAD(A) | PAD(B))per RFC 5054 §2.5.4.umixes the two ephemeral public va… - (./src/math/x.md) — Compute the SRP-6a private exponent
x = H(salt | H(I | ":" | P))per RFC 5054 §2.6.xties username + password + sa… - observability — (no submodules) - metrics — (no submodules)- pake — (no submodules) - pake-provider — (no submodules)- params — (no submodules) - params — (no submodules)- schemas — (no submodules) - schemas — (no submodules)- server-finish — Complete the SRP-6a handshake on the server side after receiving the client's public value
Aand proofM1. Validate… - server-m2 — Split-roundtrip helper that computes the server proof
M2 = H(A | M1 | K)independently ofserverFinishHandshake. Us… - server-start — Begin the SRP-6a handshake on the server side. Loads the stored verifier
v(alongside the user's(I, salt)), draws… - verifier — (no submodules) - verifier — (no submodules)
Install
bun add @suaveplan/srp
Quick start
import { computeVerifier } from "@suaveplan/srp/verifier";
import { clientStartHandshake, clientFinishHandshake } from "@suaveplan/srp/client";
import { serverStartHandshake, serverFinishHandshake } from "@suaveplan/srp/server";
import { params2048Sha256 } from "@suaveplan/srp/params";
import { nobleHashBridge } from "@suaveplan/srp/hash";
const params = params2048Sha256(nobleHashBridge("SHA256"));
const salt = crypto.getRandomValues(new Uint8Array(16));
const rng = {
nextUint32: () => {
const buf = new Uint32Array(1);
crypto.getRandomValues(buf);
return buf[0]!;
},
nextFloat: () => 0.5,
nextBytes: (n: number) => crypto.getRandomValues(new Uint8Array(n)),
};
// Registration — client computes the verifier and ships { I, salt, v }.
const { v } = computeVerifier("alice", "password123", salt, params);
const serverRecord = { I: "alice", salt, v };
// Handshake — client and server exchange (A, B) then (M1, M2).
const { a, A } = clientStartHandshake(rng, params);
const { b, B } = serverStartHandshake(serverRecord.v, rng, params);
const client = clientFinishHandshake("alice", "password123", salt, A, B, a, params);
const server = serverFinishHandshake(
"alice",
salt,
A,
B,
b,
serverRecord.v,
client.M1,
params
);
// client.K === server.K; both sides have authenticated each other.
Modules
| Module | Subpath | Description |
|---|---|---|
| groups/groups-2048 | @suaveplan/srp/groups |
Default 2048-bit safe-prime group constants |
| groups/1024/groups-1024 | @suaveplan/srp/groups/1024 |
RFC 5054 Appendix A 1024-bit group (legacy / vectors) |
| groups/1536/groups-1536 | @suaveplan/srp/groups/1536 |
RFC 5054 Appendix A 1536-bit group |
| groups/3072/groups-3072 | @suaveplan/srp/groups/3072 |
RFC 5054 Appendix A 3072-bit group |
| groups/4096/groups-4096 | @suaveplan/srp/groups/4096 |
RFC 5054 Appendix A 4096-bit group |
| groups/6144/groups-6144 | @suaveplan/srp/groups/6144 |
RFC 5054 Appendix A 6144-bit group |
| groups/8192/groups-8192 | @suaveplan/srp/groups/8192 |
RFC 5054 Appendix A 8192-bit group |
| params/params | @suaveplan/srp/params |
SrpParams + factory + validator |
| math/modpow | (root) | modPow + bigIntToBytes / bytesToBigInt |
| math/pad | (root) | RFC 5054 §2.5.3 PAD helper |
| math/k | (root) | computeK — multiplier parameter |
| math/u | (root) | computeU — scrambling value |
| math/x | (root) | computeX — private exponent derivation |
| math/proof | (root) | computeM1 / computeM2 proof formulae |
| math/rng-bytes | (root) | Rng → Uint8Array adapter |
| verifier/verifier | @suaveplan/srp/verifier |
computeVerifier registration helper |
| client/client-start | @suaveplan/srp/client |
clientStartHandshake |
| client/client-finish | @suaveplan/srp/client |
clientFinishHandshake |
| client/client-verify | @suaveplan/srp/client |
clientVerifyServerProof |
| server/server-start | @suaveplan/srp/server |
serverStartHandshake |
| server/server-finish | @suaveplan/srp/server |
serverFinishHandshake |
| server/server-m2 | @suaveplan/srp/server |
serverComputeM2 split-roundtrip helper |
| pake/pake-provider | @suaveplan/srp/pake |
Augmented-PAKE seam + SRP-6a impl |
| hash/hash-bridge | @suaveplan/srp/hash |
nobleHashBridge / subtleHashBridge / default |
| errors/errors | @suaveplan/srp/errors |
SRP_CODES + SrpError |
| observability/metrics | (root) | OTel srp.handshake_duration_ms + counters |
| schemas/schemas | (root) | Zod boundary schemas |
Conformance
- RFC 5054 Appendix B 1024/SHA-1 vectors — every intermediate (
k,x,v,u,S) byte-exact. - 2048/SHA-256 locally-derived fixture (
src/__fixtures__/vectors-2048-sha256.json) — generated bybun scripts/generate-srp-vectors.ts, byte-stable across runs. - Property test — 1000 random
(I, P, salt)triples through the full handshake;client.K === server.Kon every run. - All MUST-abort gates from RFC 5054 §2.5.4 (
A ≡ 0,B ≡ 0,u ≡ 0) wired and tested. - Constant-time compare on
M1,M2, andSvia@suaveplan/crypto-utils.constantTimeEqual.
Test vector generator
bun scripts/generate-srp-vectors.ts [--seed=42]
Regenerates src/__fixtures__/vectors-2048-sha256.json deterministically.