New issue
Advanced search Search tips

Issue 668155 link

Starred by 1 user

Issue metadata

Status: Fixed
Owner:
Closed: Jan 2017
Components:
EstimatedDays: ----
NextAction: ----
OS: All
Pri: 3
Type: Bug



Sign in to add a comment

Optimization of PasswordReuseDetector

Project Member Reported by dvadym@chromium.org, Nov 23 2016

Issue description

https://codereview.chromium.org/2525593002/ is introducing a class PasswordReuseDetector. This class has a method CheckReuse(const base::string16& input, ...) and a data-member map |passwords_| keyed with string16. CheckReuse needs to find out whether some suffix of |input| is a key in |passwords_|.

Currently, the method does so by iterating over possible suffixes of |input| and using find() on the map. This makes O(m*n*log(n)) string comparisons for m being the length of |input| and |n| the size of |passwords_|. In addition to it, it also contains O(m) string copies and allocations which are not necessary. This approach was chosen in the initial code for its simplicity, to make review of the code easier.

However, there are more efficient solutions, for example:

Initialisation:
Instead of making |passwords_| a std::map, make it a std::vector of key-value pairs. Use the reverse of passwords as keys, and std::sort the vector.

Lookup:
Reverse also |input|. Now the task is to see if a prefix (of size at least kMinPasswordLengthToCheck) is a key in |passwords_|. This can be done via std::binary_search, using a custom comparator like this:
bool IsLongInputPrefix(const base::string16& str) {
  return /* whether str is a prefix of input of length at least
            kMinPasswordLengthToCheck */;
}

bool Compare(const base::string16& a, const base::string16& b) {
  if (IsLongInputPrefix(a) && IsLongInputPrefix(b))
    return false;
  return a < b;
}
(That comparator represents the preorder on strings obtained from the lexicographical order by glueing all long prefixes of input into a single equivalence class.)

This solution would need O(n*log(n)) comparisons for the initialisation, and O(log(n)) for the lookup.
 

Comment 1 by vabr@chromium.org, Nov 23 2016

Description: Show this description

Comment 2 by vabr@chromium.org, Nov 23 2016

(I expanded the terse description in case this will sit there for longer and somebody else would need to implement it.)
Project Member

Comment 3 by bugdroid1@chromium.org, Jan 16 2017

The following revision refers to this bug:
  https://chromium.googlesource.com/chromium/src.git/+/ceaa547b121efaac5504b656826247b7b93259de

commit ceaa547b121efaac5504b656826247b7b93259de
Author: dvadym <dvadym@chromium.org>
Date: Mon Jan 16 17:04:04 2017

Password reuse look-up optimization.

In the current implementation of the password reuse detection:
1.Passwords are stored in map<password, set<domains>> passwords_
2.String |input| contains keystrokes from earliest till latest, and it needed to check any suffix of |input| for occurrence in |passwords_|.That requre m*n*log(n) operations, where m = len(input), n = len(passwords_).

This optimization:
1.Paswords stored are in the same structure but, keys are ordered(i.e. passwords) are ordered lexicographical as reversed strings.
2.So now it's needed to find a key in |passwords_| which is a suffix of |input|. If a key in |passwords_| that is suffix of |input| exists then the longest such key is the largest key in reverse lexicographical order that not bigger that |input|. Usual map<> find method is used for finding such key.

BUG=657041,  668155 

Review-Url: https://codereview.chromium.org/2629343002
Cr-Commit-Position: refs/heads/master@{#443911}

[modify] https://crrev.com/ceaa547b121efaac5504b656826247b7b93259de/components/password_manager/core/browser/password_reuse_detector.cc
[modify] https://crrev.com/ceaa547b121efaac5504b656826247b7b93259de/components/password_manager/core/browser/password_reuse_detector.h
[modify] https://crrev.com/ceaa547b121efaac5504b656826247b7b93259de/components/password_manager/core/browser/password_reuse_detector_unittest.cc

Comment 4 by dvadym@chromium.org, Jan 17 2017

Status: Fixed (was: Assigned)

Sign in to add a comment