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

164 lines
17 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# @suaveplan/password-generator - Cryptographically-strong password and passphrase generator — char-class, pronounceable, EFF Diceware, PIN, entropy estimator. Universal, zero browser/Node deps.
## Summary
Cryptographically-strong password and passphrase generator — char-class,
pronounceable, EFF Diceware, and PIN modes with bias-free RNG, real entropy
estimates, and injectable `Rng` for deterministic replay. Universal
(zero browser / Node / React deps).
The package owns the surface end-to-end: bundled EFF Long (7776) and EFF
Short 1 (1296) wordlists, Lemire-style rejection-sampling `randomInt` for
unbiased integer draws, Fisher-Yates shuffle, char-class quotas, configurable
passphrase decoration, an entropy estimator, and a `assertStrength` guard.
<!-- begin:auto-docs -->
## Documentation tree
- [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [errors](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [codes](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - pronounceable — `generatePronounceablePassword(opts…
- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs --> - pronounceable — `generatePronounceablePassword(opts…
- [pronounceable](./src/password/pronounceable.md) — `generatePronounceablePassword(opts, rng?)` emits CVC-pattern (consonant–vowel–consonant) syllables suitable for should…
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [default-rng](./src/random/default-rng.md) — `defaultRng()` builds the default `Rng` backed by `@suaveplan/crypto-utils.randomBytes`, which delegates to `crypto.get…
- [fisher-yates](./src/random/fisher-yates.md) — `shuffleInPlace(array, rng)` performs an in-place Fisher–Yates / Knuth shuffle parameterised over the bias-free `random…
- [random-int](./src/random/random-int.md) — `randomInt(rng, max)` returns a uniformly-distributed integer in the half-open interval `[0, max)` for any `max ∈ [1, 2…
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ <!-- end:auto-docs -->
- [eff-long](./src/wordlists/eff-long.md) — Bundles the EFF Long Wordlist as a frozen `readonly string[]` so callers who only want passphrase generation pull this…
- [eff-short](./src/wordlists/eff-short.md) — Bundles EFF's Short Wordlist #1 — 1296 entries (4-dice / 6⁴), ≈ 10.34 bits/word, every entry ≤ 5 ASCII characters. Sour…
- [registry](./src/wordlists/registry.md) — The wordlist registry exposes a small plugin API — `registerWordlist`, `getWordlist`, `listWordlists` — that lets calle…
<!-- end:auto-docs --> - [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [pronounceable](./src/password/pronounceable.md) — `generatePronounceablePassword(opts, rng?)` emits CVC-pattern (consonant–vowel–consonant) syllables suitable for should…
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [default-rng](./src/random/default-rng.md) — `defaultRng()` builds the default `Rng` backed by `@suaveplan/crypto-utils.randomBytes`, which delegates to `crypto.get…
- [fisher-yates](./src/random/fisher-yates.md) — `shuffleInPlace(array, rng)` performs an in-place Fisher–Yates / Knuth shuffle parameterised over the bias-free `random…
- [random-int](./src/random/random-int.md) — `randomInt(rng, max)` returns a uniformly-distributed integer in the half-open interval `[0, max)` for any `max ∈ [1, 2…
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [eff-long](./src/wordlists/eff-long.md) — Bundles the EFF Long Wordlist as a frozen `readonly string[]` so callers who only want passphrase generation pull this…
- [eff-short](./src/wordlists/eff-short.md) — Bundles EFF's Short Wordlist #1 — 1296 entries (4-dice / 6⁴), ≈ 10.34 bits/word, every entry ≤ 5 ASCII characters. Sour…
- [registry](./src/wordlists/registry.md) — The wordlist registry exposes a small plugin API — `registerWordlist`, `getWordlist`, `listWordlists` — that lets calle…
- [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [pronounceable](./src/password/pronounceable.md) — `generatePronounceablePassword(opts, rng?)` emits CVC-pattern (consonant–vowel–consonant) syllables suitable for should…
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [default-rng](./src/random/default-rng.md) — `defaultRng()` builds the default `Rng` backed by `@suaveplan/crypto-utils.randomBytes`, which delegates to `crypto.get…
- [fisher-yates](./src/random/fisher-yates.md) — `shuffleInPlace(array, rng)` performs an in-place Fisher–Yates / Knuth shuffle parameterised over the bias-free `random…
- [random-int](./src/random/random-int.md) — `randomInt(rng, max)` returns a uniformly-distributed integer in the half-open interval `[0, max)` for any `max ∈ [1, 2…
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [eff-long](./src/wordlists/eff-long.md) — Bundles the EFF Long Wordlist as a frozen `readonly string[]` so callers who only want passphrase generation pull this…
- [eff-short](./src/wordlists/eff-short.md) — Bundles EFF's Short Wordlist #1 — 1296 entries (4-dice / 6⁴), ≈ 10.34 bits/word, every entry ≤ 5 ASCII characters. Sour…
- [registry](./src/wordlists/registry.md) — The wordlist registry exposes a small plugin API — `registerWordlist`, `getWordlist`, `listWordlists` — that lets calle…
- [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [codes](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_- pronounceable — `generatePronounceablePassword(opts…
- [pronounceable](./src/password/pronounceable.md) — `generatePronounceablePassword(opts, rng?)` emits CVC-pattern (consonant–vowel–consonant) syllables suitable for should…
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [default-rng](./src/random/default-rng.md) — `defaultRng()` builds the default `Rng` backed by `@suaveplan/crypto-utils.randomBytes`, which delegates to `crypto.get…
- [fisher-yates](./src/random/fisher-yates.md) — `shuffleInPlace(array, rng)` performs an in-place Fisher–Yates / Knuth shuffle parameterised over the bias-free `random…
- [random-int](./src/random/random-int.md) — `randomInt(rng, max)` returns a uniformly-distributed integer in the half-open interval `[0, max)` for any `max ∈ [1, 2…
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [eff-long](./src/wordlists/eff-long.md) — Bundles the EFF Long Wordlist as a frozen `readonly string[]` so callers who only want passphrase generation pull this…
- [eff-short](./src/wordlists/eff-short.md) — Bundles EFF's Short Wordlist #1 — 1296 entries (4-dice / 6⁴), ≈ 10.34 bits/word, every entry ≤ 5 ASCII characters. Sour…
- [registry](./src/wordlists/registry.md) — The wordlist registry exposes a small plugin API — `registerWordlist`, `getWordlist`, `listWordlists` — that lets calle…
- [charsets](./src/charsets/charsets.md) — <!-- begin:auto-docs --> _(no submodules)_- [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_ - [entropy](./src/entropy/entropy.md) — <!-- begin:auto-docs --> _(no submodules)_- [errors](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_ - [codes](./src/errors/codes.md) — <!-- begin:auto-docs --> _(no submodules)_- [observability](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_ - [metrics](./src/observability/metrics.md) — <!-- begin:auto-docs --> _(no submodules)_- [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_ - [passphrase](./src/passphrase/passphrase.md) — <!-- begin:auto-docs --> _(no submodules)_- [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_ - [password](./src/password/password.md) — <!-- begin:auto-docs --> _(no submodules)_ - [pronounceable](./src/password/pronounceable.md) — `generatePronounceablePassword(opts, rng?)` emits CVC-pattern (consonant–vowel–consonant) syllables suitable for should…
- [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_ - [pin](./src/pin/pin.md) — <!-- begin:auto-docs --> _(no submodules)_- [default-rng](./src/random/default-rng.md) — `defaultRng()` builds the default `Rng` backed by `@suaveplan/crypto-utils.randomBytes`, which delegates to `crypto.get…
- [fisher-yates](./src/random/fisher-yates.md) — `shuffleInPlace(array, rng)` performs an in-place Fisher–Yates / Knuth shuffle parameterised over the bias-free `random…
- [random-int](./src/random/random-int.md) — `randomInt(rng, max)` returns a uniformly-distributed integer in the half-open interval `[0, max)` for any `max ∈ [1, 2…
- [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_ - [schemas](./src/schemas/schemas.md) — <!-- begin:auto-docs --> _(no submodules)_- [eff-long](./src/wordlists/eff-long.md) — Bundles the EFF Long Wordlist as a frozen `readonly string[]` so callers who only want passphrase generation pull this…
- [eff-short](./src/wordlists/eff-short.md) — Bundles EFF's Short Wordlist #1 — 1296 entries (4-dice / 6⁴), ≈ 10.34 bits/word, every entry ≤ 5 ASCII characters. Sour…
- [registry](./src/wordlists/registry.md) — The wordlist registry exposes a small plugin API — `registerWordlist`, `getWordlist`, `listWordlists` — that lets calle…
## Install
```bash
bun add @suaveplan/password-generator
```
## Quick Start
```ts
import {
assertStrength,
estimateEntropy,
generatePassphrase,
generatePassword,
generatePin,
} from "@suaveplan/password-generator";
// Char-class password
const pw = generatePassword({
length: 16,
requireLowercase: true,
requireUppercase: true,
requireDigits: true,
requireSymbols: true,
});
// 6-word EFF Long passphrase (≈ 77.5 bits)
const phrase = generatePassphrase({});
// 6-digit PIN
const pin = generatePin(6);
// Strength check
assertStrength(pw, 80); // throws PWGEN.STRENGTH_INSUFFICIENT if < 80 bits
const { bits, charsetSize } = estimateEntropy(pw);
```
## Tree-Shaking
Each major surface ships at its own subpath so consumers pull only what they
need:
```ts
import { generatePassword } from "@suaveplan/password-generator/password";
import { generatePassphrase } from "@suaveplan/password-generator/passphrase";
import { generatePin } from "@suaveplan/password-generator/pin";
import { EFF_LONG_WORDLIST } from "@suaveplan/password-generator/wordlists/eff-long";
import { EFF_SHORT_WORDLIST } from "@suaveplan/password-generator/wordlists/eff-short";
```
A consumer that imports only `./password` does not pull the 85 KB EFF Long
list. A consumer that imports only `./pin` pulls neither wordlist.
## Modules
- [`random/random-int`](./src/random/random-int.md) — bias-free `randomInt`
via Lemire rejection sampling.
- [`random/fisher-yates`](./src/random/fisher-yates.md) — Fisher-Yates shuffle
built on the unbiased picker.
- [`random/default-rng`](./src/random/default-rng.md) — default `Rng` wrapping
`@suaveplan/crypto-utils.randomBytes`.
- [`charsets/charsets`](./src/charsets/charsets.md) — `LOWERCASE` / `UPPERCASE`
/ `DIGITS` / `SYMBOLS` / `AMBIGUOUS` / `LOOKALIKES` + `buildEffectiveCharset`.
- [`password/password`](./src/password/password.md) — char-class generator with
required-class quotas.
- [`password/pronounceable`](./src/password/pronounceable.md) — CVC-pattern
pronounceable generator.
- [`passphrase/passphrase`](./src/passphrase/passphrase.md) — EFF Diceware
passphrase generator.
- [`pin/pin`](./src/pin/pin.md) — uniform digit-only PIN generator.
- [`entropy/entropy`](./src/entropy/entropy.md) — entropy estimator and
`assertStrength` guard.
- [`wordlists/eff-long`](./src/wordlists/eff-long.md) — bundled EFF Long
Wordlist (7776 entries).
- [`wordlists/eff-short`](./src/wordlists/eff-short.md) — bundled EFF Short
Wordlist 1 (1296 entries).
- [`wordlists/registry`](./src/wordlists/registry.md) — plugin API for caller-
supplied wordlists.
- [`errors/codes`](./src/errors/codes.md) — `PWGEN_CODES` registry and
`PwgenError` class.
- [`schemas/schemas`](./src/schemas/schemas.md) — Zod boundary schemas.
- [`observability/metrics`](./src/observability/metrics.md) — OpenTelemetry
histograms and counters.
## License
MIT