private static bool EvalAddPopularPasswordPattern(List <QePatternInstance>[] vPatterns, char[] vPassword, int i, char[] vSub, double dblCostPerMod) { ulong uDictSize; if (!PopularPasswords.IsPopularPassword(vSub, out uDictSize)) { return(false); } int n = vSub.Length; int d = HammingDistribution(vSub, 0, vPassword, i, n); double dblCost = Log2((double)uDictSize); // dblCost += log2(n binom d) int k = Math.Min(d, n - d); for (int j = n; j > (n - k); --j) { dblCost += Log2(j); } for (int j = k; j >= 2; --j) { dblCost -= Log2(j); } dblCost += dblCostPerMod * (double)d; vPatterns[i].Add(new QePatternInstance(i, n, PatternId.Dictionary, dblCost)); return(true); }
private static void FindPopularPasswords(char[] password, List <QePatternInstance>[] patterns) { var passwordLength = password.Length; var lower = new char[passwordLength]; var leet = new char[passwordLength]; for (var index = 0; index < passwordLength; ++index) { var character = password[index]; lower[index] = char.ToLower(character); leet[index] = char.ToLower(DecodeLeetChar(character)); } var erased = default(char); Debug.Assert(erased == char.MinValue); var maximumLength = Math.Min(passwordLength, PopularPasswords.MaxLength); for (var subLength = maximumLength; subLength >= 3; --subLength) { if (!PopularPasswords.ContainsLength(subLength)) { continue; } var substring = new char[subLength]; for (var index = 0; index <= (passwordLength - subLength); ++index) { if (Array.IndexOf(lower, erased, index, subLength) >= 0) { continue; } Array.Copy(lower, index, substring, 0, subLength); if (!EvalAddPopularPasswordPattern(patterns, password, index, substring, 0.0)) { Array.Copy(leet, index, substring, 0, subLength); if (EvalAddPopularPasswordPattern(patterns, password, index, substring, 1.5)) { Array.Clear(lower, index, subLength); Debug.Assert(lower[index] == erased); } } else { Array.Clear(lower, index, subLength); Debug.Assert(lower[index] == erased); } } } }