first commit
This commit is contained in:
58
docs/security-stack/security/srp/src/math/rng-bytes.md
Normal file
58
docs/security-stack/security/srp/src/math/rng-bytes.md
Normal file
@@ -0,0 +1,58 @@
|
||||
# `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.
|
||||
Reference in New Issue
Block a user