public void AccountsForTurnPositionsDirectionsAndStartingKey() { var match = new SpatialMatch { Token = "zxcvbn", Graph = "qwerty", Turns = 3, ShiftedCount = 0, i = 1, j = 2, }; var l = match.Token.Length; var s = SpatialGuessesCalculator.KeyboardStartingPositions; var d = SpatialGuessesCalculator.KeyboardAverageDegree; var expected = 0.0; for (var i = 2; i <= l; i++) { for (var j = 1; j <= Math.Min(match.Turns, i - 1); j++) { expected += PasswordScoring.Binomial(i - 1, j - 1) * s * Math.Pow(d, j); } } var actual = SpatialGuessesCalculator.CalculateGuesses(match); actual.Should().Be(expected); }
private void GetMatchFeedback(Match match, bool isSoleMatch, PasswordMetricResult result) { switch (match.Pattern) { case "dictionary": GetDictionaryMatchFeedback((DictionaryMatch)match, isSoleMatch, result); break; case "spatial": SpatialMatch spatialMatch = (SpatialMatch)match; if (spatialMatch.Turns == 1) { result.warning = Warning.StraightRow; } else { result.warning = Warning.ShortKeyboardPatterns; } result.suggestions.Clear(); result.suggestions.Add(Suggestion.UseLongerKeyboardPattern); break; case "repeat": //todo: add support for repeated sequences longer than 1 char // if(match.Token.Length == 1) result.warning = Warning.RepeatsLikeAaaEasy; // else // result.warning = Warning.RepeatsLikeAbcSlighterHarder; result.suggestions.Clear(); result.suggestions.Add(Suggestion.AvoidRepeatedWordsAndChars); break; case "sequence": result.warning = Warning.SequenceAbcEasy; result.suggestions.Clear(); result.suggestions.Add(Suggestion.AvoidSequences); break; //todo: add support for recent_year, however not example exist on https://dl.dropboxusercontent.com/u/209/zxcvbn/test/index.html case "date": result.warning = Warning.DatesEasy; result.suggestions.Clear(); result.suggestions.Add(Suggestion.AvoidDatesYearsAssociatedYou); break; } }
/// <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(SpatialMatch match) { int s; double d; if (match.Graph == "qwerty" || match.Graph == "dvorak") { s = KeyboardStartingPositions; d = KeyboardAverageDegree; } else { s = KeypadStartingPositions; d = KeypadAverageDegree; } double guesses = 0; var l = match.Token.Length; var t = match.Turns; for (var i = 2; i <= l; i++) { var possibleTurns = Math.Min(t, i - 1); for (var j = 1; j <= possibleTurns; j++) { guesses += PasswordScoring.Binomial(i - 1, j - 1) * s * Math.Pow(d, j); } } if (match.ShiftedCount > 0) { var shifted = match.ShiftedCount; var unshifted = match.Token.Length - match.ShiftedCount; if (shifted == 0 || unshifted == 0) { guesses *= 2; } else { double variations = 0; for (var i = 1; i <= Math.Min(shifted, unshifted); i++) { variations += PasswordScoring.Binomial(shifted + unshifted, i); } guesses *= variations; } } return(guesses); }
private static double SpatialGuesses(Match match) { SpatialMatch sm = (SpatialMatch)match; double s; double d; if (sm.Graph.Equals("qwerty") || sm.Graph.Equals("dvorak")) { s = 4.596; d = 94; } else { s = 5.0; d = 15.5; } double guesses = 0; int L = sm.Token.Length; int t = sm.Turns; foreach (int i in EnumerableUtility.Range(2, L + 1)) { int possible_turns = (int)Math.Min(t, i - 1); foreach (int j in EnumerableUtility.Range(1, possible_turns + 1)) { guesses += nCk(i - 1, j - 1) * s * Math.Pow(d, j); } } if (sm.ShiftedCount > 0) { int S = sm.ShiftedCount; int U = sm.Token.Length - S; if (S == 0 || U == 0) { guesses *= 2; } else { double shiftedVariations = 0; int rangeEnd = (int)Math.Min(S, U); foreach (int i in EnumerableUtility.Range(1, rangeEnd + 1)) { shiftedVariations += nCk(S + U, i); } guesses *= shiftedVariations; } } return(guesses); }
public void GuessesWhenThereAreNoTurns() { var match = new SpatialMatch { Token = "zxcvbn", Graph = "qwerty", Turns = 1, ShiftedCount = 0, i = 1, j = 2, }; var expected = SpatialGuessesCalculator.KeyboardStartingPositions * SpatialGuessesCalculator.KeyboardAverageDegree * (match.Token.Length - 1); var actual = SpatialGuessesCalculator.CalculateGuesses(match); actual.Should().Be(expected); }
public void DoublesGuessesIfEverythingIsShifted() { var match = new SpatialMatch { Token = "zxcvbn", Graph = "qwerty", Turns = 1, ShiftedCount = 6, i = 1, j = 2, }; var expected = SpatialGuessesCalculator.KeyboardStartingPositions * SpatialGuessesCalculator.KeyboardAverageDegree * (match.Token.Length - 1) * 2; var actual = SpatialGuessesCalculator.CalculateGuesses(match); actual.Should().Be(expected); }
public void IsDelegatedToByEstimateGuesses() { var match = new SpatialMatch { Token = "zxcvbn", Graph = "qwerty", Turns = 1, ShiftedCount = 0, i = 1, j = 2, }; var expected = SpatialGuessesCalculator.KeyboardStartingPositions * SpatialGuessesCalculator.KeyboardAverageDegree * (match.Token.Length - 1); var actual = PasswordScoring.EstimateGuesses(match, match.Token); actual.Should().Be(expected); }