|
@@ -3,11 +3,10 @@ package main
|
|
|
import (
|
|
|
"flag"
|
|
|
"fmt"
|
|
|
- "github.com/trustelem/zxcvbn"
|
|
|
"math"
|
|
|
"os"
|
|
|
- "passphrase-entropy/packages/haveibeenpwned"
|
|
|
- "strings"
|
|
|
+ "github.com/trustelem/zxcvbn"
|
|
|
+ "github.com/chaosbunker/haveibeenpwned"
|
|
|
)
|
|
|
|
|
|
func contains(arr [3]string, str string) bool {
|
|
@@ -19,15 +18,7 @@ func contains(arr [3]string, str string) bool {
|
|
|
return false
|
|
|
}
|
|
|
|
|
|
-func myUsage() {
|
|
|
- fmt.Println("usage: passphrase-strength <command> [<args>]")
|
|
|
- fmt.Println("Available commands are: ")
|
|
|
- fmt.Println(" diceware Calculate strength of a diceware passphrase")
|
|
|
- fmt.Println(" random Calculate strength of a random string")
|
|
|
- fmt.Println(" invented Calculate strength of an invented passphrase")
|
|
|
-}
|
|
|
-
|
|
|
-func secondsToHuman(guesses float64) (result string) {
|
|
|
+func guessesToHuman(guesses float64) (result string) {
|
|
|
minute := float64(60)
|
|
|
hour := minute * 60
|
|
|
day := hour * 24
|
|
@@ -41,53 +32,62 @@ func secondsToHuman(guesses float64) (result string) {
|
|
|
} else if guesses < hour {
|
|
|
result = fmt.Sprintf("%d minutes", int(math.Round(guesses / minute)))
|
|
|
} else if guesses < day {
|
|
|
- result = fmt.Sprintf("%d hours", int(math.Round(guesses / hour)))
|
|
|
+ result = fmt.Sprintf("%d hours ", int(math.Round(guesses / hour)))
|
|
|
} else if guesses < month {
|
|
|
- result = fmt.Sprintf("%d days", int(math.Round(guesses / day)))
|
|
|
+ result = fmt.Sprintf("%d days ", int(math.Round(guesses / day)))
|
|
|
} else if guesses < year {
|
|
|
- result = fmt.Sprintf("%d months", int(math.Round(guesses / month)))
|
|
|
+ result = fmt.Sprintf("%d months ", int(math.Round(guesses / month)))
|
|
|
} else if guesses < century {
|
|
|
- result = fmt.Sprintf("%d years", int(math.Round(guesses / year)))
|
|
|
+ result = fmt.Sprintf("%d years ", int(math.Round(guesses / year)))
|
|
|
} else {
|
|
|
result = fmt.Sprintf("Centuries")
|
|
|
}
|
|
|
return
|
|
|
}
|
|
|
+type arrayFlags []string
|
|
|
+func (i *arrayFlags) String() string {
|
|
|
+ return "my string representation"
|
|
|
+}
|
|
|
|
|
|
+func (i *arrayFlags) Set(value string) error {
|
|
|
+ *i = append(*i, value)
|
|
|
+ return nil
|
|
|
+}
|
|
|
func main() {
|
|
|
- var passphrase, words string
|
|
|
+ var password string
|
|
|
var pwnedFlag, haveIBeenPwned bool
|
|
|
+ var words arrayFlags
|
|
|
var err error
|
|
|
|
|
|
- flag.StringVar(&passphrase,"password", "", "the password")
|
|
|
- flag.StringVar(&words, "words", "", "used words")
|
|
|
- flag.BoolVar(&pwnedFlag, "pwned", false, "check if password has been seen before")
|
|
|
+ flag.StringVar(&password,"password", "", "a password")
|
|
|
+ flag.Var(&words, "word", "used words, e.g. -password p4ssw0rd -word password")
|
|
|
+ flag.BoolVar(&pwnedFlag, "pwned", false, "check with haveibeenpwned API if password has been seen before")
|
|
|
flag.Parse()
|
|
|
|
|
|
- if len(os.Args) == 1 || passphrase == "" {
|
|
|
+ if len(os.Args) == 1 || password == "" {
|
|
|
flag.PrintDefaults()
|
|
|
return
|
|
|
}
|
|
|
|
|
|
if pwnedFlag == true {
|
|
|
- haveIBeenPwned, err = pwned.IsPasswordCompromised(passphrase)
|
|
|
+ haveIBeenPwned, err = pwned.IsPasswordCompromised(password)
|
|
|
+ fmt.Println(haveIBeenPwned)
|
|
|
}
|
|
|
|
|
|
if err != nil {
|
|
|
fmt.Println("Something went wrong.")
|
|
|
} else {
|
|
|
- userInput := strings.Fields(words)
|
|
|
- strength := zxcvbn.PasswordStrength(passphrase, userInput)
|
|
|
+ strength := zxcvbn.PasswordStrength(password, words)
|
|
|
guesses := strength.Guesses
|
|
|
- fmt.Printf("\nPassword:\t\t%s\n", passphrase)
|
|
|
+ fmt.Printf("\nPassword:\t\t%s\n", password)
|
|
|
fmt.Printf("Password strength:\t%d/4\n", strength.Score)
|
|
|
|
|
|
- fmt.Printf("Guesses Log10:\t\t%f\n", math.Log10(float64(guesses)))
|
|
|
+ fmt.Printf("Guesses Log10:\t\t%f\n", math.Log10(guesses))
|
|
|
fmt.Println("\nGuess times")
|
|
|
- fmt.Printf("100 / h:\t\t%s\t(throttled online attack)\n",secondsToHuman(guesses * (3600 / 100)))
|
|
|
- fmt.Printf("10 / s:\t\t%s\t(unthrottled online attack)\n",secondsToHuman(guesses/10))
|
|
|
- fmt.Printf("10k / s:\t\t%s\t(offline attack, slow hash, many cores)\n",secondsToHuman(guesses / 1e4))
|
|
|
- fmt.Printf("10b / s:\t\t%s\t(offline attack, slow hash, many cores)\n",secondsToHuman(guesses / 1e10))
|
|
|
+ fmt.Printf("100 / h:\t\t%s\t(throttled online attack)\n", guessesToHuman(guesses * (3600 / 100)))
|
|
|
+ fmt.Printf("10 / s:\t\t%s\t(unthrottled online attack)\n", guessesToHuman(guesses / 10))
|
|
|
+ fmt.Printf("10k / s:\t\t%s\t(offline attack, slow hash, many cores)\n", guessesToHuman(guesses / 1e4))
|
|
|
+ fmt.Printf("10b / s:\t\t%s\t(offline attack, slow hash, many cores)\n", guessesToHuman(guesses / 1e10))
|
|
|
}
|
|
|
if haveIBeenPwned == true {
|
|
|
fmt.Println("\nThis password has been compromised and should not be used.")
|