| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687 |
- package matching
- import (
- "strings"
- "github.com/nbutton23/zxcvbn-go/adjacency"
- "github.com/nbutton23/zxcvbn-go/entropy"
- "github.com/nbutton23/zxcvbn-go/match"
- )
- const SPATIAL_MATCHER_NAME = "SPATIAL"
- func FilterSpatialMatcher(m match.Matcher) bool {
- return m.ID == SPATIAL_MATCHER_NAME
- }
- func spatialMatch(password string) (matches []match.Match) {
- for _, graph := range ADJACENCY_GRAPHS {
- if graph.Graph != nil {
- matches = append(matches, spatialMatchHelper(password, graph)...)
- }
- }
- return matches
- }
- 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
- }
|