# `k` ## Purpose Compute the SRP-6a multiplier parameter `k = H(N | PAD(g))` per RFC 5054 §2.5.3. The multiplier is the structural change that distinguishes SRP-6a from SRP-6 (the latter set `k = 3`, which broke under a generator-substitution attack). Mixing both `N` and the padded generator into a hash binds `k` to the chosen group so the multiplier cannot be transplanted between groups by an attacker who controls one side of the handshake. ## Features - Pure function of `(N, g, hash)`. - Returns the hash's native digest size (32 bytes for SHA-256, 20 for SHA-1). - Uses `PAD` to zero-extend `g` to `byteLength(N)` before hashing, per RFC 5054 §2.5.3. - Caller-side memoization safe — `params` is treated as immutable. ## Usage: Basic Example ```ts import { computeK } from "@suaveplan/srp"; import { params2048Sha256 } from "@suaveplan/srp/params"; import { nobleHashBridge } from "@suaveplan/srp/hash"; const params = params2048Sha256(nobleHashBridge("SHA256")); const k = computeK(params); console.log(k.byteLength); // 32 ``` ## Usage: Advanced Example ```ts import { computeK } from "@suaveplan/srp"; import { params2048Sha256 } from "@suaveplan/srp/params"; import { nobleHashBridge } from "@suaveplan/srp/hash"; const params = params2048Sha256(nobleHashBridge("SHA256")); const kCached = computeK(params); // Reuse k across many handshakes — k is a pure function of (N, g, hash). function getCachedK(): Uint8Array { return kCached; } console.log(getCachedK().byteLength); ``` ## API Reference ### `computeK(params: SrpParams): Uint8Array` Returns `H(N | PAD(g))` using `params.hash`. Result length equals `params.hash.digestSize`. ## Implementation Notes `k` is a pure function of `(N, g, hash)` and is therefore safe to memoize across handshakes; consumers that mount a long-lived `SrpParams` value can cache `k` outside the per-request critical path. This package does NOT cache automatically because the `SrpParams.hash` field MAY be a stateful subtle bridge that the consumer rotates per session; deferring the memoization decision to the caller keeps the contract simple. The digest call goes through `digestSync` (from `../hash/hash-bridge.js`), which throws `SRP.HASH_UNSUPPORTED` if the consumer accidentally wires an async `HashLike` into a sync handshake path. Without that gate, an awaited Promise would silently coerce to `[object Promise]` bytes downstream.