Class: Zxcvbn::Matchers::L33t Private
- Inherits:
-
Object
- Object
- Zxcvbn::Matchers::L33t
- Includes:
- CaseHelpers
- Defined in:
- lib/zxcvbn/matchers/l33t.rb,
sig/zxcvbn/matchers/l33t.rbs
Overview
This class is part of a private API. You should avoid using this class if possible, as it may be removed or be changed in the future.
Matches dictionary words after substituting common l33t-speak character replacements (e.g. "@" for "a", "3" for "e").
Constant Summary collapse
- L33T_TABLE =
This constant is part of a private API. You should avoid using this constant if possible, as it may be removed or be changed in the future.
Mapping from plain letter to the l33t characters that can represent it.
{ 'a' => ['4', '@'].freeze, 'b' => ['8'].freeze, 'c' => ['(', '{', '[', '<'].freeze, 'e' => ['3'].freeze, 'g' => ['6', '9'].freeze, 'i' => ['1', '!', '|'].freeze, 'l' => ['1', '|', '7'].freeze, 'o' => ['0'].freeze, 's' => ['$', '5'].freeze, 't' => ['+', '7'].freeze, 'x' => ['%'].freeze, 'z' => ['2'].freeze }.freeze
Instance Method Summary collapse
- #dedup(subs) ⇒ Array[untyped] private
- #find_substitutions(subs, table, keys) ⇒ Array[untyped] private
-
#initialize(dictionary_matchers) ⇒ L33t
constructor
private
A new instance of L33t.
-
#l33t_subs(table) ⇒ Array<Hash{String => String}>
private
Enumerates all possible substitution combinations for the given l33t subtable.
-
#matches(password) ⇒ Array<MatchBuilder>
private
Returns l33t-substituted dictionary matches found in password.
- #process_match(match, password, substitution, matches) ⇒ void private
-
#relevent_l33t_subtable(password) ⇒ Hash{String => Array<String>}
private
Returns the subset of L33T_TABLE whose l33t characters appear in password.
-
#translate(password, sub) ⇒ String
private
Returns a copy of password with each character replaced according to sub.
Methods included from CaseHelpers
downcase_preserving_length, #self?.downcase_preserving_length
Constructor Details
#initialize(dictionary_matchers) ⇒ L33t
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a new instance of L33t.
29 30 31 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 29 def initialize(dictionary_matchers) @dictionary_matchers = dictionary_matchers end |
Instance Method Details
#dedup(subs) ⇒ Array[untyped]
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
129 130 131 132 133 134 135 136 137 138 139 140 141 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 129 def dedup(subs) deduped = [] seen = Set.new subs.each do |sub| # Sort and convert to hash for consistent comparison sorted_sub = sub.sort.to_h unless seen.include?(sorted_sub) seen.add(sorted_sub) deduped << sub end end deduped end |
#find_substitutions(subs, table, keys) ⇒ Array[untyped]
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 105 def find_substitutions(subs, table, keys) return subs if keys.empty? first_key = keys[0] rest_keys = keys[1..] next_subs = [] table[first_key].each do |l33t_char| subs.each do |sub| dup_l33t_index = sub.find_index { |pair| pair[0] == l33t_char } if dup_l33t_index.nil? next_subs << (sub + [[l33t_char, first_key]]) else sub_alternative = sub.dup sub_alternative[dup_l33t_index, 1] = [[l33t_char, first_key]] next_subs << sub next_subs << sub_alternative end end end subs = dedup(next_subs) find_substitutions(subs, table, rest_keys) end |
#l33t_subs(table) ⇒ Array<Hash{String => String}>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Enumerates all possible substitution combinations for the given l33t subtable.
83 84 85 86 87 88 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 83 def l33t_subs(table) keys = table.keys subs = [[]] subs = find_substitutions(subs, table, keys) subs.map(&:to_h) end |
#matches(password) ⇒ Array<MatchBuilder>
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns l33t-substituted dictionary matches found in password.
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 37 def matches(password) matches = [] lowercased_password = downcase_preserving_length(password) relevent_subtable = relevent_l33t_subtable(lowercased_password) # Early bailout: if no l33t characters present, return empty matches return matches if relevent_subtable.empty? combinations_to_try = l33t_subs(relevent_subtable) combinations_to_try.each do |substitution| @dictionary_matchers.each do |matcher| subbed_password = translate(lowercased_password, substitution) matcher.matches(subbed_password).each do |match| process_match(match, password, substitution, matches) end end end matches end |
#process_match(match, password, substitution, matches) ⇒ void
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
This method returns an undefined value.
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 92 def process_match(match, password, substitution, matches) length = match.j - match.i + 1 token = password.slice(match.i, length) return if token.downcase == match.matched_word.downcase match_substitutions = substitution.select { |s, _| token.include?(s) } match.l33t = true match.token = token match.sub = match_substitutions match.sub_display = match_substitutions.map { |k, v| "#{k} -> #{v}" }.join(', ') matches << match end |
#relevent_l33t_subtable(password) ⇒ Hash{String => Array<String>}
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns the subset of L33T_TABLE whose l33t characters appear in password.
70 71 72 73 74 75 76 77 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 70 def relevent_l33t_subtable(password) filtered = {} L33T_TABLE.each do |letter, subs| relevent_subs = subs.select { |s| password.include?(s) } filtered[letter] = relevent_subs unless relevent_subs.empty? end filtered end |
#translate(password, sub) ⇒ String
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
Returns a copy of password with each character replaced according to sub.
62 63 64 |
# File 'lib/zxcvbn/matchers/l33t.rb', line 62 def translate(password, sub) password.gsub(Regexp.union(sub.keys), sub) end |