app.go 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "github.com/chaosbunker/haveibeenpwned"
  6. "github.com/trustelem/zxcvbn"
  7. "math"
  8. "os"
  9. )
  10. func contains(arr [3]string, str string) bool {
  11. for _, a := range arr {
  12. if a == str {
  13. return true
  14. }
  15. }
  16. return false
  17. }
  18. func guessesToHuman(guesses float64) (result string) {
  19. minute := float64(60)
  20. hour := minute * 60
  21. day := hour * 24
  22. month := day * 31
  23. year := month * 12
  24. century := year * 100
  25. if guesses < 1 {
  26. result = "< 1 second"
  27. } else if guesses < minute {
  28. result = fmt.Sprintf("%d seconds", int(math.Round(guesses)))
  29. } else if guesses < hour {
  30. result = fmt.Sprintf("%d minutes", int(math.Round(guesses / minute)))
  31. } else if guesses < day {
  32. result = fmt.Sprintf("%d hours ", int(math.Round(guesses / hour)))
  33. } else if guesses < month {
  34. result = fmt.Sprintf("%d days ", int(math.Round(guesses / day)))
  35. } else if guesses < year {
  36. result = fmt.Sprintf("%d months ", int(math.Round(guesses / month)))
  37. } else if guesses < century {
  38. result = fmt.Sprintf("%d years ", int(math.Round(guesses / year)))
  39. } else {
  40. result = fmt.Sprintf("Centuries")
  41. }
  42. return
  43. }
  44. type arrayFlags []string
  45. func (i *arrayFlags) String() string {
  46. return "my string representation"
  47. }
  48. func (i *arrayFlags) Set(value string) error {
  49. *i = append(*i, value)
  50. return nil
  51. }
  52. func main() {
  53. var password string
  54. var pwnedFlag, haveIBeenPwned bool
  55. var words arrayFlags
  56. var err error
  57. flag.StringVar(&password,"password", "", "a password")
  58. flag.Var(&words, "word", "used words, e.g. -password p4ssw0rd -word password")
  59. flag.BoolVar(&pwnedFlag, "pwned", false, "check with haveibeenpwned API if password has been seen before")
  60. flag.Parse()
  61. if len(os.Args) == 1 || password == "" {
  62. flag.PrintDefaults()
  63. return
  64. }
  65. if pwnedFlag == true {
  66. haveIBeenPwned, err = pwned.IsPasswordCompromised(password)
  67. }
  68. if err != nil {
  69. fmt.Println("Something went wrong.")
  70. } else {
  71. strength := zxcvbn.PasswordStrength(password, words)
  72. guesses := strength.Guesses
  73. fmt.Printf("\nPassword:\t\t%s\n", password)
  74. fmt.Printf("Password strength:\t%d/4\n", strength.Score)
  75. fmt.Printf("Guesses Log10:\t\t%f\n", math.Log10(guesses))
  76. fmt.Println("\nGuess times")
  77. fmt.Printf("100 / h:\t\t%s\t(throttled online attack)\n", guessesToHuman(guesses * (3600 / 100)))
  78. fmt.Printf("10 / s:\t\t%s\t(unthrottled online attack)\n", guessesToHuman(guesses / 10))
  79. fmt.Printf("10k / s:\t\t%s\t(offline attack, slow hash, many cores)\n", guessesToHuman(guesses / 1e4))
  80. fmt.Printf("10b / s:\t\t%s\t(offline attack, fast hash, many cores)\n", guessesToHuman(guesses / 1e10))
  81. }
  82. if haveIBeenPwned == true {
  83. fmt.Println("\nThis password has been compromised and should not be used.")
  84. }
  85. }