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 = HammingDist(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[] vPassword, List <QePatternInstance>[] vPatterns) { int n = vPassword.Length; char[] vLower = new char[n]; char[] vLeet = new char[n]; for (int i = 0; i < n; ++i) { char ch = vPassword[i]; vLower[i] = char.ToLower(ch); vLeet[i] = char.ToLower(DecodeLeetChar(ch)); } char chErased = default(char); Debug.Assert(chErased == char.MinValue); int nMaxLen = Math.Min(n, PopularPasswords.MaxLength); for (int nSubLen = nMaxLen; nSubLen >= 3; --nSubLen) { if (!PopularPasswords.ContainsLength(nSubLen)) { continue; } char[] vSub = new char[nSubLen]; for (int i = 0; i <= (n - nSubLen); ++i) { if (Array.IndexOf <char>(vLower, chErased, i, nSubLen) >= 0) { continue; } Array.Copy(vLower, i, vSub, 0, nSubLen); if (!EvalAddPopularPasswordPattern(vPatterns, vPassword, i, vSub, 0.0)) { Array.Copy(vLeet, i, vSub, 0, nSubLen); if (EvalAddPopularPasswordPattern(vPatterns, vPassword, i, vSub, 1.5)) { Array.Clear(vLower, i, nSubLen); // Not vLeet Debug.Assert(vLower[i] == chErased); } } else { Array.Clear(vLower, i, nSubLen); Debug.Assert(vLower[i] == chErased); } } } }
/// <summary> /// Estimate the quality of a password. /// </summary> /// <param name="vPasswordChars">Password to check.</param> /// <returns>Estimated bit-strength of the password.</returns> /// <exception cref="System.ArgumentNullException">Thrown if the input /// parameter is <c>null</c>.</exception> public static uint EstimatePasswordBits(char[] vPasswordChars) { Debug.Assert(vPasswordChars != null); if (vPasswordChars == null) { throw new ArgumentNullException("vPasswordChars"); } bool bChLower = false, bChUpper = false, bChNumber = false; bool bChSpecial = false, bChHigh = false, bChControl = false; Dictionary <char, uint> vCharCounts = new Dictionary <char, uint>(); Dictionary <int, uint> vDifferences = new Dictionary <int, uint>(); double dblEffectiveLength = 0.0; for (int i = 0; i < vPasswordChars.Length; ++i) // Get character types { char tch = vPasswordChars[i]; if (tch < ' ') { bChControl = true; } else if ((tch >= 'A') && (tch <= 'Z')) { bChUpper = true; } else if ((tch >= 'a') && (tch <= 'z')) { bChLower = true; } else if ((tch >= '0') && (tch <= '9')) { bChNumber = true; } else if ((tch >= ' ') && (tch <= '/')) { bChSpecial = true; } else if ((tch >= ':') && (tch <= '@')) { bChSpecial = true; } else if ((tch >= '[') && (tch <= '`')) { bChSpecial = true; } else if ((tch >= '{') && (tch <= '~')) { bChSpecial = true; } else if (tch > '~') { bChHigh = true; } double dblDiffFactor = 1.0; if (i >= 1) { int iDiff = (int)tch - (int)vPasswordChars[i - 1]; uint uDiffCount; if (vDifferences.TryGetValue(iDiff, out uDiffCount)) { ++uDiffCount; vDifferences[iDiff] = uDiffCount; dblDiffFactor /= (double)uDiffCount; } else { vDifferences.Add(iDiff, 1); } } uint uCharCount; if (vCharCounts.TryGetValue(tch, out uCharCount)) { ++uCharCount; vCharCounts[tch] = uCharCount; dblEffectiveLength += dblDiffFactor * (1.0 / (double)uCharCount); } else { vCharCounts.Add(tch, 1); dblEffectiveLength += dblDiffFactor; } } uint uCharSpace = 0; if (bChControl) { uCharSpace += (uint)CharSpaceBits.Control; } if (bChUpper) { uCharSpace += (uint)CharSpaceBits.Alpha; } if (bChLower) { uCharSpace += (uint)CharSpaceBits.Alpha; } if (bChNumber) { uCharSpace += (uint)CharSpaceBits.Number; } if (bChSpecial) { uCharSpace += (uint)CharSpaceBits.Special; } if (bChHigh) { uCharSpace += (uint)CharSpaceBits.High; } if (uCharSpace == 0) { return(0); } double dblBitsPerChar = Math.Log((double)uCharSpace) / Math.Log(2.0); double dblRating = dblBitsPerChar * dblEffectiveLength; #if !KeePassLibSD char[] vLowerCopy = new char[vPasswordChars.Length]; for (int ilc = 0; ilc < vLowerCopy.Length; ++ilc) { vLowerCopy[ilc] = char.ToLower(vPasswordChars[ilc]); } if (PopularPasswords.IsPopularPassword(vLowerCopy)) { dblRating /= 8.0; } Array.Clear(vLowerCopy, 0, vLowerCopy.Length); #endif return((uint)Math.Ceiling(dblRating)); }