lib/zxcvbn/matching.rb in zxcvbn-0.1.8 vs lib/zxcvbn/matching.rb in zxcvbn-0.1.9

- old
+ new

@@ -13,10 +13,14 @@ RANKED_DICTIONARIES = FREQUENCY_LISTS.transform_values do |lst| build_ranked_dict(lst) end + RANKED_DICTIONARIES_MAX_WORD_SIZE = RANKED_DICTIONARIES.transform_values do |word_scores| + word_scores.keys.max_by(&:size).size + end + GRAPHS = { "qwerty" => ADJACENCY_GRAPHS["qwerty"], "dvorak" => ADJACENCY_GRAPHS["dvorak"], "keypad" => ADJACENCY_GRAPHS["keypad"], "mac_keypad" => ADJACENCY_GRAPHS["mac_keypad"] @@ -149,12 +153,17 @@ # _ranked_dictionaries variable is for unit testing purposes matches = [] len = password.length password_lower = password.downcase _ranked_dictionaries.each do |dictionary_name, ranked_dict| + longest_dict_word_size = RANKED_DICTIONARIES_MAX_WORD_SIZE.fetch(dictionary_name) do + ranked_dict.keys.max_by(&:size)&.size || 0 + end + search_width = [longest_dict_word_size, len].min (0...len).each do |i| - (i...len).each do |j| + search_end = [i + search_width, len].min + (i...search_end).each do |j| if ranked_dict.key?(password_lower[i..j]) word = password_lower[i..j] rank = ranked_dict[word] matches << { "pattern" => "dictionary", @@ -185,10 +194,12 @@ end sorted(matches) end def self.user_input_dictionary=(ordered_list) - RANKED_DICTIONARIES["user_inputs"] = build_ranked_dict(ordered_list.dup) + ranked_dict = build_ranked_dict(ordered_list.dup) + RANKED_DICTIONARIES["user_inputs"] = ranked_dict + RANKED_DICTIONARIES_MAX_WORD_SIZE["user_inputs"] = ranked_dict.keys.max_by(&:size)&.size || 0 end #------------------------------------------------------------------------------- # dictionary match with common l33t substitutions ------------------------------ #-------------------------------------------------------------------------------