Skip to content
This repository has been archived by the owner on Feb 1, 2023. It is now read-only.

Commit

Permalink
Fix some small preformance issues as well as get lint passing
Browse files Browse the repository at this point in the history
  • Loading branch information
nbutton23 committed Aug 29, 2018
1 parent 780cc39 commit 953e4e2
Show file tree
Hide file tree
Showing 18 changed files with 188 additions and 184 deletions.
66 changes: 39 additions & 27 deletions adjacency/adjcmartix.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,65 +3,76 @@ package adjacency
import (
"encoding/json"
"log"
// "fmt"

"github.com/nbutton23/zxcvbn-go/data"
)

type AdjacencyGraph struct {
// Graph holds information about different graphs
type Graph struct {
Graph map[string][]string
averageDegree float64
Name string
}

var AdjacencyGph = make(map[string]AdjacencyGraph)
// GraphMap is a map of all graphs
var GraphMap = make(map[string]Graph)

func init() {
AdjacencyGph["qwerty"] = BuildQwerty()
AdjacencyGph["dvorak"] = BuildDvorak()
AdjacencyGph["keypad"] = BuildKeypad()
AdjacencyGph["macKeypad"] = BuildMacKeypad()
AdjacencyGph["l33t"] = BuildLeet()
GraphMap["qwerty"] = BuildQwerty()
GraphMap["dvorak"] = BuildDvorak()
GraphMap["keypad"] = BuildKeypad()
GraphMap["macKeypad"] = BuildMacKeypad()
GraphMap["l33t"] = BuildLeet()
}

func BuildQwerty() AdjacencyGraph {
data, err := zxcvbn_data.Asset("data/Qwerty.json")
//BuildQwerty builds the Qwerty Graph
func BuildQwerty() Graph {
data, err := data.Asset("data/Qwerty.json")
if err != nil {
panic("Can't find asset")
}
return GetAdjancencyGraphFromFile(data, "qwerty")
return getAdjancencyGraphFromFile(data, "qwerty")
}
func BuildDvorak() AdjacencyGraph {
data, err := zxcvbn_data.Asset("data/Dvorak.json")

//BuildDvorak builds the Dvorak Graph
func BuildDvorak() Graph {
data, err := data.Asset("data/Dvorak.json")
if err != nil {
panic("Can't find asset")
}
return GetAdjancencyGraphFromFile(data, "dvorak")
return getAdjancencyGraphFromFile(data, "dvorak")
}
func BuildKeypad() AdjacencyGraph {
data, err := zxcvbn_data.Asset("data/Keypad.json")

//BuildKeypad builds the Keypad Graph
func BuildKeypad() Graph {
data, err := data.Asset("data/Keypad.json")
if err != nil {
panic("Can't find asset")
}
return GetAdjancencyGraphFromFile(data, "keypad")
return getAdjancencyGraphFromFile(data, "keypad")
}
func BuildMacKeypad() AdjacencyGraph {
data, err := zxcvbn_data.Asset("data/MacKeypad.json")

//BuildMacKeypad builds the Mac Keypad Graph
func BuildMacKeypad() Graph {
data, err := data.Asset("data/MacKeypad.json")
if err != nil {
panic("Can't find asset")
}
return GetAdjancencyGraphFromFile(data, "mac_keypad")
return getAdjancencyGraphFromFile(data, "mac_keypad")
}
func BuildLeet() AdjacencyGraph {
data, err := zxcvbn_data.Asset("data/L33t.json")

//BuildLeet builds the L33T Graph
func BuildLeet() Graph {
data, err := data.Asset("data/L33t.json")
if err != nil {
panic("Can't find asset")
}
return GetAdjancencyGraphFromFile(data, "keypad")
return getAdjancencyGraphFromFile(data, "keypad")
}

func GetAdjancencyGraphFromFile(data []byte, name string) AdjacencyGraph {
func getAdjancencyGraphFromFile(data []byte, name string) Graph {

var graph AdjacencyGraph
var graph Graph
err := json.Unmarshal(data, &graph)
if err != nil {
log.Fatal(err)
Expand All @@ -70,10 +81,11 @@ func GetAdjancencyGraphFromFile(data []byte, name string) AdjacencyGraph {
return graph
}

// CalculateAvgDegree calclates the average degree between nodes in the 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() float64 {
func (adjGrp Graph) CalculateAvgDegree() float64 {
if adjGrp.averageDegree != float64(0) {
return adjGrp.averageDegree
}
Expand All @@ -82,7 +94,7 @@ func (adjGrp AdjacencyGraph) CalculateAvgDegree() float64 {
for _, value := range adjGrp.Graph {

for _, char := range value {
if char != "" || char != " " {
if len(char) != 0 || char != " " {
avg += float64(len(char))
count++
}
Expand Down
2 changes: 1 addition & 1 deletion data/bindata.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

47 changes: 24 additions & 23 deletions entropy/entropyCalculator.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,20 @@ import (
)

const (
START_UPPER string = `^[A-Z][^A-Z]+$`
END_UPPER string = `^[^A-Z]+[A-Z]$'`
ALL_UPPER string = `^[A-Z]+$`
NUM_YEARS = float64(119) // years match against 1900 - 2019
NUM_MONTHS = float64(12)
NUM_DAYS = float64(31)
numYears = float64(119) // years match against 1900 - 2019
numMonths = float64(12)
numDays = float64(31)
)

var (
KEYPAD_STARTING_POSITIONS = len(adjacency.AdjacencyGph["keypad"].Graph)
KEYPAD_AVG_DEGREE = adjacency.AdjacencyGph["keypad"].CalculateAvgDegree()
startUpperRx = regexp.MustCompile(`^[A-Z][^A-Z]+$`)
endUpperRx = regexp.MustCompile(`^[^A-Z]+[A-Z]$'`)
allUpperRx = regexp.MustCompile(`^[A-Z]+$`)
keyPadStartingPositions = len(adjacency.GraphMap["keypad"].Graph)
keyPadAvgDegree = adjacency.GraphMap["keypad"].CalculateAvgDegree()
)

// DictionaryEntropy calculates the entropy of a dictionary match
func DictionaryEntropy(match match.Match, rank float64) float64 {
baseEntropy := math.Log2(rank)
upperCaseEntropy := extraUpperCaseEntropy(match)
Expand All @@ -49,9 +50,7 @@ func extraUpperCaseEntropy(match match.Match) float64 {
//so it only doubles the search space (uncapitalized + capitalized): 1 extra bit of entropy.
//allcaps and end-capitalized are common enough too, underestimate as 1 extra bit to be safe.

for _, regex := range []string{START_UPPER, END_UPPER, ALL_UPPER} {
matcher := regexp.MustCompile(regex)

for _, matcher := range []*regexp.Regexp{startUpperRx, endUpperRx, allUpperRx} {
if matcher.MatchString(word) {
return float64(1)
}
Expand All @@ -72,7 +71,7 @@ func extraUpperCaseEntropy(match match.Match) float64 {
var possibililities float64

for i := float64(0); i <= math.Min(countUpper, countLower); i++ {
possibililities += float64(zxcvbn_math.NChoseK(totalLenght, i))
possibililities += float64(zxcvbnmath.NChoseK(totalLenght, i))
}

if possibililities < 1 {
Expand All @@ -82,15 +81,16 @@ func extraUpperCaseEntropy(match match.Match) float64 {
return float64(math.Log2(possibililities))
}

// SpatialEntropy calculates the entropy for spatial matches
func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
var s, d float64
if match.DictionaryName == "qwerty" || match.DictionaryName == "dvorak" {
//todo: verify qwerty and dvorak have the same length and degree
s = float64(len(adjacency.BuildQwerty().Graph))
d = adjacency.BuildQwerty().CalculateAvgDegree()
} else {
s = float64(KEYPAD_STARTING_POSITIONS)
d = KEYPAD_AVG_DEGREE
s = float64(keyPadStartingPositions)
d = keyPadAvgDegree
}

possibilities := float64(0)
Expand All @@ -102,7 +102,7 @@ func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
for i := float64(2); i <= length+1; i++ {
possibleTurns := math.Min(float64(turns), i-1)
for j := float64(1); j <= possibleTurns+1; j++ {
x := zxcvbn_math.NChoseK(i-1, j-1) * s * math.Pow(d, j)
x := zxcvbnmath.NChoseK(i-1, j-1) * s * math.Pow(d, j)
possibilities += x
}
}
Expand All @@ -116,7 +116,7 @@ func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
U := length - S

for i := float64(0); i < math.Min(S, U)+1; i++ {
possibilities += zxcvbn_math.NChoseK(S+U, i)
possibilities += zxcvbnmath.NChoseK(S+U, i)
}

entropy += math.Log2(possibilities)
Expand All @@ -125,13 +125,15 @@ func SpatialEntropy(match match.Match, turns int, shiftCount int) float64 {
return entropy
}

// RepeatEntropy calculates the entropy for repeating entropy
func RepeatEntropy(match match.Match) float64 {
cardinality := CalcBruteForceCardinality(match.Token)
entropy := math.Log2(cardinality * float64(len(match.Token)))

return entropy
}

// CalcBruteForceCardinality calculates the brute force cardinality
//TODO: Validate against python
func CalcBruteForceCardinality(password string) float64 {
lower, upper, digits, symbols := float64(0), float64(0), float64(0), float64(0)
Expand All @@ -152,6 +154,7 @@ func CalcBruteForceCardinality(password string) float64 {
return cardinality
}

// SequenceEntropy calculates the entropy for sequences such as 4567 or cdef
func SequenceEntropy(match match.Match, dictionaryLength int, ascending bool) float64 {
firstChar := match.Token[0]
baseEntropy := float64(0)
Expand All @@ -171,6 +174,7 @@ func SequenceEntropy(match match.Match, dictionaryLength int, ascending bool) fl
return baseEntropy + math.Log2(float64(len(match.Token)))
}

// ExtraLeetEntropy calulates the added entropy provied by l33t substitustions
func ExtraLeetEntropy(match match.Match, password string) float64 {
var subsitutions float64
var unsub float64
Expand All @@ -187,7 +191,7 @@ func ExtraLeetEntropy(match match.Match, password string) float64 {
var possibilities float64

for i := float64(0); i <= math.Min(subsitutions, unsub)+1; i++ {
possibilities += zxcvbn_math.NChoseK(subsitutions+unsub, i)
possibilities += zxcvbnmath.NChoseK(subsitutions+unsub, i)
}

if possibilities <= 1 {
Expand All @@ -196,16 +200,13 @@ func ExtraLeetEntropy(match match.Match, password string) float64 {
return math.Log2(possibilities)
}

func YearEntropy(dateMatch match.DateMatch) float64 {
return math.Log2(NUM_YEARS)
}

// DateEntropy calculates the entropy provided by a date
func DateEntropy(dateMatch match.DateMatch) float64 {
var entropy float64
if dateMatch.Year < 100 {
entropy = math.Log2(NUM_DAYS * NUM_MONTHS * 100)
entropy = math.Log2(numDays * numMonths * 100)
} else {
entropy = math.Log2(NUM_DAYS * NUM_MONTHS * NUM_YEARS)
entropy = math.Log2(numDays * numMonths * numYears)
}

if dateMatch.Separator != "" {
Expand Down
27 changes: 14 additions & 13 deletions frequency/frequency.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,17 @@ package frequency

import (
"encoding/json"
"github.com/nbutton23/zxcvbn-go/data"
"log"
)

type FrequencyList struct {
"github.com/nbutton23/zxcvbn-go/data"
)
// List holds a frequency list
type List struct {
Name string
List []string
}

var FrequencyLists = make(map[string]FrequencyList)
// Lists holds all the frequency list in a map
var Lists = make(map[string]List)

func init() {
maleFilePath := getAsset("data/MaleNames.json")
Expand All @@ -20,24 +21,24 @@ func init() {
englishFilePath := getAsset("data/English.json")
passwordsFilePath := getAsset("data/Passwords.json")

FrequencyLists["MaleNames"] = GetStringListFromAsset(maleFilePath, "MaleNames")
FrequencyLists["FemaleNames"] = GetStringListFromAsset(femaleFilePath, "FemaleNames")
FrequencyLists["Surname"] = GetStringListFromAsset(surnameFilePath, "Surname")
FrequencyLists["English"] = GetStringListFromAsset(englishFilePath, "English")
FrequencyLists["Passwords"] = GetStringListFromAsset(passwordsFilePath, "Passwords")
Lists["MaleNames"] = getStringListFromAsset(maleFilePath, "MaleNames")
Lists["FemaleNames"] = getStringListFromAsset(femaleFilePath, "FemaleNames")
Lists["Surname"] = getStringListFromAsset(surnameFilePath, "Surname")
Lists["English"] = getStringListFromAsset(englishFilePath, "English")
Lists["Passwords"] = getStringListFromAsset(passwordsFilePath, "Passwords")

}
func getAsset(name string) []byte {
data, err := zxcvbn_data.Asset(name)
data, err := data.Asset(name)
if err != nil {
panic("Error getting asset " + name)
}

return data
}
func GetStringListFromAsset(data []byte, name string) FrequencyList {
func getStringListFromAsset(data []byte, name string) List {

var tempList FrequencyList
var tempList List
err := json.Unmarshal(data, &tempList)
if err != nil {
log.Fatal(err)
Expand Down
4 changes: 4 additions & 0 deletions match/match.go
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package match

//Matches is an alies for []Match used for sorting
type Matches []Match

func (s Matches) Len() int {
Expand All @@ -18,6 +19,7 @@ func (s Matches) Less(i, j int) bool {
}
}

// Match represents different matches
type Match struct {
Pattern string
I, J int
Expand All @@ -26,6 +28,7 @@ type Match struct {
Entropy float64
}

//DateMatch is specifilly a match for type date
type DateMatch struct {
Pattern string
I, J int
Expand All @@ -34,6 +37,7 @@ type DateMatch struct {
Day, Month, Year int64
}

//Matcher are a func and ID that can be used to match different passwords
type Matcher struct {
MatchingFunc func(password string) []Match
ID string
Expand Down
Loading

0 comments on commit 953e4e2

Please sign in to comment.