Module: Philiprehberger::Password::Zxcvbn
- Defined in:
- lib/philiprehberger/password/zxcvbn.rb
Constant Summary collapse
- LEET_MAP =
L33t substitution mappings
{ '@' => 'a', '4' => 'a', '^' => 'a', '8' => 'b', '(' => 'c', '{' => 'c', '<' => 'c', '3' => 'e', '6' => 'g', '9' => 'g', '#' => 'h', '1' => 'i', '!' => 'i', '|' => 'i', '7' => 'l', '0' => 'o', '$' => 's', '5' => 's', '+' => 't', '2' => 'z' }.freeze
- DATE_PATTERNS =
Common date patterns
[ /\b(19|20)\d{2}\b/, # yyyy %r{\b(0?[1-9]|1[0-2])[/-](0?[1-9]|[12]\d|3[01])[/-](\d{2}|\d{4})\b}, # mm/dd/yy or mm/dd/yyyy %r{\b(0?[1-9]|[12]\d|3[01])[/-](0?[1-9]|1[0-2])[/-](\d{2}|\d{4})\b}, # dd/mm/yy or dd/mm/yyyy /\b(0?[1-9]|1[0-2])(0?[1-9]|[12]\d|3[01])(\d{2}|\d{4})\b/, # mmddyy or mmddyyyy /\b(\d{2}|\d{4})(0?[1-9]|1[0-2])(0?[1-9]|[12]\d|3[01])\b/ # yymmdd or yyyymmdd ].freeze
- SPATIAL_PATTERNS_QWERTY =
%w[ qwert werty ertyu rtyui tyuio yuiop asdfg sdfgh dfghj fghjk ghjkl zxcvb xcvbn cvbnm qwer wert erty rtyu tyui yuio uiop asdf sdfg dfgh fghj ghjk hjkl zxcv xcvb cvbn vbnm ].freeze
- CRACK_TIMES =
{ 0 => 'instant', 1 => 'minutes', 2 => 'hours to days', 3 => 'months to years', 4 => 'centuries' }.freeze
Class Method Summary collapse
-
.estimate(password) ⇒ Object
Perform zxcvbn-style password strength estimation.
Class Method Details
.estimate(password) ⇒ Object
Perform zxcvbn-style password strength estimation. Returns a hash with :score (0-4), :patterns (array), and :crack_time_display.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 |
# File 'lib/philiprehberger/password/zxcvbn.rb', line 50 def self.estimate(password) pwd = password.to_s return { score: 0, patterns: [], crack_time_display: 'instant' } if pwd.empty? patterns = [] patterns.concat(detect_dictionary_words(pwd)) patterns.concat(detect_leet_substitutions(pwd)) patterns.concat(detect_spatial_patterns(pwd)) patterns.concat(detect_date_patterns(pwd)) patterns.concat(detect_keyboard_patterns(pwd)) # Calculate base entropy base_entropy = Strength.entropy(pwd) # Apply penalty for detected patterns penalty = patterns.sum { |p| pattern_penalty(p) } adjusted_entropy = [base_entropy - penalty, 0.0].max score = entropy_to_score(adjusted_entropy, pwd.length, patterns.length) { score: score, patterns: patterns, crack_time_display: CRACK_TIMES[score] } end |