コード例 #1
0
        /// <summary>
        /// Returns a new result structure initialised with data for the lowest entropy result of all of the matches passed in, adding brute-force
        /// matches where there are no lesser entropy found pattern matches.
        /// </summary>
        /// <param name="matches">Password being evaluated</param>
        /// <param name="password">List of matches found against the password</param>
        /// <returns>A result object for the lowest entropy match sequence</returns>
        private PasswordMetricResult FindMinimumEntropyMatch(string password, IEnumerable <Match> matches)
        {
            var bruteforce_cardinality = PasswordScoring.PasswordCardinality(password);

            // Minimum entropy up to position k in the password
            var minimumEntropyToIndex = new double[password.Length];
            var bestMatchForIndex     = new Match[password.Length];

            for (var k = 0; k < password.Length; k++)
            {
                // Start with bruteforce scenario added to previous sequence to beat
                minimumEntropyToIndex[k] = (k == 0 ? 0 : minimumEntropyToIndex[k - 1]) + Math.Log(bruteforce_cardinality, 2);

                // All matches that end at the current character, test to see if the entropy is less
                foreach (var match in matches.Where(m => m.End == k))
                {
                    var candidate_entropy = (match.Begin <= 0 ? 0 : minimumEntropyToIndex[match.Begin - 1]) + match.Entropy;
                    if (candidate_entropy < minimumEntropyToIndex[k])
                    {
                        minimumEntropyToIndex[k] = candidate_entropy;
                        bestMatchForIndex[k]     = match;
                    }
                }
            }


            // Walk backwards through lowest entropy matches, to build the best password sequence
            var matchSequence = new List <Match>();

            for (var k = password.Length - 1; k >= 0; k--)
            {
                if (bestMatchForIndex[k] != null)
                {
                    matchSequence.Add(bestMatchForIndex[k]);
                    k = bestMatchForIndex[k].Begin; // Jump back to start of match
                }
            }
            matchSequence.Reverse();


            // The match sequence might have gaps, fill in with bruteforce matching
            // After this the matches in matchSequence must cover the whole string (i.e. match[k].j == match[k + 1].i - 1)
            if (matchSequence.Count == 0)
            {
                // To make things easy, we'll separate out the case where there are no matches so everything is bruteforced
                matchSequence.Add(new Match()
                {
                    Begin       = 0,
                    End         = password.Length,
                    Token       = password,
                    Cardinality = bruteforce_cardinality,
                    Pattern     = BruteforcePattern,
                    Entropy     = Math.Log(Math.Pow(bruteforce_cardinality, password.Length), 2)
                });
            }
            else
            {
                // There are matches, so find the gaps and fill them in
                var matchSequenceCopy = new List <Match>();
                for (var k = 0; k < matchSequence.Count; k++)
                {
                    var m1 = matchSequence[k];
                    var m2 = (k < matchSequence.Count - 1 ? matchSequence[k + 1] : new Match()
                    {
                        Begin = password.Length
                    });                                                                                                      // Next match, or a match past the end of the password

                    matchSequenceCopy.Add(m1);
                    if (m1.End < m2.Begin - 1)
                    {
                        // Fill in gap
                        var ns = m1.End + 1;
                        var ne = m2.Begin - 1;
                        matchSequenceCopy.Add(new Match()
                        {
                            Begin       = ns,
                            End         = ne,
                            Token       = password.Substring(ns, ne - ns + 1),
                            Cardinality = bruteforce_cardinality,
                            Pattern     = BruteforcePattern,
                            Entropy     = Math.Log(Math.Pow(bruteforce_cardinality, ne - ns + 1), 2)
                        });
                    }
                }

                matchSequence = matchSequenceCopy;
            }


            var minEntropy = (password.Length == 0 ? 0 : minimumEntropyToIndex[password.Length - 1]);
            var crackTime  = PasswordScoring.EntropyToCrackTime(minEntropy);

            var result = new PasswordMetricResult();

            result.Password         = password;
            result.Entropy          = Math.Round(minEntropy, 3);
            result.MatchSequence    = matchSequence;
            result.CrackTime        = Math.Round(crackTime, 3);
            result.CrackTimeDisplay = Utility.DisplayTime(crackTime, this.translation);
            result.Score            = PasswordScoring.CrackTimeToScore(crackTime);


            //starting feedback
            if ((matchSequence == null) || (matchSequence.Count() == 0))
            {
                result.warning = Warning.Default;
                result.suggestions.Clear();
                result.suggestions.Add(Suggestion.Default);
            }
            else
            {
                //no Feedback if score is good or great
                if (result.Score > 2)
                {
                    result.warning = Warning.Empty;
                    result.suggestions.Clear();
                    result.suggestions.Add(Suggestion.Empty);
                }
                else
                {
                    //tie feedback to the longest match for longer sequences
                    Match longestMatch = GetLongestMatch(matchSequence);
                    GetMatchFeedback(longestMatch, matchSequence.Count() == 1, result);
                    result.suggestions.Insert(0, Suggestion.AddAnotherWordOrTwo);
                }
            }
            return(result);
        }
コード例 #2
0
ファイル: Zxcvbn.cs プロジェクト: UsmanSabir/zxcvbn-cs
        /// <summary>
        /// Returns a new result structure initialised with data for the lowest entropy result of all of the matches passed in, adding brute-force
        /// matches where there are no lesser entropy found pattern matches.
        /// </summary>
        /// <param name="matches">Password being evaluated</param>
        /// <param name="password">List of matches found against the password</param>
        /// <returns>A result object for the lowest entropy match sequence</returns>
        private Result FindMinimumEntropyMatch(string password, IEnumerable <Match> matches)
        {
            var bruteforce_cardinality = PasswordScoring.PasswordCardinality(password);

            // Minimum entropy up to position k in the password
            var minimumEntropyToIndex = new double[password.Length];
            var bestMatchForIndex     = new Match[password.Length];

            for (var k = 0; k < password.Length; k++)
            {
                // Start with bruteforce scenario added to previous sequence to beat
                minimumEntropyToIndex[k] = (k == 0 ? 0 : minimumEntropyToIndex[k - 1]) + Math.Log(bruteforce_cardinality, 2);

                // All matches that end at the current character, test to see if the entropy is less
                foreach (var match in matches.Where(m => m.j == k))
                {
                    var candidate_entropy = (match.i <= 0 ? 0 : minimumEntropyToIndex[match.i - 1]) + match.Entropy;
                    if (candidate_entropy < minimumEntropyToIndex[k])
                    {
                        minimumEntropyToIndex[k] = candidate_entropy;
                        bestMatchForIndex[k]     = match;
                    }
                }
            }

            // Walk backwards through lowest entropy matches, to build the best password sequence
            var matchSequence = new List <Match>();

            for (var k = password.Length - 1; k >= 0; k--)
            {
                if (bestMatchForIndex[k] != null)
                {
                    matchSequence.Add(bestMatchForIndex[k]);
                    k = bestMatchForIndex[k].i; // Jump back to start of match
                }
            }
            matchSequence.Reverse();

            // The match sequence might have gaps, fill in with bruteforce matching
            // After this the matches in matchSequence must cover the whole string (i.e. match[k].j == match[k + 1].i - 1)
            if (matchSequence.Count == 0)
            {
                // To make things easy, we'll separate out the case where there are no matches so everything is bruteforced
                matchSequence.Add(new Match()
                {
                    i           = 0,
                    j           = password.Length,
                    Token       = password,
                    Cardinality = bruteforce_cardinality,
                    Pattern     = BruteforcePattern,
                    Entropy     = Math.Log(Math.Pow(bruteforce_cardinality, password.Length), 2)
                });
            }
            else
            {
                // There are matches, so find the gaps and fill them in
                var matchSequenceCopy = new List <Match>();
                for (var k = 0; k < matchSequence.Count; k++)
                {
                    var m1 = matchSequence[k];
                    var m2 = (k < matchSequence.Count - 1 ? matchSequence[k + 1] : new Match()
                    {
                        i = password.Length
                    });                                                                                                  // Next match, or a match past the end of the password

                    matchSequenceCopy.Add(m1);
                    if (m1.j < m2.i - 1)
                    {
                        // Fill in gap
                        var ns = m1.j + 1;
                        var ne = m2.i - 1;
                        matchSequenceCopy.Add(new Match()
                        {
                            i           = ns,
                            j           = ne,
                            Token       = password.Substring(ns, ne - ns + 1),
                            Cardinality = bruteforce_cardinality,
                            Pattern     = BruteforcePattern,
                            Entropy     = Math.Log(Math.Pow(bruteforce_cardinality, ne - ns + 1), 2)
                        });
                    }
                }

                matchSequence = matchSequenceCopy;
            }

            var minEntropy = (password.Length == 0 ? 0 : minimumEntropyToIndex[password.Length - 1]);
            var crackTime  = PasswordScoring.EntropyToCrackTime(minEntropy);

            var result = new Result()
            {
                Password         = password,
                Entropy          = Math.Round(minEntropy, 3),
                MatchSequence    = matchSequence,
                CrackTime        = Math.Round(crackTime, 3),
                CrackTimeDisplay = Utility.DisplayTime(crackTime, translation),
                Score            = PasswordScoring.CrackTimeToScore(crackTime)
            };

            return(result);
        }