Fixed the spatial match issue. Added more test
This commit is contained in:
parent
7fa8f55be0
commit
24b6c156b2
|
@ -92,7 +92,7 @@ func dataDvorakJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/Dvorak.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/Dvorak.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -112,7 +112,7 @@ func dataEnglishJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/English.json", size: 341560, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/English.json", size: 341560, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -132,7 +132,7 @@ func dataFemalenamesJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/FemaleNames.json", size: 53909, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/FemaleNames.json", size: 53909, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -152,7 +152,7 @@ func dataKeypadJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/Keypad.json", size: 1639, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/Keypad.json", size: 1639, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -172,7 +172,7 @@ func dataL33tJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/L33t.json", size: 477, mode: os.FileMode(420), modTime: time.Unix(1444170193, 0)}
|
||||
info := bindataFileInfo{name: "data/L33t.json", size: 477, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -192,7 +192,7 @@ func dataMackeypadJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/MacKeypad.json", size: 1744, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/MacKeypad.json", size: 1744, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -212,7 +212,7 @@ func dataMalenamesJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/MaleNames.json", size: 11791, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/MaleNames.json", size: 11791, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -232,7 +232,7 @@ func dataPasswordsJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/Passwords.json", size: 67534, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/Passwords.json", size: 67534, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -252,7 +252,7 @@ func dataQwertyJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/Qwerty.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/Qwerty.json", size: 8398, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
@ -272,7 +272,7 @@ func dataSurnamesJson() (*asset, error) {
|
|||
return nil, err
|
||||
}
|
||||
|
||||
info := bindataFileInfo{name: "data/Surnames.json", size: 396413, mode: os.FileMode(420), modTime: time.Unix(1444169890, 0)}
|
||||
info := bindataFileInfo{name: "data/Surnames.json", size: 396413, mode: os.FileMode(420), modTime: time.Unix(1452717629, 0)}
|
||||
a := &asset{bytes: bytes, info: info}
|
||||
return a, nil
|
||||
}
|
||||
|
|
|
@ -65,13 +65,13 @@ func loadFrequencyList() {
|
|||
KEYPAD_AVG_DEGREE = adjacency.AdjacencyGph["keypad"].CalculateAvgDegree()
|
||||
KEYPAD_STARTING_POSITIONS = len(adjacency.AdjacencyGph["keypad"].Graph)
|
||||
|
||||
ADJACENCY_GRAPHS = append(ADJACENCY_GRAPHS, adjacency.AdjacencyGph["querty"])
|
||||
ADJACENCY_GRAPHS = append(ADJACENCY_GRAPHS, adjacency.AdjacencyGph["qwerty"])
|
||||
ADJACENCY_GRAPHS = append(ADJACENCY_GRAPHS, adjacency.AdjacencyGph["dvorak"])
|
||||
ADJACENCY_GRAPHS = append(ADJACENCY_GRAPHS, adjacency.AdjacencyGph["keypad"])
|
||||
ADJACENCY_GRAPHS = append(ADJACENCY_GRAPHS, adjacency.AdjacencyGph["macKeypad"])
|
||||
//
|
||||
// l33tFilePath, _ := filepath.Abs("adjacency/L33t.json")
|
||||
// L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t")
|
||||
|
||||
//l33tFilePath, _ := filepath.Abs("adjacency/L33t.json")
|
||||
//L33T_TABLE = adjacency.GetAdjancencyGraphFromFile(l33tFilePath, "l33t")
|
||||
|
||||
SEQUENCES = make(map[string]string)
|
||||
SEQUENCES["lower"] = "abcdefghijklmnopqrstuvwxyz"
|
||||
|
@ -79,8 +79,8 @@ func loadFrequencyList() {
|
|||
SEQUENCES["digits"] = "0123456789"
|
||||
|
||||
MATCHERS = append(MATCHERS, DICTIONARY_MATCHERS...)
|
||||
MATCHERS = append(MATCHERS, spatialMatch)
|
||||
MATCHERS = append(MATCHERS, repeatMatch)
|
||||
MATCHERS = append(MATCHERS, SpatialMatch)
|
||||
MATCHERS = append(MATCHERS, RepeatMatch)
|
||||
MATCHERS = append(MATCHERS, SequenceMatch)
|
||||
|
||||
}
|
||||
|
@ -244,17 +244,22 @@ func buildDateMatchCandidateTwo(day, month byte, year string, i, j int) match.Da
|
|||
return match.DateMatch{Day: intDay, Month: intMonth, Year: intYear, I: i, J: j}
|
||||
}
|
||||
|
||||
func spatialMatch(password string) (matches []match.Match) {
|
||||
//TODO: This is not working.
|
||||
//It appears that the Adjacency graph data is incorrect. Need to get a new copy from python-zxcvbn.
|
||||
func SpatialMatch(password string) (matches []match.Match) {
|
||||
for _, graph := range ADJACENCY_GRAPHS {
|
||||
matches = append(matches, spatialMatchHelper(password, graph)...)
|
||||
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 //and int that it should never be!
|
||||
lastDirection := -99 //an int that it should never be!
|
||||
turns := 0
|
||||
shiftedCount := 0
|
||||
|
||||
|
@ -263,8 +268,9 @@ func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matche
|
|||
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
|
||||
//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 {
|
||||
|
@ -275,15 +281,14 @@ func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matche
|
|||
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.
|
||||
|
||||
//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.
|
||||
//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
|
||||
}
|
||||
|
@ -292,16 +297,16 @@ func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matche
|
|||
}
|
||||
}
|
||||
|
||||
// if the current pattern continued, extend j and try to grow again
|
||||
//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.
|
||||
//otherwise push the pattern discovered so far, if any...
|
||||
//don't consider length 1 or 2 chains.
|
||||
if j-i > 2 {
|
||||
matches = append(matches, match.Match{Pattern: "spatial", I: i, J: j - 1, Token: password[i:j], DictionaryName: graph.Name, Turns: turns, ShiftedCount: shiftedCount})
|
||||
}
|
||||
// . . . and then start a new search from the rest of the password
|
||||
//. . . and then start a new search from the rest of the password
|
||||
i = j
|
||||
break
|
||||
}
|
||||
|
@ -340,7 +345,7 @@ func relevantL33tSubtable(password string) adjacency.AdjacencyGraph {
|
|||
// }
|
||||
//}
|
||||
|
||||
func repeatMatch(password string) []match.Match {
|
||||
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
|
||||
|
@ -355,7 +360,7 @@ func repeatMatch(password string) []match.Match {
|
|||
continue
|
||||
}
|
||||
|
||||
if current == prev {
|
||||
if strings.ToLower(current) == strings.ToLower(prev) {
|
||||
currentStreak++
|
||||
|
||||
} else if currentStreak > 2 {
|
||||
|
|
|
@ -2,6 +2,8 @@ package matching
|
|||
|
||||
import (
|
||||
"github.com/nbutton23/zxcvbn-go/Godeps/_workspace/src/github.com/stretchr/testify/assert"
|
||||
"github.com/nbutton23/zxcvbn-go/match"
|
||||
"strings"
|
||||
"testing"
|
||||
)
|
||||
|
||||
|
@ -30,3 +32,78 @@ func TestDateSepMatch(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
|
||||
func TestRepeatMatch(t *testing.T) {
|
||||
//aaaBbBb
|
||||
matches := RepeatMatch("aaabBbB")
|
||||
|
||||
assert.Len(t, matches, 2, "Lenght should be 2")
|
||||
|
||||
for _, match := range matches {
|
||||
if strings.ToLower(match.RepeatedChar) == "b" {
|
||||
assert.Equal(t, 3, match.I)
|
||||
assert.Equal(t, 6, match.J)
|
||||
assert.Equal(t, "bBbB", match.Token)
|
||||
} else {
|
||||
assert.Equal(t, 0, match.I)
|
||||
assert.Equal(t, 2, match.J)
|
||||
assert.Equal(t, "aaa", match.Token)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSequenceMatch(t *testing.T) {
|
||||
//abcdjibjacLMNOPjibjac1234 => abcd LMNOP 1234
|
||||
|
||||
matches := SequenceMatch("abcdjibjacLMNOPjibjac1234")
|
||||
assert.Len(t, matches, 3, "Lenght should be 2")
|
||||
|
||||
for _, match := range matches {
|
||||
if match.DictionaryName == "lower" {
|
||||
assert.Equal(t, 0, match.I)
|
||||
assert.Equal(t, 3, match.J)
|
||||
assert.Equal(t, "abcd", match.Token)
|
||||
} else if match.DictionaryName == "upper" {
|
||||
assert.Equal(t, 10, match.I)
|
||||
assert.Equal(t, 14, match.J)
|
||||
assert.Equal(t, "LMNOP", match.Token)
|
||||
} else if match.DictionaryName == "digits" {
|
||||
assert.Equal(t, 21, match.I)
|
||||
assert.Equal(t, 24, match.J)
|
||||
assert.Equal(t, "1234", match.Token)
|
||||
} else {
|
||||
assert.True(t, false, "Unknow dictionary")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestSpatialMatchQwerty(t *testing.T) {
|
||||
matches := SpatialMatch("qwerty")
|
||||
assert.Len(t, matches, 1, "Lenght should be 1")
|
||||
|
||||
matches = SpatialMatch("asdf")
|
||||
assert.Len(t, matches, 1, "Lenght should be 1")
|
||||
|
||||
}
|
||||
|
||||
func TestSpatialMatchDvorak(t *testing.T) {
|
||||
matches := SpatialMatch("aoeuidhtns")
|
||||
assert.Len(t, matches, 1, "Lenght should be 1")
|
||||
|
||||
}
|
||||
|
||||
func TestDictionaryMatch(t *testing.T) {
|
||||
var matches []match.Match
|
||||
for _, dicMatcher := range DICTIONARY_MATCHERS {
|
||||
matchesTemp := dicMatcher("first")
|
||||
matches = append(matches, matchesTemp...)
|
||||
}
|
||||
|
||||
assert.Len(t, matches, 4, "Lenght should be 4")
|
||||
|
||||
}
|
||||
|
||||
func TestDateWithoutSepMatch(t *testing.T) {
|
||||
matches := dateWithoutSepMatch("11091991")
|
||||
assert.Len(t, matches, 1, "Lenght should be 1")
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
|||
}
|
||||
}
|
||||
|
||||
// walk backwards and decode the best sequence
|
||||
//walk backwards and decode the best sequence
|
||||
var matchSequence []match.Match
|
||||
passwordLen := len(password)
|
||||
passwordLen--
|
||||
|
|
Loading…
Reference in New Issue