Exemple #1
0
        private void CalculateEntropyForMatch(DictionaryMatch match)
        {
            match.BaseEntropy      = Math.Log(match.Rank, 2);
            match.UppercaseEntropy = PasswordScoring.CalculateUppercaseEntropy(match.Token);

            match.Entropy = match.BaseEntropy + match.UppercaseEntropy;
        }
        // ReSharper disable once InconsistentNaming
        private static void CalulateL33tEntropy(L33tDictionaryMatch match)
        {
            // I'm a bit dubious about this function, but I have duplicated zxcvbn functionality regardless

            var possibilities = 0;

            foreach (var kvp in match.Subs)
            {
                var subbedChars   = match.Token.Count(c => c == kvp.Key);
                var unsubbedChars = match.Token.Count(c => c == kvp.Value); // Won't this always be zero?

                possibilities += Enumerable.Range(0, Math.Min(subbedChars, unsubbedChars) + 1).Sum(i => (int)PasswordScoring.Binomial(subbedChars + unsubbedChars, i));
            }

            var entropy = Math.Log(possibilities, 2);

            // In the case of only a single subsitution (e.g. 4pple) this would otherwise come out as zero, so give it one bit
            match.L33tEntropy = (entropy < 1 ? 1 : entropy);
            match.Entropy    += match.L33tEntropy;

            // We have to recalculate the uppercase entropy -- the password matcher will have used the subbed password not the original text
            match.Entropy         -= match.UppercaseEntropy;
            match.UppercaseEntropy = PasswordScoring.CalculateUppercaseEntropy(match.Token);
            match.Entropy         += match.UppercaseEntropy;
        }
        /// <summary>
        /// Match substrings of password agains the loaded dictionary
        /// </summary>
        /// <param name="password">The password to match</param>
        /// <param name="cancellationToken">The token for the operation</param>
        /// <returns>An enumerable of dictionary matches</returns>
        /// <seealso cref="DictionaryMatch"/>
        public IEnumerable <Match> MatchPassword(string password, CancellationToken cancellationToken)
        {
            // Build the dictionary to use if necessary
            DictionarySemaphore.Wait(cancellationToken);

            // Build the dictionary
            if (_RankedDictionary == null)
            {
                _RankedDictionary = BuildRankedDictionary(DictionaryPath);
            }
            DictionarySemaphore.Release();

            // Check the token state
            cancellationToken.ThrowIfCancellationRequested();
            string passwordLower = password.ToLower();

            // Compute and return the result list
            return
                ((from i in Enumerable.Range(0, password.Length)
                  from j in Enumerable.Range(i, password.Length - i)
                  let psub = passwordLower.Substring(i, j - i + 1)
                             where _RankedDictionary.ContainsKey(psub)
                             let rank = _RankedDictionary[psub]
                                        let token = password.Substring(i, j - i + 1) // Could have different case so pull from password
                                                    let baseEntropy = Math.Log(rank, 2)
                                                                      let upperEntropy = PasswordScoring.CalculateUppercaseEntropy(token)
                                                                                         select new DictionaryMatch
            {
                Pattern = DictionaryPattern,
                i = i,
                j = j,
                Token = token,
                MatchedWord = psub,
                Rank = rank,
                DictionaryName = DictionaryName,
                Cardinality = _RankedDictionary.Count,
                BaseEntropy = baseEntropy,
                UppercaseEntropy = upperEntropy,
                Entropy = baseEntropy + upperEntropy
            }).ToList());
        }