Skip to content

Latest commit

 

History

History
186 lines (146 loc) · 12 KB

File metadata and controls

186 lines (146 loc) · 12 KB

Changelog

All notable changes to this project will be documented in this file.

The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.

2.0.0 - 2026-05-28

Fixed

  • User-input dictionary matchers now use the Trie path, preventing O(n²) slowdowns on long passwords (#89)

Added

  • Zxcvbn::TesterBuilder: fluent builder for constructing a Tester with custom word lists and options. Obtain a builder via Zxcvbn.tester_builder, then chain add_word_list, max_password_length, and build.
  • Zxcvbn::Guesses module with per-pattern guess estimation formulas matching zxcvbn.js v4: bruteforce, dictionary (with uppercase and l33t variation multipliers), spatial, repeat, sequence, digits, year, and date (#69)
  • us_tv_and_film frequency list (19,160 entries) introduced in zxcvbn.js v4 (#69)
  • Reverse dictionary matching in Omnimatch so reversed words (e.g. "drowssap") are detected and scored (#69)
  • guesses and guesses_log10 fields on Zxcvbn::Score (#69)
  • guesses, guesses_log10, base_token, repeat_count, and base_guesses fields on Zxcvbn::Match (#69)
  • YARD documentation for all public classes, modules, and methods (#72)

Changed

  • Breaking: Zxcvbn::Tester.new now requires data: and max_password_length: keyword arguments with no defaults. Use Zxcvbn.tester_builder.build to construct a Tester.
  • Breaking: English frequency list dictionary name renamed from english to english_wikipedia, matching the zxcvbn.js source. Affects match.dictionary_name in results (#90)
  • Zxcvbn.test now reuses a shared Tester instance across calls, avoiding repeated dictionary parsing (#80)
  • Repeat base tokens are now scored without user_inputs, matching zxcvbn.js v4. Previously, user-supplied words were propagated into the recursive scoring of a repeat's base token, causing repeat matches of user-supplied words to score lower than JS would report (#83)
  • Zxcvbn::Score is now an immutable value object backed by Ruby's Data. Attribute setters (calc_time=, feedback=, etc.) have been removed. Instances now support structural equality (==/eql?/hash) and the with method for creating modified copies (#74)
  • Breaking: Zxcvbn::Match is now an immutable value object backed by Ruby's Data. Attribute setters have been removed. Instances now support structural equality (==/eql?/hash) and the with method for creating modified copies (#92)
  • Breaking: Match#to_hash has been removed. Use match.to_h instead — note the shape differs: keys are symbols (not strings), all 28 attributes are included (not just those that were set), and order follows the member definition rather than being sorted alphabetically. To replicate the old behaviour: match.to_h.transform_keys(&:to_s).compact.sort.to_h. Additionally, to_hash was Ruby's implicit-conversion hook, so any code that splatted a match (**match) or passed it to Hash() will now raise TypeError — use match.to_h explicitly instead (#92)
  • Breaking: Zxcvbn::Feedback is now an immutable value object backed by Ruby's Data. Attribute setters (warning=, suggestions=) have been removed. Instances now support structural equality (==/eql?/hash) and the with method for creating modified copies (#77)
  • Breaking: Scoring algorithm aligned with zxcvbn.js v4.4.2. The dynamic programming step now minimises total guesses (factorial(l) × cumulative_product + MIN_GUESSES^(l-1) penalty) instead of entropy bits. Scores for many passwords will change (#69)
  • Breaking: Bruteforce cardinality is now fixed at 10 (digits only), matching zxcvbn.js v4. Previously it was computed dynamically from the character classes present in the password (10–95), so bruteforce guesses for passwords containing letters or symbols will change (#69)
  • Breaking: Repeat matcher now detects multi-character repeating units (e.g. abcabc). The base_token field holds the repeating unit (which may be more than one character); repeated_char has been removed (#69)
  • Breaking: Match#entropy, Match#base_entropy, Match#uppercase_entropy, and Match#l33t_entropy have been removed. Use Match#guesses and Match#guesses_log10 instead (#69)
  • crack_time_to_score replaced by guesses_to_score with v4 thresholds: 0 (<1,005 guesses), 1 (<1,000,005), 2 (<100,000,005), 3 (<10,000,000,005), 4 (≥10,000,000,005) (#69)
  • Sequence matcher ported to the zxcvbn.js v4 delta-based algorithm. Sequences are now detected using codepoint deltas up to ±5 (was ±1 only), enabling matches like "ace" (delta 2) or Unicode runs like "αβγ". Sequence type is classified by character class (lower/upper/digits/unicode) rather than a lookup table (#69)
  • Date matcher year range extended to 1000–2050; 2-digit years are now expanded (>50 → 1900s, ≤50 → 2000s) (#69)
  • All frequency lists replaced with zxcvbn.js v4.4.2 versions: passwords (30k entries), surnames (10k), female_names (3,712), male_names (983), english_wikipedia (30k entries) (#69)
  • Breaking: entropy on Zxcvbn::Score has been removed. Use Score#guesses or Math.log2(score.guesses) instead (#69)
  • Breaking: Score#crack_time and Score#crack_time_display replaced by Score#crack_times_seconds and Score#crack_times_display, each a hash keyed by attack scenario (online_throttling_100_per_hour, online_no_throttling_10_per_second, offline_slow_hashing_1e4_per_second, offline_fast_hashing_1e10_per_second), matching the zxcvbn.js v4 output format (#69)
  • Breaking: Score#match_sequence renamed to Score#sequence to match the zxcvbn.js v4 field name (#69)
  • Breaking: Feedback#warning now returns '' instead of nil when no warning applies, matching zxcvbn.js v4 (#69)
  • Breaking: The "This is similar to a commonly used password" warning is now only emitted when match.guesses_log10 <= 4, matching the zxcvbn.js v4 threshold. Previously it was emitted unconditionally for any l33t, reversed, or non-sole-match on the passwords dictionary (#69)
  • Repeat feedback now distinguishes single-char repeats ("aaa") from multi-char repeats ("abcabcabc"), matching zxcvbn.js v4 (#69)
  • year pattern matches now produce a "Recent years are easy to guess" warning (#69)
  • Sole matches from the english_wikipedia dictionary now produce an "A word by itself is easy to guess" warning (#69)
  • Breaking: Tester#test and Zxcvbn.test now raise Zxcvbn::PasswordTooLong (a subclass of ArgumentError) for passwords longer than 256 characters (the default). Previously, long passwords were accepted and could cause super-quadratic runtime on adversarial repeat inputs to the password argument. The user_inputs parameter remains unbounded. Override the limit with the ZXCVBN_MAX_PASSWORD_LENGTH environment variable or Zxcvbn.tester_builder.max_password_length(n).build.

Removed

  • Breaking: Tester#add_word_lists. Use Zxcvbn.tester_builder.add_word_list(name, words).build instead.
  • Breaking: word_lists: argument to Zxcvbn.test. Use Zxcvbn.tester_builder.add_word_list(name, words).build to construct a tester with custom word lists.
  • Support for Ruby versions below 3.3 (#70)

1.4.0 - 2026-01-15

Added

  • RBS type signatures for improved type checking and IDE support (#68)

Changed

  • Minor fixups in gem metadata (#67).

1.3.0 - 2026-01-02

Changed

  • Replace OpenStruct with regular class in Zxcvbn::Match for 2x performance improvement (#61)
  • Implement Trie data structure for dictionary matching with 1.4x additional performance improvement (#62)
  • Replace range operators with String#slice for string slicing operations (#63)
  • Optimise L33t matcher with early bailout and improved deduplication (#64)
  • Pre-compute spatial graph statistics during data initialisation (#65)
  • Optimise nCk calculation using symmetry property (#66)

Overall performance improvement: 4.1x faster than v1.2.4 (0.722ms → 0.176ms per password)

1.2.4 - 2025-12-07

Changed

  • Address security issues found by RuboCop (#57)

1.2.3 - 2025-12-07

Changed

  • Address linting issues found by RuboCop (#52)
  • Address style issues found by RuboCop (#53, #54, #55)

1.2.2 - 2025-12-06

Changed

  • Address layout and frozen string literal issues (#49)

1.2.1 - 2025-12-05

Removed

  • Removed the dependency on the Ruby benchmark module (#44).
  • Tests are no longer included in the gem package (#45).

1.2.0 - 2021-01-05

Added

  • Support for Ruby 3 (thanks @RSO (#32))

Changed

1.1.0 - 2020-07-16

Added

  • Support for Ruby 2.7 (#29)
  • Gem metadata (#29)

Removed

  • Support for Ruby 2.3 (#29)
  • Support for Ruby 2.4 (#29)

Fixed

  • Invalid user dictionaries are handled more robustly (#28)

1.0.0 - 2019-05-14

Added

  • License info in the gemspec (#21)
  • More ported password checking features to bring this gem more up to date. (#22)
    • spatial - Keyboard patterns
    • repeat - Repeated characters
    • sequence - easily guessable sequences
    • date - date associations

Removed

  • This gem will no longer run on Ruby versions < 2.3 (#25)