Files
skills/docs/security-stack/security/otp/src/recovery/generate.md
2026-05-29 08:20:56 +01:00

65 lines
2.3 KiB
Markdown

# `recovery/generate`
## Purpose
Generate Crockford-base32 recovery codes — the printable single-use fallback
the user prints / writes down when first enrolling MFA. Default form is the
conventional `XXXX-XXXX-XXXX-XXXX` quad-grouped 16-character shape. RNG is
injectable so deterministic test fixtures can produce stable byte strings;
production callers leave it default and pull from the platform CSPRNG.
## Features
- Crockford alphabet (excludes `I`, `L`, `O`, `U` to avoid hand-copy
collisions with `1` / `0`).
- Configurable length / group size / separator.
- Injectable `Rng` (`@suaveplan/types`) — `nextBytes` preferred, falls back
to `nextUint32` assembly.
- Default RNG draws from `randomBytes` in `@suaveplan/crypto-utils`.
## Usage: Basic Example
```ts
import { generateRecoveryCodes } from "@suaveplan/otp";
const codes = generateRecoveryCodes(10);
// ten codes shaped like "XXXX-XXXX-XXXX-XXXX".
```
## Usage: Advanced Example
```ts
import { generateRecoveryCodes } from "@suaveplan/otp";
// Custom form for a UI that accepts longer codes.
const codes = generateRecoveryCodes(5, {
length: 20,
groupSize: 5,
separator: " ",
});
```
## API Reference
- `generateRecoveryCodes(count, opts?): string[]` — primary API.
- `bytesFromRng(rng, n): Uint8Array` — exported helper used by the
recovery-hash module to draw salt bytes from the same RNG.
- `RecoveryCodeOptions` — `{ length?: number; groupSize?: number;
separator?: string; rng?: Rng }`.
## Implementation Notes
The 32-character alphabet is power-of-two sized so taking `byte & 0x1f`
introduces no modulo bias. When the supplied `Rng` only exposes
`nextUint32`, the helper assembles bytes from 32-bit words and uses guarded
indexing so a request for `n < 4` writes only the bytes the caller asked
for. The default RNG is the platform CSPRNG via `@suaveplan/crypto-utils` —
bring your own only for deterministic tests.
Crockford-base32's character exclusions (`I`, `L`, `O`, `U`) are the
practical reason this module does not reuse the standard RFC 4648 alphabet
exposed by the `base32` module: hand-copied recovery codes get transcribed
under stress, and visually-similar characters cause silent enrollment
errors. The two alphabets are distinct on purpose and must not be confused
when implementing import / export between password managers.