Files
2026-05-27 23:47:53 +01:00

2.3 KiB

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

import { generateRecoveryCodes } from "@suaveplan/otp";

const codes = generateRecoveryCodes(10);
// ten codes shaped like "XXXX-XXXX-XXXX-XXXX".

Usage: Advanced Example

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.