예제 #1
0
        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);
        }
예제 #2
0
        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);
                    }
                }
            }
        }
예제 #3
0
        /// <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));
        }