Files
2026-06-09 21:06:27 +01:00
..
2026-06-09 21:06:27 +01:00
2026-06-09 21:06:27 +01:00

@suaveplan/password-strength - zxcvbn-style password strength estimator — pattern-matching + dictionary cracker model per Wheeler 2016. Zero browser/Node/React deps.

Summary

zxcvbn-style password strength estimator — pattern-matching + dictionary cracker model per Wheeler 2016. Universal; zero browser/Node/React deps. Re-implementation of the open-source dropbox/zxcvbn algorithm in style: Zod boundaries, OTel histograms + counters, structured PWSTRENGTH.* error codes, 100% coverage, multilingual dictionary subpaths, runtime dictionary swap, observable streaming variant, and a hard 200-character DoS guard.

Documentation tree

  • assess — (no submodules)
    • assess-reactive — Debounce + cancel-on-newer-input wrapper around assess for UI strength meters that update as the user types. Each new…
    • assess — (no submodules)
  • dicts — (no submodules) - wikipedia — _(no submodules…
    • de — (no submodules)
    • english-wikipedia — Frequency-ranked dictionary of the most common English tokens observed in Wikipedia. The matcher uses this to flag pass…
    • names — Frequency-ranked dictionaries of common US given names (male and female) and surnames. Names are over-represented in pa…
    • passwords — Frequency-ranked dictionary of the most common passwords observed across public breach corpora (RockYou, HaveIBeenPwned…
    • es — (no submodules)
    • fr — (no submodules)
    • ru — (no submodules)
    • zh-Hans — (no submodules)
    • load-dictionaries — (no submodules) - wikipedia — _(no submodules…
  • errors — (no submodules)
  • feedback — (no submodules)
  • graphs — (no submodules) - azerty — (no submodules)…
  • matchers — (no submodules) - date — (no submodules) <!…
    • date — (no submodules)
      • date — (no submodules)
    • dictionary — (no submodules) - l33t-table — Provides the default character → lette…
      • dictionary — (no submodules) - l33t-table — Provides the default character → lette…
      • l33t-table — Provides the default character → letter substitution table used by the dictionaryMatch matcher to recognise l33t-enco…
    • keyboard — (no submodules)
    • regex — (no submodules)
      • regex — (no submodules)
    • repeat — (no submodules)
    • sequence — (no submodules)
    • types — (no submodules) - date — (no submodules) <!…
  • observability — (no submodules)
  • schemas — (no submodules)
  • crack-times — Maps a guesses count to seconds-to-crack under the four canonical attack scenarios from Wheeler 2016 section 5: onlin…
  • estimate-guesses — Implements the Wheeler 2016 section 4 closed-form guess estimates per pattern type: dictionary (rank × uppercase × l33t…
  • most-guessable-match-sequence — Picks the lowest-Π guesses × k! cover of the password from the union of pattern matches plus implicit bruteforce-char…
  • score — Maps a guesses count to a coarse integer score per Wheeler 2016 section 5. This score (0–4) is what most consumer…
- [assess-reactive](./src/assess/assess-reactive.md) — Debounce + cancel-on-newer-input wrapper around `assess` for UI strength meters that update as the user types. Each new…
  • assess — (no submodules)- dicts — (no submodules)- de — (no submodules)- wikipedia — (no submodules)- english-wikipedia — Frequency-ranked dictionary of the most common English tokens observed in Wikipedia. The matcher uses this to flag pass…
  • names — Frequency-ranked dictionaries of common US given names (male and female) and surnames. Names are over-represented in pa…
  • passwords — Frequency-ranked dictionary of the most common passwords observed across public breach corpora (RockYou, HaveIBeenPwned…
  • es — (no submodules)- wikipedia — (no submodules)- fr — (no submodules)- wikipedia — (no submodules)- ru — (no submodules)- wikipedia — (no submodules)- zh-Hans — (no submodules)- wikipedia — (no submodules)- load-dictionaries — (no submodules)- errors — (no submodules)- error-codes — (no submodules)- feedback — (no submodules)- feedback — (no submodules)- graphs — (no submodules)- azerty — (no submodules)- azerty — (no submodules)- dvorak — (no submodules)- dvorak — (no submodules)- qwerty — (no submodules)- qwerty — (no submodules)- validate-graph — (no submodules)- matchers — (no submodules)- date — (no submodules)- date — (no submodules)- dictionary — (no submodules)- l33t-table — Provides the default character → lette…
    • dictionary — (no submodules)- l33t-table — Provides the default character → lette…
    • l33t-table — Provides the default character → letter substitution table used by the dictionaryMatch matcher to recognise l33t-enco…
  • keyboard — (no submodules)- keyboard — (no submodules)- regex — (no submodules)- regex — (no submodules)- repeat — (no submodules)- repeat — (no submodules)- sequence — (no submodules)- sequence — (no submodules)- types — (no submodules)- observability — (no submodules)- metrics — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- crack-times — Maps a guesses count to seconds-to-crack under the four canonical attack scenarios from Wheeler 2016 section 5: onlin…
  • estimate-guesses — Implements the Wheeler 2016 section 4 closed-form guess estimates per pattern type: dictionary (rank × uppercase × l33t…
  • most-guessable-match-sequence — Picks the lowest-Π guesses × k! cover of the password from the union of pattern matches plus implicit bruteforce-char…
  • score — Maps a guesses count to a coarse integer score per Wheeler 2016 section 5. This score (0–4) is what most consumer…
  • assess-reactive — Debounce + cancel-on-newer-input wrapper around assess for UI strength meters that update as the user types. Each new…
  • assess — (no submodules)- dicts — (no submodules)- wikipedia — <!-- begin:auto-…
    • de — (no submodules)- wikipedia — (no submodules)- english-wikipedia — Frequency-ranked dictionary of the most common English tokens observed in Wikipedia. The matcher uses this to flag pass…
    • names — Frequency-ranked dictionaries of common US given names (male and female) and surnames. Names are over-represented in pa…
    • passwords — Frequency-ranked dictionary of the most common passwords observed across public breach corpora (RockYou, HaveIBeenPwned…
    • es — (no submodules)- wikipedia — (no submodules)- fr — (no submodules)- wikipedia — (no submodules)- ru — (no submodules)- wikipedia — (no submodules)- zh-Hans — (no submodules)- wikipedia — (no submodules)- load-dictionaries — (no submodules)- wikipedia — <!-- begin:auto-…
  • errors — (no submodules)- error-codes — (no submodules)- feedback — (no submodules)- feedback — (no submodules)- graphs — (no submodules)- azerty — <!-- begin:auto-doc…
  • matchers — (no submodules)- date — <!-- begin:auto-docs…
    • date — (no submodules)- date — (no submodules)- dictionary — (no submodules)- l33t-table — Provides the default character → lette…
      • dictionary — (no submodules)- l33t-table — Provides the default character → lette…
      • l33t-table — Provides the default character → letter substitution table used by the dictionaryMatch matcher to recognise l33t-enco…
    • keyboard — (no submodules)- keyboard — (no submodules)- regex — (no submodules)- regex — (no submodules)- repeat — (no submodules)- repeat — (no submodules)- sequence — (no submodules)- sequence — (no submodules)- types — (no submodules)- date — <!-- begin:auto-docs…
  • observability — (no submodules)- metrics — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- crack-times — Maps a guesses count to seconds-to-crack under the four canonical attack scenarios from Wheeler 2016 section 5: onlin…
  • estimate-guesses — Implements the Wheeler 2016 section 4 closed-form guess estimates per pattern type: dictionary (rank × uppercase × l33t…
  • most-guessable-match-sequence — Picks the lowest-Π guesses × k! cover of the password from the union of pattern matches plus implicit bruteforce-char…
  • score — Maps a guesses count to a coarse integer score per Wheeler 2016 section 5. This score (0–4) is what most consumer…
  • assess-reactive — Debounce + cancel-on-newer-input wrapper around assess for UI strength meters that update as the user types. Each new…
  • assess — (no submodules)- dicts — (no submodules)- wikipedia — _(no submodule…
    • de — (no submodules)- wikipedia — (no submodules)- english-wikipedia — Frequency-ranked dictionary of the most common English tokens observed in Wikipedia. The matcher uses this to flag pass…
    • names — Frequency-ranked dictionaries of common US given names (male and female) and surnames. Names are over-represented in pa…
    • passwords — Frequency-ranked dictionary of the most common passwords observed across public breach corpora (RockYou, HaveIBeenPwned…
    • es — (no submodules)- wikipedia — (no submodules)- fr — (no submodules)- wikipedia — (no submodules)- ru — (no submodules)- wikipedia — (no submodules)- zh-Hans — (no submodules)- wikipedia — (no submodules)- load-dictionaries — (no submodules)- wikipedia — _(no submodule…
  • errors — (no submodules)- error-codes — (no submodules)- feedback — (no submodules)- feedback — (no submodules)- graphs — (no submodules)- azerty — (no submodules)…
  • matchers — (no submodules)- date — (no submodules) <…
    • date — (no submodules)- date — (no submodules)- dictionary — (no submodules)- l33t-table — Provides the default character → lette…
      • dictionary — (no submodules)- l33t-table — Provides the default character → lette…
      • l33t-table — Provides the default character → letter substitution table used by the dictionaryMatch matcher to recognise l33t-enco…
    • keyboard — (no submodules)- keyboard — (no submodules)- regex — (no submodules)- regex — (no submodules)- repeat — (no submodules)- repeat — (no submodules)- sequence — (no submodules)- sequence — (no submodules)- types — (no submodules)- date — (no submodules) <…
  • observability — (no submodules)- metrics — (no submodules)- schemas — (no submodules)- schemas — (no submodules)- crack-times — Maps a guesses count to seconds-to-crack under the four canonical attack scenarios from Wheeler 2016 section 5: onlin…
  • estimate-guesses — Implements the Wheeler 2016 section 4 closed-form guess estimates per pattern type: dictionary (rank × uppercase × l33t…
  • most-guessable-match-sequence — Picks the lowest-Π guesses × k! cover of the password from the union of pattern matches plus implicit bruteforce-char…
  • score — Maps a guesses count to a coarse integer score per Wheeler 2016 section 5. This score (0–4) is what most consumer…
  • assess-reactive — Debounce + cancel-on-newer-input wrapper around assess for UI strength meters that update as the user types. Each new…
  • assess — (no submodules)- dicts — (no submodules) - de — (no submodules) - wikipedia — (no submodules) - english-wikipedia — Frequency-ranked dictionary of the most common English tokens observed in Wikipedia. The matcher uses this to flag pass…
    • names — Frequency-ranked dictionaries of common US given names (male and female) and surnames. Names are over-represented in pa…
    • passwords — Frequency-ranked dictionary of the most common passwords observed across public breach corpora (RockYou, HaveIBeenPwned…
    • es — (no submodules) - wikipedia — (no submodules) - fr — (no submodules) - wikipedia — (no submodules) - ru — (no submodules) - wikipedia — (no submodules) - zh-Hans — (no submodules) - wikipedia — (no submodules) - load-dictionaries — (no submodules)- errors — (no submodules) - error-codes — (no submodules)- feedback — (no submodules) - feedback — (no submodules)- graphs — (no submodules) - azerty — (no submodules) - azerty — (no submodules) - dvorak — (no submodules) - dvorak — (no submodules) - qwerty — (no submodules) - qwerty — (no submodules) - validate-graph — (no submodules)- matchers — (no submodules) - date — (no submodules) - date — (no submodules) - dictionary — (no submodules) - dictionary — (no submodules) - l33t-table — Provides the default character → letter substitution table used by the dictionaryMatch matcher to recognise l33t-enco…
    • keyboard — (no submodules) - keyboard — (no submodules) - regex — (no submodules) - regex — (no submodules) - repeat — (no submodules) - repeat — (no submodules) - sequence — (no submodules) - sequence — (no submodules) - types — (no submodules)- observability — (no submodules) - metrics — (no submodules)- schemas — (no submodules) - schemas — (no submodules)- crack-times — Maps a guesses count to seconds-to-crack under the four canonical attack scenarios from Wheeler 2016 section 5: onlin…
  • estimate-guesses — Implements the Wheeler 2016 section 4 closed-form guess estimates per pattern type: dictionary (rank × uppercase × l33t…
  • most-guessable-match-sequence — Picks the lowest-Π guesses × k! cover of the password from the union of pattern matches plus implicit bruteforce-char…
  • score — Maps a guesses count to a coarse integer score per Wheeler 2016 section 5. This score (0–4) is what most consumer…

Install

bun add @suaveplan/password-strength

Quick Start

import { assess } from "@suaveplan/password-strength";

const result = assess("Password1!");
console.log(result.score);            // 0..4 bucket
console.log(result.guesses);          // closed-form guess count
console.log(result.feedback.warning); // English-default UI string
console.log(result.crackTimes.offline_fast_hashing_1e10_per_second);

Modules

Module Doc
errors/error-codes src/errors/error-codes.md
matchers/dictionary src/matchers/dictionary/dictionary.md
matchers/dictionary/l33t-table src/matchers/dictionary/l33t-table.md
matchers/sequence src/matchers/sequence/sequence.md
matchers/repeat src/matchers/repeat/repeat.md
matchers/date src/matchers/date/date.md
matchers/keyboard src/matchers/keyboard/keyboard.md
matchers/regex src/matchers/regex/regex.md
graphs/qwerty src/graphs/qwerty/qwerty.md
graphs/dvorak src/graphs/dvorak/dvorak.md
graphs/azerty src/graphs/azerty/azerty.md
graphs/validate-graph src/graphs/validate-graph.md
dicts/en/passwords src/dicts/en/passwords.md
dicts/en/english-wikipedia src/dicts/en/english-wikipedia.md
dicts/en/names src/dicts/en/names.md
dicts/de/wikipedia src/dicts/de/wikipedia.md
dicts/fr/wikipedia src/dicts/fr/wikipedia.md
dicts/es/wikipedia src/dicts/es/wikipedia.md
dicts/zh-Hans/wikipedia src/dicts/zh-Hans/wikipedia.md
dicts/ru/wikipedia src/dicts/ru/wikipedia.md
dicts/load-dictionaries src/dicts/load-dictionaries.md
scoring/score src/scoring/score.md
scoring/crack-times src/scoring/crack-times.md
scoring/estimate-guesses src/scoring/estimate-guesses.md
scoring/most-guessable-match-sequence src/scoring/most-guessable-match-sequence.md
assess/assess src/assess/assess.md
assess/assess-reactive src/assess/assess-reactive.md
feedback/feedback src/feedback/feedback.md
schemas src/schemas/schemas.md
observability/metrics src/observability/metrics.md

Features

  • Six pattern matchers: dictionary (with l33t + reverse), sequence, repeat, date, keyboard adjacency, regex
  • DP cover with factorial penalty per Wheeler section 4
  • Four crack-time scenarios, site-tunable via adjustments
  • 5-bucket score (0–4) per Wheeler section 5
  • 200-character DoS guard
  • Streaming variant (assessReactive) with debounce + cancel-on-newer
  • Runtime dictionary swap via loadDictionaries
  • Multilingual dictionary subpaths (en, de, fr, es, zh-Hans, ru)
  • Keyboard graph subpaths (qwerty, dvorak, azerty)
  • Zod-validated boundaries at every public entry point
  • OTel histogram + counters for assess duration, score distribution, error code, and matcher hit count

Baseline benchmarks

Run bun run src/__benchmarks__/assess.bench.ts to print baseline numbers locally. Indicative timings on commodity hardware (single fork, no warmup):

Bench Mean
8-char password ~0.5 ms
64-char password ~5 ms
Dictionary-heavy ~1 ms
DP n=100 ~3 ms
DP n=199 ~12 ms

The 200-character DoS guard keeps p99 well under the 5 ms it() default.