package main import ( "flag" "fmt" "math" "os" "strings" "passphrase-entropy/packages/haveibeenpwned" ) func contains(arr [3]string, str string) bool { for _, a := range arr { if a == str { return true } } return false } func myUsage() { fmt.Println("usage: passphrase-entropy []") fmt.Println("Available commands are: ") fmt.Println(" diceware Calculate entropy of a diceware passphrase") fmt.Println(" random Calculate entropy of a random string") fmt.Println(" invented Calculate entropy of an invented passphrase") } func main() { var charsets map[string]string var usedCharsets[] string var possibleSymbols int = 0 var haveIBeenPwned bool var passphrase string var err error charsets = make(map[string]string) charsets["Numbers"] = "0123456789" charsets["Lowercase"] = "abcdefghijklmnopqrstuvwxyz" charsets["Uppercase"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" charsets["Common Special Characters"] = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" charsets["Space"] = " " charsets["Extended ASCII"] = "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ" dicewareCommand := flag.NewFlagSet("diceware", flag.ExitOnError) dicewarePassphraseFlag := dicewareCommand.String("password", "", "the password") wordsFlag := dicewareCommand.Int("words", 0, "number of words in passphrase") dictSizeFlag := dicewareCommand.Int("dictSize", 0, "number of words in dictionary") delimiterFlag := dicewareCommand.String("delimiter", "", "delimiter used") randomCommand := flag.NewFlagSet("random", flag.ExitOnError) randomPassphraseFlag := randomCommand.String("password", "", "the password") randomPwnedFlag := randomCommand.Bool("pwned", false, "check if password has been seen before") inventedCommand := flag.NewFlagSet("invented", flag.ExitOnError) inventedPassphraseFlag := inventedCommand.String("password", "", "the password") inventedWords := inventedCommand.Int("words", 0, "number of words in invented passphrase") inventedPwnedFlag := inventedCommand.Bool("pwned", false, "check if password has been seen before") if len(os.Args) == 1 { myUsage() return } switch os.Args[1] { case "diceware": dicewareCommand.Parse(os.Args[2:]) case "random": randomCommand.Parse(os.Args[2:]) case "invented": inventedCommand.Parse(os.Args[2:]) default: myUsage() fmt.Printf("\n%q is not valid command.\n", os.Args[1]) os.Exit(2) } if *inventedPassphraseFlag != "" { passphrase = *inventedPassphraseFlag } else if *randomPassphraseFlag != "" { passphrase = *randomPassphraseFlag } else { passphrase = *dicewarePassphraseFlag } if dicewareCommand.Parsed() { if *wordsFlag == 0 { dicewareCommand.Usage() return } if *dictSizeFlag == 0 { dicewareCommand.Usage() return } if *delimiterFlag != "" { for key, value := range charsets { if strings.ContainsAny(*delimiterFlag, value) { *dictSizeFlag += len(value) usedCharsets = append(usedCharsets, key) } } } entropy := math.Log2(math.Pow(float64(*dictSizeFlag), float64(*wordsFlag))) fmt.Println("\nPassphrase entropy:", entropy) } if randomCommand.Parsed() { if *randomPassphraseFlag == "" { randomCommand.Usage() return } if *randomPwnedFlag == true { haveIBeenPwned, err = pwned.IsPasswordCompromised(passphrase) if haveIBeenPwned == true { fmt.Println("This password does not have any entropy, because it has been compromised.") return } } passphraseLength := len(*randomPassphraseFlag) for key, value := range charsets { if strings.ContainsAny(*randomPassphraseFlag, value) { possibleSymbols += len(value) usedCharsets = append(usedCharsets, key) } } entropy := math.Log2(math.Pow(float64(possibleSymbols), float64(passphraseLength))) fmt.Println("\nNumber of characters:", passphraseLength) fmt.Println("\nUsed character sets:", strings.Join(usedCharsets, ", ")) fmt.Println("\nPassphrase entropy:", entropy) } if inventedCommand.Parsed() { if *inventedWords != 0 { inventedCommand.Usage() return } if *inventedPwnedFlag == true { haveIBeenPwned, err = pwned.IsPasswordCompromised(passphrase) } if err != nil { fmt.Println("Something went wrong.") } else if haveIBeenPwned == true { fmt.Println("This password does not have any entropy, because it has been compromised.") return } else { fmt.Println("Calc entropy here") } } }