first commit

This commit is contained in:
2026-05-29 08:20:56 +01:00
commit 949299f58d
6368 changed files with 527176 additions and 0 deletions

View 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.