diff --git a/zxcvbn_test.go b/zxcvbn_test.go new file mode 100644 index 0000000..cc0369d --- /dev/null +++ b/zxcvbn_test.go @@ -0,0 +1,70 @@ +package zxcvbn + +import ( + "bytes" + "encoding/json" + "fmt" + "math/rand" + "os/exec" + "testing" + "testing/quick" + "time" +) + +func TestPasswordStrength(t *testing.T) { + cfg := &quick.Config{Rand: rand.New(rand.NewSource(time.Now().Unix()))} + err := quick.CheckEqual(GoPasswordStrength, PythonPasswordStrength, cfg) + if err != nil { + t.Error(err) + } +} + +func GoPasswordStrength(password string, userInputs []string) float64 { + return PasswordStrength(password, userInputs).Entropy +} + +func PythonPasswordStrength(password string, userInputs []string) float64 { + cmd := exec.Command("python", append([]string{"-", password}, userInputs...)...) + cmd.Stdin = bytes.NewBufferString(py) + + o, err := cmd.CombinedOutput() + if err != nil { + fmt.Println("outErr:", err) + } + + var pmatch pyMatch + if err := json.Unmarshal(o, &pmatch); err != nil { + fmt.Println("json:", err) + } + + return pmatch.Entropy +} + +const py = `import zxcvbn +import json +import sys + +print json.dumps(zxcvbn.password_strength(sys.argv[1], sys.argv[2:len(sys.argv)])) +` + +type pyMatch struct { + CalcTime float64 `json:"calc_time"` + CrackTime float64 `json:"crack_time"` + CrackTimeDisplay string `json:"crack_time_display"` + Entropy float64 `json:"entropy"` + MatchSequence []struct { + BaseEntropy float64 `json:"base_entropy"` + DictionaryName string `json:"dictionary_name"` + Entropy float64 `json:"entropy"` + I int64 `json:"i"` + J int64 `json:"j"` + L33tEntropy float64 `json:"l33t_entropy"` + MatchedWord string `json:"matched_word"` + Pattern string `json:"pattern"` + Rank int64 `json:"rank"` + Token string `json:"token"` + UppercaseEntropy float64 `json:"uppercase_entropy"` + } `json:"match_sequence"` + Password string `json:"password"` + Score float64 `json:"score"` +}