fat
This commit is contained in:
parent
e3fb346bcb
commit
7fa8f55be0
|
@ -1,20 +1,20 @@
|
||||||
package adjacency
|
package adjacency
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
// "fmt"
|
"log"
|
||||||
|
// "fmt"
|
||||||
"github.com/nbutton23/zxcvbn-go/data"
|
"github.com/nbutton23/zxcvbn-go/data"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
type AdjacencyGraph struct {
|
type AdjacencyGraph struct {
|
||||||
Graph map[string][]string
|
Graph map[string][]string
|
||||||
averageDegree float64
|
averageDegree float64
|
||||||
Name string
|
Name string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var AdjacencyGph = make(map[string]AdjacencyGraph)
|
||||||
|
|
||||||
var AdjacencyGph = make(map[string]AdjacencyGraph);
|
|
||||||
func init() {
|
func init() {
|
||||||
log.SetFlags(log.Lshortfile)
|
log.SetFlags(log.Lshortfile)
|
||||||
AdjacencyGph["qwerty"] = BuildQwerty()
|
AdjacencyGph["qwerty"] = BuildQwerty()
|
||||||
|
@ -54,7 +54,7 @@ func BuildMacKeypad() AdjacencyGraph {
|
||||||
|
|
||||||
func GetAdjancencyGraphFromFile(data []byte, name string) AdjacencyGraph {
|
func GetAdjancencyGraphFromFile(data []byte, name string) AdjacencyGraph {
|
||||||
|
|
||||||
var graph AdjacencyGraph;
|
var graph AdjacencyGraph
|
||||||
err := json.Unmarshal(data, &graph)
|
err := json.Unmarshal(data, &graph)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
@ -66,7 +66,7 @@ func GetAdjancencyGraphFromFile(data []byte, name string) AdjacencyGraph {
|
||||||
//on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1.
|
//on qwerty, 'g' has degree 6, being adjacent to 'ftyhbv'. '\' has degree 1.
|
||||||
//this calculates the average over all keys.
|
//this calculates the average over all keys.
|
||||||
//TODO double check that i ported this correctly scoring.coffee ln 5
|
//TODO double check that i ported this correctly scoring.coffee ln 5
|
||||||
func (adjGrp AdjacencyGraph) CalculateAvgDegree() (float64) {
|
func (adjGrp AdjacencyGraph) CalculateAvgDegree() float64 {
|
||||||
if adjGrp.averageDegree != float64(0) {
|
if adjGrp.averageDegree != float64(0) {
|
||||||
return adjGrp.averageDegree
|
return adjGrp.averageDegree
|
||||||
}
|
}
|
||||||
|
@ -83,8 +83,7 @@ func (adjGrp AdjacencyGraph) CalculateAvgDegree() (float64) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
adjGrp.averageDegree = avg/count
|
adjGrp.averageDegree = avg / count
|
||||||
|
|
||||||
return adjGrp.averageDegree
|
return adjGrp.averageDegree
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
158
data/bindata.go
158
data/bindata.go
|
@ -19,11 +19,11 @@ import (
|
||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"strings"
|
|
||||||
"os"
|
|
||||||
"time"
|
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
func bindataRead(data []byte, name string) ([]byte, error) {
|
func bindataRead(data []byte, name string) ([]byte, error) {
|
||||||
|
@ -52,9 +52,9 @@ type asset struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type bindataFileInfo struct {
|
type bindataFileInfo struct {
|
||||||
name string
|
name string
|
||||||
size int64
|
size int64
|
||||||
mode os.FileMode
|
mode os.FileMode
|
||||||
modTime time.Time
|
modTime time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -93,7 +93,7 @@ func dataDvorakJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,7 +113,7 @@ func dataEnglishJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,7 +133,7 @@ func dataFemalenamesJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -153,7 +153,7 @@ func dataKeypadJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,7 +173,7 @@ func dataL33tJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444170193, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -193,7 +193,7 @@ func dataMackeypadJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -213,7 +213,7 @@ func dataMalenamesJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -233,7 +233,7 @@ func dataPasswordsJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -253,7 +253,7 @@ func dataQwertyJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -273,7 +273,7 @@ func dataSurnamesJson() (*asset, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
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(1444169890, 0)}
|
||||||
a := &asset{bytes: bytes, info: info}
|
a := &asset{bytes: bytes, info: info}
|
||||||
return a, nil
|
return a, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -296,7 +296,7 @@ func Asset(name string) ([]byte, error) {
|
||||||
// It simplifies safe initialization of global variables.
|
// It simplifies safe initialization of global variables.
|
||||||
func MustAsset(name string) []byte {
|
func MustAsset(name string) []byte {
|
||||||
a, err := Asset(name)
|
a, err := Asset(name)
|
||||||
if (err != nil) {
|
if err != nil {
|
||||||
panic("asset: Asset(" + name + "): " + err.Error())
|
panic("asset: Asset(" + name + "): " + err.Error())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -329,16 +329,16 @@ func AssetNames() []string {
|
||||||
|
|
||||||
// _bindata is a table, holding each asset generator, mapped to its name.
|
// _bindata is a table, holding each asset generator, mapped to its name.
|
||||||
var _bindata = map[string]func() (*asset, error){
|
var _bindata = map[string]func() (*asset, error){
|
||||||
"data/Dvorak.json": dataDvorakJson,
|
"data/Dvorak.json": dataDvorakJson,
|
||||||
"data/English.json": dataEnglishJson,
|
"data/English.json": dataEnglishJson,
|
||||||
"data/FemaleNames.json": dataFemalenamesJson,
|
"data/FemaleNames.json": dataFemalenamesJson,
|
||||||
"data/Keypad.json": dataKeypadJson,
|
"data/Keypad.json": dataKeypadJson,
|
||||||
"data/L33t.json": dataL33tJson,
|
"data/L33t.json": dataL33tJson,
|
||||||
"data/MacKeypad.json": dataMackeypadJson,
|
"data/MacKeypad.json": dataMackeypadJson,
|
||||||
"data/MaleNames.json": dataMalenamesJson,
|
"data/MaleNames.json": dataMalenamesJson,
|
||||||
"data/Passwords.json": dataPasswordsJson,
|
"data/Passwords.json": dataPasswordsJson,
|
||||||
"data/Qwerty.json": dataQwertyJson,
|
"data/Qwerty.json": dataQwertyJson,
|
||||||
"data/Surnames.json": dataSurnamesJson,
|
"data/Surnames.json": dataSurnamesJson,
|
||||||
}
|
}
|
||||||
|
|
||||||
// AssetDir returns the file names below a certain
|
// AssetDir returns the file names below a certain
|
||||||
|
@ -377,78 +377,68 @@ func AssetDir(name string) ([]string, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
type bintree struct {
|
type bintree struct {
|
||||||
Func func() (*asset, error)
|
Func func() (*asset, error)
|
||||||
Children map[string]*bintree
|
Children map[string]*bintree
|
||||||
}
|
}
|
||||||
|
|
||||||
var _bintree = &bintree{nil, map[string]*bintree{
|
var _bintree = &bintree{nil, map[string]*bintree{
|
||||||
"data": &bintree{nil, map[string]*bintree{
|
"data": &bintree{nil, map[string]*bintree{
|
||||||
"Dvorak.json": &bintree{dataDvorakJson, map[string]*bintree{
|
"Dvorak.json": &bintree{dataDvorakJson, map[string]*bintree{}},
|
||||||
}},
|
"English.json": &bintree{dataEnglishJson, map[string]*bintree{}},
|
||||||
"English.json": &bintree{dataEnglishJson, map[string]*bintree{
|
"FemaleNames.json": &bintree{dataFemalenamesJson, map[string]*bintree{}},
|
||||||
}},
|
"Keypad.json": &bintree{dataKeypadJson, map[string]*bintree{}},
|
||||||
"FemaleNames.json": &bintree{dataFemalenamesJson, map[string]*bintree{
|
"L33t.json": &bintree{dataL33tJson, map[string]*bintree{}},
|
||||||
}},
|
"MacKeypad.json": &bintree{dataMackeypadJson, map[string]*bintree{}},
|
||||||
"Keypad.json": &bintree{dataKeypadJson, map[string]*bintree{
|
"MaleNames.json": &bintree{dataMalenamesJson, map[string]*bintree{}},
|
||||||
}},
|
"Passwords.json": &bintree{dataPasswordsJson, map[string]*bintree{}},
|
||||||
"L33t.json": &bintree{dataL33tJson, map[string]*bintree{
|
"Qwerty.json": &bintree{dataQwertyJson, map[string]*bintree{}},
|
||||||
}},
|
"Surnames.json": &bintree{dataSurnamesJson, map[string]*bintree{}},
|
||||||
"MacKeypad.json": &bintree{dataMackeypadJson, map[string]*bintree{
|
|
||||||
}},
|
|
||||||
"MaleNames.json": &bintree{dataMalenamesJson, map[string]*bintree{
|
|
||||||
}},
|
|
||||||
"Passwords.json": &bintree{dataPasswordsJson, map[string]*bintree{
|
|
||||||
}},
|
|
||||||
"Qwerty.json": &bintree{dataQwertyJson, map[string]*bintree{
|
|
||||||
}},
|
|
||||||
"Surnames.json": &bintree{dataSurnamesJson, map[string]*bintree{
|
|
||||||
}},
|
|
||||||
}},
|
}},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
// RestoreAsset restores an asset under the given directory
|
// RestoreAsset restores an asset under the given directory
|
||||||
func RestoreAsset(dir, name string) error {
|
func RestoreAsset(dir, name string) error {
|
||||||
data, err := Asset(name)
|
data, err := Asset(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
info, err := AssetInfo(name)
|
info, err := AssetInfo(name)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
err = os.MkdirAll(_filePath(dir, filepath.Dir(name)), os.FileMode(0755))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
err = ioutil.WriteFile(_filePath(dir, name), data, info.Mode())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
err = os.Chtimes(_filePath(dir, name), info.ModTime(), info.ModTime())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// RestoreAssets restores an asset under the given directory recursively
|
// RestoreAssets restores an asset under the given directory recursively
|
||||||
func RestoreAssets(dir, name string) error {
|
func RestoreAssets(dir, name string) error {
|
||||||
children, err := AssetDir(name)
|
children, err := AssetDir(name)
|
||||||
// File
|
// File
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return RestoreAsset(dir, name)
|
return RestoreAsset(dir, name)
|
||||||
}
|
}
|
||||||
// Dir
|
// Dir
|
||||||
for _, child := range children {
|
for _, child := range children {
|
||||||
err = RestoreAssets(dir, filepath.Join(name, child))
|
err = RestoreAssets(dir, filepath.Join(name, child))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func _filePath(dir, name string) string {
|
func _filePath(dir, name string) string {
|
||||||
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
cannonicalName := strings.Replace(name, "\\", "/", -1)
|
||||||
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
return filepath.Join(append([]string{dir}, strings.Split(cannonicalName, "/")...)...)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
package frequency
|
package frequency
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"log"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"github.com/nbutton23/zxcvbn-go/data"
|
"github.com/nbutton23/zxcvbn-go/data"
|
||||||
|
"log"
|
||||||
)
|
)
|
||||||
|
|
||||||
type FrequencyList struct {
|
type FrequencyList struct {
|
||||||
|
@ -11,6 +12,7 @@ type FrequencyList struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
var FrequencyLists = make(map[string]FrequencyList)
|
var FrequencyLists = make(map[string]FrequencyList)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
maleFilePath := getAsset("data/MaleNames.json")
|
maleFilePath := getAsset("data/MaleNames.json")
|
||||||
femaleFilePath := getAsset("data/FemaleNames.json")
|
femaleFilePath := getAsset("data/FemaleNames.json")
|
||||||
|
@ -35,7 +37,7 @@ func getAsset(name string) []byte {
|
||||||
}
|
}
|
||||||
func GetStringListFromAsset(data []byte, name string) FrequencyList {
|
func GetStringListFromAsset(data []byte, name string) FrequencyList {
|
||||||
|
|
||||||
var tempList FrequencyList;
|
var tempList FrequencyList
|
||||||
err := json.Unmarshal(data, &tempList)
|
err := json.Unmarshal(data, &tempList)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
package match
|
package match
|
||||||
|
|
||||||
type Matches []Match
|
type Matches []Match
|
||||||
func (s Matches)Len() int {
|
|
||||||
|
func (s Matches) Len() int {
|
||||||
return len(s)
|
return len(s)
|
||||||
}
|
}
|
||||||
func (s Matches)Swap(i, j int) {
|
func (s Matches) Swap(i, j int) {
|
||||||
s[i], s[j] = s[j], s[i]
|
s[i], s[j] = s[j], s[i]
|
||||||
}
|
}
|
||||||
func (s Matches) Less(i, j int) bool {
|
func (s Matches) Less(i, j int) bool {
|
||||||
|
@ -16,19 +17,20 @@ func (s Matches) Less(i, j int) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type Match struct {
|
type Match struct {
|
||||||
Pattern string
|
Pattern string
|
||||||
I, J int
|
I, J int
|
||||||
Token string
|
Token string
|
||||||
MatchedWord string
|
MatchedWord string
|
||||||
Rank float64
|
Rank float64
|
||||||
DictionaryName string
|
DictionaryName string
|
||||||
DictionaryLength int
|
DictionaryLength int
|
||||||
Ascending bool
|
Ascending bool
|
||||||
Turns int
|
Turns int
|
||||||
ShiftedCount int
|
ShiftedCount int
|
||||||
Entropy float64
|
Entropy float64
|
||||||
RepeatedChar string
|
RepeatedChar string
|
||||||
}
|
}
|
||||||
|
|
||||||
type DateMatch struct {
|
type DateMatch struct {
|
||||||
|
@ -37,5 +39,4 @@ type DateMatch struct {
|
||||||
Token string
|
Token string
|
||||||
Separator string
|
Separator string
|
||||||
Day, Month, Year int64
|
Day, Month, Year int64
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,37 +1,37 @@
|
||||||
package matching
|
package matching
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strings"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/frequency"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/adjacency"
|
"github.com/nbutton23/zxcvbn-go/adjacency"
|
||||||
|
"github.com/nbutton23/zxcvbn-go/frequency"
|
||||||
"github.com/nbutton23/zxcvbn-go/match"
|
"github.com/nbutton23/zxcvbn-go/match"
|
||||||
|
"regexp"
|
||||||
"sort"
|
"sort"
|
||||||
// "github.com/deckarep/golang-set"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
// "github.com/deckarep/golang-set"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
DICTIONARY_MATCHERS []func(password string) []match.Match
|
DICTIONARY_MATCHERS []func(password string) []match.Match
|
||||||
MATCHERS []func(password string) []match.Match
|
MATCHERS []func(password string) []match.Match
|
||||||
ADJACENCY_GRAPHS []adjacency.AdjacencyGraph;
|
ADJACENCY_GRAPHS []adjacency.AdjacencyGraph
|
||||||
KEYBOARD_STARTING_POSITIONS int
|
KEYBOARD_STARTING_POSITIONS int
|
||||||
KEYBOARD_AVG_DEGREE float64
|
KEYBOARD_AVG_DEGREE float64
|
||||||
KEYPAD_STARTING_POSITIONS int
|
KEYPAD_STARTING_POSITIONS int
|
||||||
KEYPAD_AVG_DEGREE float64
|
KEYPAD_AVG_DEGREE float64
|
||||||
L33T_TABLE adjacency.AdjacencyGraph
|
L33T_TABLE adjacency.AdjacencyGraph
|
||||||
|
|
||||||
SEQUENCES map[string]string
|
SEQUENCES map[string]string
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
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_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}))`
|
DATE_RX_YEAR_PREFIX string = `((19\d{2}|200\d|201\d|\d{2})(\s|-|/|\\|_|\.)(\d{1,2})(\s|-|/|\\|_|\.)(\d{1,2}))`
|
||||||
DATE_WITHOUT_SEP_MATCH string = `\d{4,8}`
|
DATE_WITHOUT_SEP_MATCH string = `\d{4,8}`
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
loadFrequencyList()
|
loadFrequencyList()
|
||||||
}
|
}
|
||||||
|
|
||||||
func Omnimatch(password string, userInputs []string) (matches []match.Match) {
|
func Omnimatch(password string, userInputs []string) (matches []match.Match) {
|
||||||
|
@ -83,10 +83,8 @@ func loadFrequencyList() {
|
||||||
MATCHERS = append(MATCHERS, repeatMatch)
|
MATCHERS = append(MATCHERS, repeatMatch)
|
||||||
MATCHERS = append(MATCHERS, SequenceMatch)
|
MATCHERS = append(MATCHERS, SequenceMatch)
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []match.Match {
|
func buildDictMatcher(dictName string, rankedDict map[string]int) func(password string) []match.Match {
|
||||||
return func(password string) []match.Match {
|
return func(password string) []match.Match {
|
||||||
matches := dictionaryMatch(password, dictName, rankedDict)
|
matches := dictionaryMatch(password, dictName, rankedDict)
|
||||||
|
@ -105,15 +103,15 @@ func dictionaryMatch(password string, dictionaryName string, rankedDict map[stri
|
||||||
|
|
||||||
for i := 0; i < length; i++ {
|
for i := 0; i < length; i++ {
|
||||||
for j := i; j < length; j++ {
|
for j := i; j < length; j++ {
|
||||||
word := pwLower[i:j + 1]
|
word := pwLower[i : j+1]
|
||||||
if val, ok := rankedDict[word]; ok {
|
if val, ok := rankedDict[word]; ok {
|
||||||
results = append(results, match.Match{Pattern:"dictionary",
|
results = append(results, match.Match{Pattern: "dictionary",
|
||||||
DictionaryName:dictionaryName,
|
DictionaryName: dictionaryName,
|
||||||
I:i,
|
I: i,
|
||||||
J:j,
|
J: j,
|
||||||
Token:password[i:j + 1],
|
Token: password[i : j+1],
|
||||||
MatchedWord:word,
|
MatchedWord: word,
|
||||||
Rank:float64(val)})
|
Rank: float64(val)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -160,11 +158,10 @@ func DateSepMatch(password string) []match.DateMatch {
|
||||||
day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
|
day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
|
||||||
month, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
month, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
||||||
year, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
year, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
||||||
match := match.DateMatch{Day:day, Month:month, Year:year, Separator:splitV[0][5], I:i, J:j }
|
match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j}
|
||||||
matches = append(matches, match)
|
matches = append(matches, match)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
matcher = regexp.MustCompile(DATE_RX_YEAR_PREFIX)
|
matcher = regexp.MustCompile(DATE_RX_YEAR_PREFIX)
|
||||||
for _, v := range matcher.FindAllString(password, len(password)) {
|
for _, v := range matcher.FindAllString(password, len(password)) {
|
||||||
splitV := matcher.FindAllStringSubmatch(v, len(v))
|
splitV := matcher.FindAllStringSubmatch(v, len(v))
|
||||||
|
@ -173,7 +170,7 @@ func DateSepMatch(password string) []match.DateMatch {
|
||||||
day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
|
day, _ := strconv.ParseInt(splitV[0][4], 10, 16)
|
||||||
month, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
month, _ := strconv.ParseInt(splitV[0][6], 10, 16)
|
||||||
year, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
year, _ := strconv.ParseInt(splitV[0][2], 10, 16)
|
||||||
match := match.DateMatch{Day:day, Month:month, Year:year, Separator:splitV[0][5], I:i, J:j }
|
match := match.DateMatch{Day: day, Month: month, Year: year, Separator: splitV[0][5], I: i, J: j}
|
||||||
matches = append(matches, match)
|
matches = append(matches, match)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -190,11 +187,13 @@ func DateSepMatch(password string) []match.DateMatch {
|
||||||
return out
|
return out
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type DateMatchCandidate struct {
|
type DateMatchCandidate struct {
|
||||||
DayMonth string
|
DayMonth string
|
||||||
Year string
|
Year string
|
||||||
I, J int
|
I, J int
|
||||||
}
|
}
|
||||||
|
|
||||||
//TODO I think Im doing this wrong.
|
//TODO I think Im doing this wrong.
|
||||||
func dateWithoutSepMatch(password string) (matches []match.DateMatch) {
|
func dateWithoutSepMatch(password string) (matches []match.DateMatch) {
|
||||||
matcher := regexp.MustCompile(DATE_WITHOUT_SEP_MATCH)
|
matcher := regexp.MustCompile(DATE_WITHOUT_SEP_MATCH)
|
||||||
|
@ -210,14 +209,14 @@ func dateWithoutSepMatch(password string) (matches []match.DateMatch) {
|
||||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j))
|
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[2:], v[0:2], i, j))
|
||||||
|
|
||||||
//2-digityear suffix
|
//2-digityear suffix
|
||||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex - 2], v[lastIndex - 2:], i, j))
|
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-2], v[lastIndex-2:], i, j))
|
||||||
}
|
}
|
||||||
if length >= 6 {
|
if length >= 6 {
|
||||||
//4-digit year prefix
|
//4-digit year prefix
|
||||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j))
|
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[4:], v[0:4], i, j))
|
||||||
|
|
||||||
//4-digit year sufix
|
//4-digit year sufix
|
||||||
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex - 4], v[lastIndex - 4:], i, j))
|
candidatesRoundOne = append(candidatesRoundOne, buildDateMatchCandidate(v[0:lastIndex-4], v[lastIndex-4:], i, j))
|
||||||
}
|
}
|
||||||
|
|
||||||
var candidatesRoundTwo []match.DateMatch
|
var candidatesRoundTwo []match.DateMatch
|
||||||
|
@ -232,7 +231,7 @@ func dateWithoutSepMatch(password string) (matches []match.DateMatch) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildDateMatchCandidate(dayMonth, year string, i, j int) DateMatchCandidate {
|
func buildDateMatchCandidate(dayMonth, year string, i, j int) DateMatchCandidate {
|
||||||
return DateMatchCandidate{DayMonth: dayMonth, Year:year, I:i, J:j}
|
return DateMatchCandidate{DayMonth: dayMonth, Year: year, I: i, J: j}
|
||||||
}
|
}
|
||||||
|
|
||||||
func buildDateMatchCandidateTwo(day, month byte, year string, i, j int) match.DateMatch {
|
func buildDateMatchCandidateTwo(day, month byte, year string, i, j int) match.DateMatch {
|
||||||
|
@ -242,10 +241,9 @@ func buildDateMatchCandidateTwo(day, month byte, year string, i, j int) match.Da
|
||||||
intMonth, _ := strconv.ParseInt(sMonth, 10, 16)
|
intMonth, _ := strconv.ParseInt(sMonth, 10, 16)
|
||||||
intYear, _ := strconv.ParseInt(year, 10, 16)
|
intYear, _ := strconv.ParseInt(year, 10, 16)
|
||||||
|
|
||||||
return match.DateMatch{Day:intDay, Month:intMonth, Year:intYear, I:i, J:j}
|
return match.DateMatch{Day: intDay, Month: intMonth, Year: intYear, I: i, J: j}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func spatialMatch(password string) (matches []match.Match) {
|
func spatialMatch(password string) (matches []match.Match) {
|
||||||
for _, graph := range ADJACENCY_GRAPHS {
|
for _, graph := range ADJACENCY_GRAPHS {
|
||||||
matches = append(matches, spatialMatchHelper(password, graph)...)
|
matches = append(matches, spatialMatchHelper(password, graph)...)
|
||||||
|
@ -254,14 +252,14 @@ func spatialMatch(password string) (matches []match.Match) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matches []match.Match) {
|
func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matches []match.Match) {
|
||||||
for i := 0; i < len(password) - 1; {
|
for i := 0; i < len(password)-1; {
|
||||||
j := i + 1
|
j := i + 1
|
||||||
lastDirection := -99 //and int that it should never be!
|
lastDirection := -99 //and int that it should never be!
|
||||||
turns := 0
|
turns := 0
|
||||||
shiftedCount := 0
|
shiftedCount := 0
|
||||||
|
|
||||||
for ;; {
|
for {
|
||||||
prevChar := password[j - 1]
|
prevChar := password[j-1]
|
||||||
found := false
|
found := false
|
||||||
foundDirection := -1
|
foundDirection := -1
|
||||||
curDirection := -1
|
curDirection := -1
|
||||||
|
@ -300,8 +298,8 @@ func spatialMatchHelper(password string, graph adjacency.AdjacencyGraph) (matche
|
||||||
} else {
|
} else {
|
||||||
// otherwise push the pattern discovered so far, if any...
|
// otherwise push the pattern discovered so far, if any...
|
||||||
// don't consider length 1 or 2 chains.
|
// don't consider length 1 or 2 chains.
|
||||||
if j - i > 2 {
|
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 })
|
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
|
i = j
|
||||||
|
@ -364,11 +362,11 @@ func repeatMatch(password string) []match.Match {
|
||||||
iPos := i - currentStreak
|
iPos := i - currentStreak
|
||||||
jPos := i - 1
|
jPos := i - 1
|
||||||
matches = append(matches, match.Match{
|
matches = append(matches, match.Match{
|
||||||
Pattern:"repeat",
|
Pattern: "repeat",
|
||||||
I:iPos,
|
I: iPos,
|
||||||
J:jPos,
|
J: jPos,
|
||||||
Token:password[iPos:jPos + 1],
|
Token: password[iPos : jPos+1],
|
||||||
RepeatedChar:prev})
|
RepeatedChar: prev})
|
||||||
currentStreak = 1
|
currentStreak = 1
|
||||||
} else {
|
} else {
|
||||||
currentStreak = 1
|
currentStreak = 1
|
||||||
|
@ -381,11 +379,11 @@ func repeatMatch(password string) []match.Match {
|
||||||
iPos := i - currentStreak + 1
|
iPos := i - currentStreak + 1
|
||||||
jPos := i
|
jPos := i
|
||||||
matches = append(matches, match.Match{
|
matches = append(matches, match.Match{
|
||||||
Pattern:"repeat",
|
Pattern: "repeat",
|
||||||
I:iPos,
|
I: iPos,
|
||||||
J:jPos,
|
J: jPos,
|
||||||
Token:password[iPos:jPos + 1],
|
Token: password[iPos : jPos+1],
|
||||||
RepeatedChar:prev})
|
RepeatedChar: prev})
|
||||||
}
|
}
|
||||||
return matches
|
return matches
|
||||||
}
|
}
|
||||||
|
@ -419,22 +417,22 @@ func SequenceMatch(password string) []match.Match {
|
||||||
}
|
}
|
||||||
|
|
||||||
if seq != "" {
|
if seq != "" {
|
||||||
for ;; {
|
for {
|
||||||
var prevN, curN int
|
var prevN, curN int
|
||||||
if j < len(password) {
|
if j < len(password) {
|
||||||
prevChar, curChar := password[j - 1], password[j]
|
prevChar, curChar := password[j-1], password[j]
|
||||||
prevN, curN = strings.Index(seq, string(prevChar)), strings.Index(seq, string(curChar))
|
prevN, curN = strings.Index(seq, string(prevChar)), strings.Index(seq, string(curChar))
|
||||||
}
|
}
|
||||||
|
|
||||||
if j == len(password) || curN - prevN != seqDirection {
|
if j == len(password) || curN-prevN != seqDirection {
|
||||||
if j - i > 2 {
|
if j-i > 2 {
|
||||||
matches = append(matches, match.Match{Pattern:"sequence",
|
matches = append(matches, match.Match{Pattern: "sequence",
|
||||||
I:i,
|
I: i,
|
||||||
J:j-1,
|
J: j - 1,
|
||||||
Token:password[i:j],
|
Token: password[i:j],
|
||||||
DictionaryName:seqName,
|
DictionaryName: seqName,
|
||||||
DictionaryLength: len(seq),
|
DictionaryLength: len(seq),
|
||||||
Ascending:(seqDirection == 1)})
|
Ascending: (seqDirection == 1)})
|
||||||
}
|
}
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,32 +1,31 @@
|
||||||
package scoring
|
package scoring
|
||||||
import (
|
|
||||||
"github.com/nbutton23/zxcvbn-go/match"
|
|
||||||
"unicode"
|
|
||||||
"fmt"
|
|
||||||
"math"
|
|
||||||
"sort"
|
|
||||||
"regexp"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/utils/math"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/matching"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/adjacency"
|
|
||||||
)
|
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"github.com/nbutton23/zxcvbn-go/adjacency"
|
||||||
|
"github.com/nbutton23/zxcvbn-go/match"
|
||||||
|
"github.com/nbutton23/zxcvbn-go/matching"
|
||||||
|
"github.com/nbutton23/zxcvbn-go/utils/math"
|
||||||
|
"math"
|
||||||
|
"regexp"
|
||||||
|
"sort"
|
||||||
|
"unicode"
|
||||||
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
START_UPPER string = `^[A-Z][^A-Z]+$`
|
START_UPPER string = `^[A-Z][^A-Z]+$`
|
||||||
END_UPPER string = `^[^A-Z]+[A-Z]$'`
|
END_UPPER string = `^[^A-Z]+[A-Z]$'`
|
||||||
ALL_UPPER string = `^[A-Z]+$`
|
ALL_UPPER string = `^[A-Z]+$`
|
||||||
|
|
||||||
//for a hash function like bcrypt/scrypt/PBKDF2, 10ms per guess is a safe lower bound.
|
//for a hash function like bcrypt/scrypt/PBKDF2, 10ms per guess is a safe lower bound.
|
||||||
//(usually a guess would take longer -- this assumes fast hardware and a small work factor.)
|
//(usually a guess would take longer -- this assumes fast hardware and a small work factor.)
|
||||||
//adjust for your site accordingly if you use another hash function, possibly by
|
//adjust for your site accordingly if you use another hash function, possibly by
|
||||||
//several orders of magnitude!
|
//several orders of magnitude!
|
||||||
SINGLE_GUESS float64 = 0.010
|
SINGLE_GUESS float64 = 0.010
|
||||||
NUM_ATTACKERS float64 = 100 //Cores used to make guesses
|
NUM_ATTACKERS float64 = 100 //Cores used to make guesses
|
||||||
SECONDS_PER_GUESS float64 = SINGLE_GUESS / NUM_ATTACKERS
|
SECONDS_PER_GUESS float64 = SINGLE_GUESS / NUM_ATTACKERS
|
||||||
|
|
||||||
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type MinEntropyMatch struct {
|
type MinEntropyMatch struct {
|
||||||
Password string
|
Password string
|
||||||
Entropy float64
|
Entropy float64
|
||||||
|
@ -42,14 +41,14 @@ Returns minimum entropy
|
||||||
|
|
||||||
Takes a list of overlapping matches, returns the non-overlapping sublist with
|
Takes a list of overlapping matches, returns the non-overlapping sublist with
|
||||||
minimum entropy. O(nm) dp alg for length-n password with m candidate matches.
|
minimum entropy. O(nm) dp alg for length-n password with m candidate matches.
|
||||||
*/
|
*/
|
||||||
func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntropyMatch {
|
func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntropyMatch {
|
||||||
bruteforceCardinality := float64(calcBruteforceCardinality(password))
|
bruteforceCardinality := float64(calcBruteforceCardinality(password))
|
||||||
upToK := make([]float64, len(password))
|
upToK := make([]float64, len(password))
|
||||||
backPointers := make([]match.Match, len(password))
|
backPointers := make([]match.Match, len(password))
|
||||||
|
|
||||||
for k := 0; k < len(password); k++ {
|
for k := 0; k < len(password); k++ {
|
||||||
upToK[k] = get(upToK, k - 1) + math.Log2(bruteforceCardinality)
|
upToK[k] = get(upToK, k-1) + math.Log2(bruteforceCardinality)
|
||||||
|
|
||||||
for _, match := range matches {
|
for _, match := range matches {
|
||||||
if match.J != k {
|
if match.J != k {
|
||||||
|
@ -58,7 +57,7 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||||
|
|
||||||
i, j := match.I, match.J
|
i, j := match.I, match.J
|
||||||
// see if best entropy up to i-1 + entropy of match is less that current min at j
|
// see if best entropy up to i-1 + entropy of match is less that current min at j
|
||||||
upTo := get(upToK, i - 1)
|
upTo := get(upToK, i-1)
|
||||||
calculatedEntropy := calcEntropy(match)
|
calculatedEntropy := calcEntropy(match)
|
||||||
match.Entropy = calculatedEntropy
|
match.Entropy = calculatedEntropy
|
||||||
candidateEntropy := upTo + calculatedEntropy
|
candidateEntropy := upTo + calculatedEntropy
|
||||||
|
@ -81,7 +80,7 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||||
matchSequence = append(matchSequence, match)
|
matchSequence = append(matchSequence, match)
|
||||||
k = match.I - 1
|
k = match.I - 1
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
k--
|
k--
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -89,11 +88,11 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||||
sort.Sort(match.Matches(matchSequence))
|
sort.Sort(match.Matches(matchSequence))
|
||||||
|
|
||||||
makeBruteForecMatch := func(i, j int) match.Match {
|
makeBruteForecMatch := func(i, j int) match.Match {
|
||||||
return match.Match{Pattern:"bruteforce",
|
return match.Match{Pattern: "bruteforce",
|
||||||
I:i,
|
I: i,
|
||||||
J:j,
|
J: j,
|
||||||
Token:password[i:j + 1],
|
Token: password[i : j+1],
|
||||||
Entropy:math.Log2(math.Pow(bruteforceCardinality, float64(j - i)))}
|
Entropy: math.Log2(math.Pow(bruteforceCardinality, float64(j-i)))}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -101,30 +100,30 @@ func MinimumEntropyMatchSequence(password string, matches []match.Match) MinEntr
|
||||||
var matchSequenceCopy []match.Match
|
var matchSequenceCopy []match.Match
|
||||||
for _, match := range matchSequence {
|
for _, match := range matchSequence {
|
||||||
i, j := match.I, match.J
|
i, j := match.I, match.J
|
||||||
if i - k > 0 {
|
if i-k > 0 {
|
||||||
matchSequenceCopy = append(matchSequenceCopy, makeBruteForecMatch(k, i - 1))
|
matchSequenceCopy = append(matchSequenceCopy, makeBruteForecMatch(k, i-1))
|
||||||
}
|
}
|
||||||
k = j + 1
|
k = j + 1
|
||||||
matchSequenceCopy = append(matchSequenceCopy, match)
|
matchSequenceCopy = append(matchSequenceCopy, match)
|
||||||
}
|
}
|
||||||
|
|
||||||
if k < len(password) {
|
if k < len(password) {
|
||||||
matchSequenceCopy = append(matchSequenceCopy, makeBruteForecMatch(k, len(password) - 1))
|
matchSequenceCopy = append(matchSequenceCopy, makeBruteForecMatch(k, len(password)-1))
|
||||||
}
|
}
|
||||||
var minEntropy float64
|
var minEntropy float64
|
||||||
if len(password) == 0 {
|
if len(password) == 0 {
|
||||||
minEntropy = float64(0)
|
minEntropy = float64(0)
|
||||||
} else {
|
} else {
|
||||||
minEntropy = upToK[len(password) - 1 ]
|
minEntropy = upToK[len(password)-1]
|
||||||
}
|
}
|
||||||
|
|
||||||
crackTime := roundToXDigits(entropyToCrackTime(minEntropy), 3)
|
crackTime := roundToXDigits(entropyToCrackTime(minEntropy), 3)
|
||||||
return MinEntropyMatch{Password:password,
|
return MinEntropyMatch{Password: password,
|
||||||
Entropy:roundToXDigits(minEntropy, 3),
|
Entropy: roundToXDigits(minEntropy, 3),
|
||||||
MatchSequence:matchSequenceCopy,
|
MatchSequence: matchSequenceCopy,
|
||||||
CrackTime:crackTime,
|
CrackTime: crackTime,
|
||||||
CrackTimeDisplay:displayTime(crackTime),
|
CrackTimeDisplay: displayTime(crackTime),
|
||||||
Score:crackTimeToScore(crackTime)}
|
Score: crackTimeToScore(crackTime)}
|
||||||
|
|
||||||
}
|
}
|
||||||
func get(a []float64, i int) float64 {
|
func get(a []float64, i int) float64 {
|
||||||
|
@ -198,10 +197,10 @@ func spatialEntropy(match match.Match) float64 {
|
||||||
|
|
||||||
//TODO: Should this be <= or just < ?
|
//TODO: Should this be <= or just < ?
|
||||||
//Estimate the number of possible patterns w/ length L or less with t turns or less
|
//Estimate the number of possible patterns w/ length L or less with t turns or less
|
||||||
for i := float64(2); i <= length + 1; i++ {
|
for i := float64(2); i <= length+1; i++ {
|
||||||
possibleTurns := math.Min(float64(t), i - 1)
|
possibleTurns := math.Min(float64(t), i-1)
|
||||||
for j := float64(1); j <= possibleTurns + 1; j++ {
|
for j := float64(1); j <= possibleTurns+1; j++ {
|
||||||
x := zxcvbn_math.NChoseK(i - 1, j - 1) * s * math.Pow(d, j)
|
x := zxcvbn_math.NChoseK(i-1, j-1) * s * math.Pow(d, j)
|
||||||
possibilities += x
|
possibilities += x
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -214,8 +213,8 @@ func spatialEntropy(match match.Match) float64 {
|
||||||
possibilities = float64(0)
|
possibilities = float64(0)
|
||||||
U := length - S
|
U := length - S
|
||||||
|
|
||||||
for i := float64(0); i < math.Min(S, U) + 1; i++ {
|
for i := float64(0); i < math.Min(S, U)+1; i++ {
|
||||||
possibilities += zxcvbn_math.NChoseK(S + U, i)
|
possibilities += zxcvbn_math.NChoseK(S+U, i)
|
||||||
}
|
}
|
||||||
|
|
||||||
entropy += math.Log2(possibilities)
|
entropy += math.Log2(possibilities)
|
||||||
|
@ -231,7 +230,7 @@ func sequenceEntropy(match match.Match) float64 {
|
||||||
} else {
|
} else {
|
||||||
baseEntropy = math.Log2(float64(match.DictionaryLength))
|
baseEntropy = math.Log2(float64(match.DictionaryLength))
|
||||||
if unicode.IsUpper(rune(firstChar)) {
|
if unicode.IsUpper(rune(firstChar)) {
|
||||||
baseEntropy ++
|
baseEntropy++
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -321,15 +320,15 @@ func displayTime(seconds float64) string {
|
||||||
if seconds < minute {
|
if seconds < minute {
|
||||||
return "instant"
|
return "instant"
|
||||||
} else if seconds < hour {
|
} else if seconds < hour {
|
||||||
return fmt.Sprintf(formater, (1 + math.Ceil(seconds / minute)), "minutes")
|
return fmt.Sprintf(formater, (1 + math.Ceil(seconds/minute)), "minutes")
|
||||||
} else if seconds < day {
|
} else if seconds < day {
|
||||||
return fmt.Sprintf(formater, (1 + math.Ceil(seconds / hour)), "hours")
|
return fmt.Sprintf(formater, (1 + math.Ceil(seconds/hour)), "hours")
|
||||||
} else if seconds < month {
|
} else if seconds < month {
|
||||||
return fmt.Sprintf(formater, (1 + math.Ceil(seconds / day)), "days")
|
return fmt.Sprintf(formater, (1 + math.Ceil(seconds/day)), "days")
|
||||||
} else if seconds < year {
|
} else if seconds < year {
|
||||||
return fmt.Sprintf(formater, (1 + math.Ceil(seconds / month)), "months")
|
return fmt.Sprintf(formater, (1 + math.Ceil(seconds/month)), "months")
|
||||||
}else if seconds < century {
|
} else if seconds < century {
|
||||||
return fmt.Sprintf(formater, (1 + math.Ceil(seconds / century)), "years")
|
return fmt.Sprintf(formater, (1 + math.Ceil(seconds/century)), "years")
|
||||||
} else {
|
} else {
|
||||||
return "centuries"
|
return "centuries"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package zxcvbn_math
|
package zxcvbn_math
|
||||||
|
|
||||||
import "math"
|
import "math"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
I am surprised that I have to define these. . . Maybe i just didn't look hard enough for a lib.
|
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
|
//http://blog.plover.com/math/choose.html
|
||||||
func NChoseK(n, k float64) float64 {
|
func NChoseK(n, k float64) float64 {
|
||||||
|
|
|
@ -3,8 +3,8 @@ package zxcvbn
|
||||||
import (
|
import (
|
||||||
"github.com/nbutton23/zxcvbn-go/matching"
|
"github.com/nbutton23/zxcvbn-go/matching"
|
||||||
"github.com/nbutton23/zxcvbn-go/scoring"
|
"github.com/nbutton23/zxcvbn-go/scoring"
|
||||||
"time"
|
|
||||||
"github.com/nbutton23/zxcvbn-go/utils/math"
|
"github.com/nbutton23/zxcvbn-go/utils/math"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
//func main() {
|
//func main() {
|
||||||
|
|
Loading…
Reference in New Issue