# `rng-bytes` ## Purpose Adapter helper that draws `n` bytes from any `Rng` implementing the `@suaveplan/types` contract. The `Rng` interface mandates `nextUint32` but `nextBytes` is optional; SRP's client/server start functions need a `≥ 256`-bit random exponent, so this helper unifies the two paths. When the supplied `Rng` exposes `nextBytes`, that path is used directly; otherwise the helper packs `nextUint32` calls into a byte buffer with little-endian field extraction. Both paths produce uniform output across the full byte range. ## Features - Single entry point regardless of whether the `Rng` provides `nextBytes`. - Little-endian packing of `nextUint32` for portability across deterministic seeded RNGs. - No allocation overhead on the `nextBytes` fast path. - Pure function — no global state. ## Usage: Basic Example ```ts import { rngBytes } from "@suaveplan/srp"; import type { Rng } from "@suaveplan/types"; const rng: Rng = { nextUint32: () => 0x12345678, nextFloat: () => 0.5, }; const bytes = rngBytes(rng, 32); console.log(bytes.byteLength); // 32 ``` ## Usage: Advanced Example ```ts import { rngBytes } from "@suaveplan/srp"; import type { Rng } from "@suaveplan/types"; // Web-Crypto-backed RNG with native nextBytes — the fast path. const cryptoRng: Rng = { nextUint32: () => { const buf = new Uint32Array(1); crypto.getRandomValues(buf); return buf[0]; }, nextFloat: () => crypto.getRandomValues(new Uint32Array(1))[0] / 2 ** 32, nextBytes: (n: number) => crypto.getRandomValues(new Uint8Array(n)), }; const a = rngBytes(cryptoRng, 32); console.log(a.byteLength); ``` ## API Reference ### `rngBytes(rng: Rng, n: number): Uint8Array` Returns an `n`-byte `Uint8Array` of uniformly distributed bytes. When `rng.nextBytes` exists, delegates directly. Otherwise packs `nextUint32` outputs into the buffer in little-endian byte order. ## Implementation Notes The little-endian pack order on the `nextUint32` fallback is arbitrary — the resulting bytes feed straight into a `bigInt` decode that does NOT preserve endianness of the source 32-bit words, so any consistent order is correct. We pick little-endian because it matches the layout of `Uint32Array` views over `ArrayBuffer` on every modern platform, so an implementation that wants to optimize further can swap to a typed-array view without changing behaviour. The helper is deliberately not memoized: each call draws fresh entropy. Callers that need a deterministic exponent for testing supply a seeded `Rng` instance whose `nextUint32` reproduces the same word stream; `rngBytes` then yields a deterministic byte sequence from that stream.