Changed to use the Python version as my base.
This commit is contained in:
parent
21a0630b2e
commit
441bbc2241
|
@ -1,6 +1,6 @@
|
|||
# zxcvbn-go
|
||||
zxcvbn password complexity algorithm in golang
|
||||
|
||||
This is based off of the zxcvbn algorithm by Dropbox. https://github.com/dropbox/zxcvbn
|
||||
This is based off of the zxcvbn algorithm by Dropbox. https://github.com/dropbox/python-zxcvbn
|
||||
|
||||
This is a work in progress
|
||||
|
|
|
@ -3,6 +3,7 @@ import (
|
|||
"log"
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
// "fmt"
|
||||
)
|
||||
|
||||
|
||||
|
@ -58,3 +59,23 @@ func getAdjancencyGraphFromFile(filePath string) AdjacencyGraph {
|
|||
return graph
|
||||
}
|
||||
|
||||
//on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1.
|
||||
//this calculates the average over all keys.
|
||||
//TODO double check that i ported this correctly scoring.coffee ln 5
|
||||
func (adjGrp AdjacencyGraph) CalculateAvgDegree() (float32) {
|
||||
var avg float32
|
||||
var count float32
|
||||
for _, value := range adjGrp.Graph {
|
||||
|
||||
for _, char := range value {
|
||||
if char != "" || char != " " {
|
||||
avg += float32(len(char))
|
||||
count++
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return avg/count
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,150 @@
|
|||
package matching
|
||||
import (
|
||||
"strings"
|
||||
"github.com/bradfitz/slice"
|
||||
"regexp"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
var DICTIONARY_MATCHERS []func(password string) []Match
|
||||
|
||||
const (
|
||||
//TODO: Invalid regex for Golang since it has a \2
|
||||
DATE_RX_YEAR_SUFFIX string = `((\d{1,2})(\s|-|\/|\\|_|\.)(\d{1,2})(\s|-|\/|\\|_|\.)(19\d{2}|200\d|201\d|\d{2}))`
|
||||
DATE_RX_YEAR_PREFIX string = `((19\d{2}|200\d|201\d|\d{2})(\s|-|/|\\|_|\.)(\d{1,2})(\s|-|/|\\|_|\.)(\d{1,2}))`
|
||||
)
|
||||
type Match struct {
|
||||
Pattern string
|
||||
I, J int
|
||||
Token string
|
||||
MatchedWord string
|
||||
Rank int
|
||||
DictionaryName string
|
||||
}
|
||||
|
||||
type DateMatch struct {
|
||||
Pattern string
|
||||
I, J int
|
||||
Token string
|
||||
Separator string
|
||||
Day, Month, Year int64
|
||||
|
||||
}
|
||||
|
||||
func Omnimatch(password string, userInputs []string) []Match {
|
||||
var rankedUserInputsDir map[string]int
|
||||
|
||||
for i, v := range userInputs {
|
||||
rankedUserInputsDir[strings.ToLower(v)] = i+1
|
||||
}
|
||||
userInputMatcher := buildDictMatcher("user_inputs", rankedUserInputsDir)
|
||||
matches := userInputMatcher(password)
|
||||
|
||||
for _, matcher := range DICTIONARY_MATCHERS {
|
||||
mtemp := matcher(password)
|
||||
for _,v:= range mtemp {
|
||||
matches = append(matches, v)
|
||||
}
|
||||
}
|
||||
slice.Sort(matches,func(i, j int)bool{
|
||||
//TODO fix this
|
||||
return false;
|
||||
})
|
||||
return matches
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []Match {
|
||||
return func (password string) []Match{
|
||||
matches := dictionaryMatch(password, rankedDict)
|
||||
for _, v := range matches {
|
||||
v.DictionaryName = dictName
|
||||
}
|
||||
return matches
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func dictionaryMatch(password string, rankedDict map[string]int) []Match{
|
||||
length := len(password)
|
||||
var results []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 {
|
||||
results = append(results, Match{Pattern:"dictionary",
|
||||
I:i,
|
||||
J:j,
|
||||
Token:password[i:j+1],
|
||||
MatchedWord:word,
|
||||
Rank:val})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
|
||||
func checkDate(day, month, year int64)( bool, int64, int64, int64){
|
||||
if (12 <= month && month <= 31) && day <= 12 {
|
||||
day, month = month, day
|
||||
}
|
||||
|
||||
if day > 31 || month > 12 {
|
||||
return false, 0, 0, 0
|
||||
}
|
||||
|
||||
if !(1900 <= year && year <=2019) {
|
||||
return false, 0, 0, 0
|
||||
}
|
||||
|
||||
return true, day, month, year
|
||||
}
|
||||
|
||||
func DateSepMatch(password string) []DateMatch {
|
||||
|
||||
var matches []DateMatch
|
||||
|
||||
|
||||
matcher := regexp.MustCompile(DATE_RX_YEAR_SUFFIX)
|
||||
for _, v := range matcher.FindAllString(password,len(password)) {
|
||||
splitV := matcher.FindAllStringSubmatch(v, len(v))
|
||||
i := strings.Index(password,v)
|
||||
j := i+len(v)
|
||||
day, _ := strconv.ParseInt(splitV[0][4],10,16)
|
||||
month, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
||||
year, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
||||
match := DateMatch{Day:day, Month:month, Year:year, Separator:splitV[0][5], I:i, J:j }
|
||||
matches = append(matches, match)
|
||||
}
|
||||
|
||||
|
||||
matcher = regexp.MustCompile(DATE_RX_YEAR_PREFIX)
|
||||
for _, v := range matcher.FindAllString(password,len(password)) {
|
||||
splitV := matcher.FindAllStringSubmatch(v, len(v))
|
||||
i := strings.Index(password,v)
|
||||
j := i+len(v)
|
||||
day, _ := strconv.ParseInt(splitV[0][4],10,16)
|
||||
month, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
||||
year, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
||||
match := DateMatch{Day:day, Month:month, Year:year, Separator:splitV[0][5], I:i, J:j }
|
||||
matches = append(matches, match)
|
||||
}
|
||||
|
||||
var out []DateMatch
|
||||
for _, match := range matches {
|
||||
if valid, day, month, year := checkDate(match.Day, match.Month, match.Year); valid{
|
||||
match.Pattern = "date"
|
||||
match.Day = day
|
||||
match.Month = month
|
||||
match.Year = year
|
||||
out = append(out, match)
|
||||
}
|
||||
}
|
||||
return out
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package math
|
||||
|
||||
|
||||
|
||||
/**
|
||||
I am surprised that I have to define these. . . Maybe i just didn't look hard enough for a lib.
|
||||
*/
|
||||
|
||||
//http://blog.plover.com/math/choose.html
|
||||
func NChoseK(n, k uint) uint64 {
|
||||
uN := uint64(n)
|
||||
uK := uint64(k)
|
||||
if uK > uN {
|
||||
return 0
|
||||
} else if uK == 0 {
|
||||
return 1
|
||||
}
|
||||
|
||||
var r uint64 = 1
|
||||
|
||||
for d := uint64(1) ; d <= uK; d++ {
|
||||
r *= uN
|
||||
r /= d
|
||||
uN--
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
17
zxcvbn.go
17
zxcvbn.go
|
@ -1,14 +1,21 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
// "zxcvbn-go/adjacency"
|
||||
"zxcvbn-go/adjacency"
|
||||
"fmt"
|
||||
"zxcvbn-go/frequency"
|
||||
"zxcvbn-go/utils/math"
|
||||
"zxcvbn-go/matching"
|
||||
)
|
||||
|
||||
func main(){
|
||||
func main() {
|
||||
fmt.Println("Start")
|
||||
// fmt.Println(adjacency.AdjacencyGph)
|
||||
fmt.Println(adjacency.AdjacencyGph.Qwerty.CalculateAvgDegree())
|
||||
fmt.Println(adjacency.AdjacencyGph.Dvorak.CalculateAvgDegree())
|
||||
fmt.Println(adjacency.AdjacencyGph.Keypad.CalculateAvgDegree())
|
||||
fmt.Println(adjacency.AdjacencyGph.MacKeypad.CalculateAvgDegree())
|
||||
|
||||
fmt.Println(len(frequency.FreqLists.Passwords))
|
||||
|
||||
fmt.Println(math.NChoseK(100, 2))
|
||||
|
||||
fmt.Println(matching.DateSepMatch("1991-09-11jibjab11.9.1991"))
|
||||
}
|
Loading…
Reference in New Issue