Пример #1
0
        private static double L33tVariations(DictionaryMatch dictionaryMatch)
        {
            if (dictionaryMatch.GetType() != typeof(L33tDictionaryMatch))
            {
                return(1);
            }

            double variations = 1;

            L33tDictionaryMatch ldm = (L33tDictionaryMatch)dictionaryMatch;

            foreach (KeyValuePair <char, char> val in ldm.Subs)
            {
                char   subbed   = val.Key;
                char   unsubbed = val.Value;
                char[] chrs     = ldm.Token.ToLower().ToCharArray();
                int    S        = chrs.Where(c => c == subbed).Count();
                int    U        = chrs.Where(c => c == unsubbed).Count();
                if (S == 0 || U == 0)
                {
                    variations *= 2;
                }
                else
                {
                    int    p             = (int)Math.Min(U, S);
                    double possibilities = 0;
                    foreach (int i in EnumerableUtility.Range(1, p + 1))
                    {
                        possibilities += nCk(U + S, i);
                    }
                    variations *= possibilities;
                }
            }
            return(variations);
        }
Пример #2
0
        private static double UppercaseVariations(DictionaryMatch dictionaryMatch)
        {
            string word      = dictionaryMatch.Token;
            Regex  all_lower = new Regex(@"^[^a-z]+$");

            if (all_lower.IsMatch(word) || word.ToLower().Equals(word))
            {
                return(1);
            }

            Regex startUpper = new Regex(@"^[A-Z][^A-Z]+$");
            Regex endUpper   = new Regex(@"^[^A-Z]+[A-Z]$");
            Regex allUpper   = new Regex(@"^[^A-Z]+$");

            foreach (Regex r in new Regex[] { startUpper, endUpper, allUpper })
            {
                if (r.IsMatch(word))
                {
                    return(2);
                }
            }

            int U = word.ToCharArray().Where(c => char.IsUpper(c)).Count();
            int L = word.ToCharArray().Where(c => char.IsLower(c)).Count();

            double variations = 0;
            int    end        = (int)Math.Min(U, L);

            foreach (int i in EnumerableUtility.Range(1, end + 1))
            {
                variations += nCk(U + L, i);
            }

            return(variations);
        }
        /// <summary>
        /// Calculates the number of l33t variations in the word.
        /// </summary>
        /// <param name="match">The match.</param>
        /// <returns>The number of possible variations.</returns>
        internal static double L33tVariations(DictionaryMatch match)
        {
            if (!match.L33t)
            {
                return(1);
            }

            var variations = 1.0;

            foreach (var subbed in match.Sub.Keys)
            {
                var unsubbed = match.Sub[subbed];
                var s        = match.Token.ToLower().Count(c => c == subbed);
                var u        = match.Token.ToLower().Count(c => c == unsubbed);

                if (s == 0 || u == 0)
                {
                    variations *= 2;
                }
                else
                {
                    var p             = Math.Min(u, s);
                    var possibilities = 0.0;
                    for (var i = 1; i <= p; i++)
                    {
                        possibilities += PasswordScoring.Binomial(u + s, i);
                    }
                    variations *= possibilities;
                }
            }

            return(variations);
        }
        /// <summary>
        /// Estimates the attempts required to guess the password.
        /// </summary>
        /// <param name="match">The match.</param>
        /// <returns>The guesses estimate.</returns>
        public static double CalculateGuesses(DictionaryMatch match)
        {
            match.BaseGuesses         = match.Rank;
            match.UppercaseVariations = UppercaseVariations(match.Token);
            match.L33tVariations      = L33tVariations(match);
            var reversedVariations = match.Reversed ? 2 : 1;

            return(match.BaseGuesses * match.UppercaseVariations * match.L33tVariations * reversedVariations);
        }
Пример #5
0
        private static double DictionaryGuesses(Match match)
        {
            DictionaryMatch dm = (DictionaryMatch)match;

            double uppercase_variations = UppercaseVariations(dm);
            double l33t_variatioins     = L33tVariations(dm);
            int    reversedVariations   = (dm.Reversed) ? 2 : 1;

            return(dm.Rank * uppercase_variations * l33t_variatioins * reversedVariations);
        }
        public void MakesBaseGuessesEqualTheRank()
        {
            var match = new DictionaryMatch
            {
                Token          = "aaaaa",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
            };

            var expected = 32;
            var actual   = DictionaryGuessesCalculator.CalculateGuesses(match);

            actual.Should().Be(expected);
        }
        public void IsDelegatedToByEstimateGuesses()
        {
            var match = new DictionaryMatch
            {
                Token          = "aaaaa",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
            };

            var expected = 32;
            var actual   = PasswordScoring.EstimateGuesses(match, "aaaaa");

            actual.Should().Be(expected);
        }
        public void AddsExtraGuessesForCapitilization()
        {
            var match = new DictionaryMatch
            {
                Token          = "AAAaaa",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
            };

            var expected = 32 * DictionaryGuessesCalculator.UppercaseVariations(match.Token);
            var actual   = DictionaryGuessesCalculator.CalculateGuesses(match);

            actual.Should().Be(expected);
        }
        public void AddsDoubleGuessesForReversedWords()
        {
            var match = new DictionaryMatch
            {
                Token          = "aaaaa",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = true,
            };

            var expected = 32 * 2;
            var actual   = DictionaryGuessesCalculator.CalculateGuesses(match);

            actual.Should().Be(expected);
        }
        public void AddsExtraGuessesForCommonL33tSubstitutions()
        {
            var match = new DictionaryMatch
            {
                Token          = "aaa@@@",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char> {
                    { '@', 'a' }
                },
            };

            var expected = 32 * DictionaryGuessesCalculator.L33tVariations(match);
            var actual   = DictionaryGuessesCalculator.CalculateGuesses(match);

            actual.Should().Be(expected);
        }
        public void IgnoresCapitilizationForL33tVariations()
        {
            var expected = 21;
            var match    = new DictionaryMatch
            {
                Token          = "Aa44aA",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            var actual = DictionaryGuessesCalculator.L33tVariations(match);

            actual.Should().Be(expected);
        }
        public void GetsCorrectL33tVariantsForWord()
        {
            var expected = 1;
            var match    = new DictionaryMatch
            {
                Token          = string.Empty,
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>(),
            };
            var actual = DictionaryGuessesCalculator.L33tVariations(match);

            actual.Should().Be(expected);

            expected = 1;
            match    = new DictionaryMatch
            {
                Token          = "a",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>(),
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 1;
            match    = new DictionaryMatch
            {
                Token          = "abcet",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = false,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>(),
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 2;
            match    = new DictionaryMatch
            {
                Token          = "4",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 2;
            match    = new DictionaryMatch
            {
                Token          = "4pple",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 2;
            match    = new DictionaryMatch
            {
                Token          = "4bcet",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 2;
            match    = new DictionaryMatch
            {
                Token          = "a8cet",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '8', 'b' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 2;
            match    = new DictionaryMatch
            {
                Token          = "abce+",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '+', 't' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 4;
            match    = new DictionaryMatch
            {
                Token          = "48cet",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }, { '8', 'b' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 21;
            match    = new DictionaryMatch
            {
                Token          = "a4a4aa",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 21;
            match    = new DictionaryMatch
            {
                Token          = "4a4a44",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);

            expected = 30;
            match    = new DictionaryMatch
            {
                Token          = "a44att+",
                Rank           = 32,
                DictionaryName = "dic",
                i           = 1,
                j           = 2,
                L33t        = true,
                MatchedWord = "a",
                Reversed    = false,
                L33tSubs    = new Dictionary <char, char>()
                {
                    { '4', 'a' }, { '+', 't' }
                },
            };
            actual = DictionaryGuessesCalculator.L33tVariations(match);
            actual.Should().Be(expected);
        }
Пример #13
0
        private void GetDictionaryMatchFeedback(DictionaryMatch match, bool isSoleMatch, PasswordMetricResult result)
        {
            if (match.DictionaryName.Equals("passwords"))
            {
                //todo: add support for reversed words
                if (isSoleMatch == true && !(match is L33tDictionaryMatch))
                {
                    if (match.Rank <= 10)
                    {
                        result.warning = Warning.Top10Passwords;
                    }
                    else if (match.Rank <= 100)
                    {
                        result.warning = Warning.Top100Passwords;
                    }
                    else
                    {
                        result.warning = Warning.CommonPasswords;
                    }
                }
                else if (PasswordScoring.CrackTimeToScore(PasswordScoring.EntropyToCrackTime(match.Entropy)) <= 1)
                {
                    result.warning = Warning.SimilarCommonPasswords;
                }
            }
            else if (match.DictionaryName.Equals("english"))
            {
                if (isSoleMatch == true)
                {
                    result.warning = Warning.WordEasy;
                }
            }
            else if (match.DictionaryName.Equals("surnames") ||
                     match.DictionaryName.Equals("male_names") ||
                     match.DictionaryName.Equals("female_names"))
            {
                if (isSoleMatch == true)
                {
                    result.warning = Warning.NameSurnamesEasy;
                }
                else
                {
                    result.warning = Warning.CommonNameSurnamesEasy;
                }
            }
            else
            {
                result.warning = Warning.Empty;
            }

            string word = match.Token;

            if (Regex.IsMatch(word, PasswordScoring.StartUpper))
            {
                result.suggestions.Add(Suggestion.CapsDontHelp);
            }
            else if (Regex.IsMatch(word, PasswordScoring.AllUpper) && !word.Equals(word.ToLowerInvariant()))
            {
                result.suggestions.Add(Suggestion.AllCapsEasy);
            }

            //todo: add support for reversed words
            //if match.reversed and match.token.length >= 4
            //    suggestions.push "Reversed words aren't much harder to guess"

            if (match is L33tDictionaryMatch)
            {
                result.suggestions.Add(Suggestion.PredictableSubstitutionsEasy);
            }
        }
Пример #14
0
        private static FeedbackItem GetDictionaryMatchFeedback(DictionaryMatch match, bool isSoleMatch)
        {
            var warning = string.Empty;

            if (match.DictionaryName == "passwords")
            {
                if (isSoleMatch && !match.L33t && !match.Reversed)
                {
                    if (match.Rank <= 10)
                    {
                        warning = "This is a top-10 common password";
                    }
                    else if (match.Rank <= 100)
                    {
                        warning = "This is a top-100 common password";
                    }
                    else
                    {
                        warning = "This is a very common password";
                    }
                }
                else if (match.GuessesLog10 <= 4)
                {
                    warning = "This is similar to a commonly used password";
                }
            }
            else if (match.DictionaryName == "english" && isSoleMatch)
            {
                warning = "A word by itself is easy to guess";
            }
            else if (match.DictionaryName == "surnames" || match.DictionaryName == "male_names" || match.DictionaryName == "female_names")
            {
                if (isSoleMatch)
                {
                    warning = "Names and surnames by themselves are easy to guess";
                }
                else
                {
                    warning = "Common names and surnames are easy to guess";
                }
            }

            var suggestions = new List <string>();
            var word        = match.Token;

            if (char.IsUpper(word[0]))
            {
                suggestions.Add("Capitalization doesn't help very much");
            }
            else if (word.All(c => char.IsUpper(c)) && word.ToLower() != word)
            {
                suggestions.Add("All-uppercase is almost as easy to guess as all-lowercase");
            }

            if (match.Reversed && match.Token.Length >= 4)
            {
                suggestions.Add("Reversed words aren't much harder to guess");
            }
            if (match.L33t)
            {
                suggestions.Add("Predictable substitutions like '@' instead of 'a' don't help very much");
            }

            return(new FeedbackItem
            {
                Suggestions = suggestions,
                Warning = warning,
            });
        }
Пример #15
0
        private static FeedbackItem GetDictionaryMatchFeedback(DictionaryMatch match, bool isSoleMatch)
        {
            var warning = string.Empty;

            if (match.DictionaryName == "passwords" ||
                match.DictionaryName == "fr-password")
            {
                if (isSoleMatch && !match.L33t && !match.Reversed)
                {
                    if (match.Rank <= 10)
                    {
                        // warning = "This is a top-10 common password";
                        warning = "Ce mot de passe fait parti des 10 les plus utilisé";
                    }
                    else if (match.Rank <= 100)
                    {
                        // warning = "This is a top-100 common password";
                        warning = "Ce mot de passe fait parti des 100 les plus utilisé";
                    }
                    else
                    {
                        // warning = "This is a very common password";
                        warning = "Ce mot de passe est trés commun";
                    }
                }
                else if (
                    (match.DictionaryName == "english" ||
                     match.DictionaryName == "fr") && isSoleMatch)
                {
                    // warning = "A word by itself is easy to guess";
                    warning = "Un mot, seul, est trés simple à deviner";
                }
                else if (match.DictionaryName == "surnames" ||
                         match.DictionaryName == "male_names" ||
                         match.DictionaryName == "female_names" ||
                         match.DictionaryName == "nom_femme" ||
                         match.DictionaryName == "nom_homme")
                {
                    if (isSoleMatch)
                    {
                        // warning = "Names and surnames by themselves are easy to guess";
                        warning = "Les noms propres sont trés simples à deviner";
                    }
                    else
                    {
                        // warning = "Common names and surnames are easy to guess";
                        warning = "Les noms propres sont trés simples à deviner";
                    }
                }
            }

            var suggestions = new List <string>();
            var word        = match.Token;

            if (char.IsUpper(word[0]))
            {
                // suggestions.Add("Capitalization doesn't help very much");
                suggestions.Add("Les lettres capitales n'avancent en rien.");
            }
            else if (word.All(c => char.IsUpper(c)) && word.ToLower() != word)
            {
                // suggestions.Add("All-uppercase is almost as easy to guess as all-lowercase");
                suggestions.Add("Tout en lettres capitales est aussi simple à deviner que tout en lettres minuscules");
            }

            if (match.Reversed && match.Token.Length >= 4)
            {
                // suggestions.Add("Reversed words aren't much harder to guess");
                suggestions.Add("Les mots inversés ne sont pas difficiles à deviner");
            }
            if (match.L33t)
            {
                // suggestions.Add("Predictable substitutions like '@' instead of 'a' don't help very much");
                suggestions.Add("Les substitutions simples comme un '@' à la place d'un 'a' sont simples à deviner");
            }

            return(new FeedbackItem
            {
                Suggestions = suggestions,
                Warning = warning,
            });
        }