func sequenceMatch(password string) []match.Match { var matches []match.Match for i := 0; i < len(password); { j := i + 1 var seq string var seqName string seqDirection := 0 for seqCandidateName, seqCandidate := range SEQUENCES { iN := strings.Index(seqCandidate, string(password[i])) var jN int if j < len(password) { jN = strings.Index(seqCandidate, string(password[j])) } else { jN = -1 } if iN > -1 && jN > -1 { direction := jN - iN if direction == 1 || direction == -1 { seq = seqCandidate seqName = seqCandidateName seqDirection = direction break } } } if seq != "" { for { var prevN, curN int if j < len(password) { prevChar, curChar := password[j-1], password[j] prevN, curN = strings.Index(seq, string(prevChar)), strings.Index(seq, string(curChar)) } if j == len(password) || curN-prevN != seqDirection { if j-i > 2 { matchSequence := match.Match{ Pattern: "sequence", I: i, J: j - 1, Token: password[i:j], DictionaryName: seqName, } matchSequence.Entropy = entropy.SequenceEntropy(matchSequence, len(seq), (seqDirection == 1)) matches = append(matches, matchSequence) } break } else { j += 1 } } } i = j } return matches }
func repeatMatch(password string) []match.Match { var matches []match.Match //Loop through password. if current == prev currentStreak++ else if currentStreak > 2 {buildMatch; currentStreak = 1} prev = current var current, prev string currentStreak := 1 var i int var char rune for i, char = range password { current = string(char) if i == 0 { prev = current continue } if strings.ToLower(current) == strings.ToLower(prev) { currentStreak++ } else if currentStreak > 2 { iPos := i - currentStreak jPos := i - 1 matchRepeat := match.Match{ Pattern: "repeat", I: iPos, J: jPos, Token: password[iPos : jPos+1], DictionaryName: prev} matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) matches = append(matches, matchRepeat) currentStreak = 1 } else { currentStreak = 1 } prev = current } if currentStreak > 2 { iPos := i - currentStreak + 1 jPos := i matchRepeat := match.Match{ Pattern: "repeat", I: iPos, J: jPos, Token: password[iPos : jPos+1], DictionaryName: prev} matchRepeat.Entropy = entropy.RepeatEntropy(matchRepeat) matches = append(matches, matchRepeat) } return matches }
func dictionaryMatch(password string, dictionaryName string, rankedDict map[string]int) []match.Match { length := len(password) var results []match.Match pwLower := strings.ToLower(password) for i := 0; i < length; i++ { for j := i; j < length; j++ { word := pwLower[i : j+1] if val, ok := rankedDict[word]; ok { matchDic := match.Match{Pattern: "dictionary", DictionaryName: dictionaryName, I: i, J: j, Token: password[i : j+1], } matchDic.Entropy = entropy.DictionaryEntropy(matchDic, float64(val)) results = append(results, matchDic) } } } return results }
func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matches []match.Match) { for i := 0; i < len(password)-1; { j := i + 1 lastDirection := -99 //an int that it should never be! turns := 0 shiftedCount := 0 for { prevChar := password[j-1] found := false foundDirection := -1 curDirection := -1 //My graphs seem to be wrong. . . and where the hell is qwerty adjacents := graph.Graph[string(prevChar)] //Consider growing pattern by one character if j hasn't gone over the edge if j < len(password) { curChar := password[j] for _, adj := range adjacents { curDirection += 1 if strings.Index(adj, string(curChar)) != -1 { found = true foundDirection = curDirection if strings.Index(adj, string(curChar)) == 1 { //index 1 in the adjacency means the key is shifted, 0 means unshifted: A vs a, % vs 5, etc. //for example, 'q' is adjacent to the entry '2@'. @ is shifted w/ index 1, 2 is unshifted. shiftedCount += 1 } if lastDirection != foundDirection { //adding a turn is correct even in the initial case when last_direction is null: //every spatial pattern starts with a turn. turns += 1 lastDirection = foundDirection } break } } } //if the current pattern continued, extend j and try to grow again if found { j += 1 } else { //otherwise push the pattern discovered so far, if any... //don't consider length 1 or 2 chains. if j-i > 2 { matchSpc := match.Match{Pattern: "spatial", I: i, J: j - 1, Token: password[i:j], DictionaryName: graph.Name} matchSpc.Entropy = entropy.SpatialEntropy(matchSpc, turns, shiftedCount) matches = append(matches, matchSpc) } //. . . and then start a new search from the rest of the password i = j break } } } return matches }