app.go 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. package main
  2. import (
  3. "flag"
  4. "fmt"
  5. "math"
  6. "os"
  7. "strings"
  8. "passphrase-entropy/packages/haveibeenpwned"
  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 myUsage() {
  19. fmt.Println("usage: passphrase-entropy <command> [<args>]")
  20. fmt.Println("Available commands are: ")
  21. fmt.Println(" diceware Calculate entropy of a diceware passphrase")
  22. fmt.Println(" random Calculate entropy of a random string")
  23. fmt.Println(" invented Calculate entropy of an invented passphrase")
  24. }
  25. func main() {
  26. var charsets map[string]string
  27. var usedCharsets[] string
  28. var possibleSymbols int = 0
  29. var haveIBeenPwned bool
  30. var passphrase string
  31. var err error
  32. charsets = make(map[string]string)
  33. charsets["Numbers"] = "0123456789"
  34. charsets["Lowercase"] = "abcdefghijklmnopqrstuvwxyz"
  35. charsets["Uppercase"] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
  36. charsets["Common Special Characters"] = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~"
  37. charsets["Space"] = " "
  38. charsets["Extended ASCII"] = "€‚ƒ„…†‡ˆ‰Š‹ŒŽ‘’“”•–—˜™š›œžŸ¡¢£¤¥¦§¨©ª«¬®¯°±²³´µ¶·¸¹º»¼½¾¿ÀÁÂÃÄÅÆÇÈÉÊËÌÍÎÏÐÑÒÓÔÕÖרÙÚÛÜÝÞßàáâãäåæçèéêëìíîïðñòóôõö÷øùúûüýþÿ"
  39. dicewareCommand := flag.NewFlagSet("diceware", flag.ExitOnError)
  40. dicewarePassphraseFlag := dicewareCommand.String("password", "", "the password")
  41. wordsFlag := dicewareCommand.Int("words", 0, "number of words in passphrase")
  42. dictSizeFlag := dicewareCommand.Int("dictSize", 0, "number of words in dictionary")
  43. delimiterFlag := dicewareCommand.String("delimiter", "", "delimiter used")
  44. randomCommand := flag.NewFlagSet("random", flag.ExitOnError)
  45. randomPassphraseFlag := randomCommand.String("password", "", "the password")
  46. randomPwnedFlag := randomCommand.Bool("pwned", false, "check if password has been seen before")
  47. inventedCommand := flag.NewFlagSet("invented", flag.ExitOnError)
  48. inventedPassphraseFlag := inventedCommand.String("password", "", "the password")
  49. inventedWords := inventedCommand.Int("words", 0, "number of words in invented passphrase")
  50. inventedPwnedFlag := inventedCommand.Bool("pwned", false, "check if password has been seen before")
  51. if len(os.Args) == 1 {
  52. myUsage()
  53. return
  54. }
  55. switch os.Args[1] {
  56. case "diceware":
  57. dicewareCommand.Parse(os.Args[2:])
  58. case "random":
  59. randomCommand.Parse(os.Args[2:])
  60. case "invented":
  61. inventedCommand.Parse(os.Args[2:])
  62. default:
  63. myUsage()
  64. fmt.Printf("\n%q is not valid command.\n", os.Args[1])
  65. os.Exit(2)
  66. }
  67. if *inventedPassphraseFlag != "" {
  68. passphrase = *inventedPassphraseFlag
  69. } else if *randomPassphraseFlag != "" {
  70. passphrase = *randomPassphraseFlag
  71. } else {
  72. passphrase = *dicewarePassphraseFlag
  73. }
  74. if dicewareCommand.Parsed() {
  75. if *wordsFlag == 0 {
  76. dicewareCommand.Usage()
  77. return
  78. }
  79. if *dictSizeFlag == 0 {
  80. dicewareCommand.Usage()
  81. return
  82. }
  83. if *delimiterFlag != "" {
  84. for key, value := range charsets {
  85. if strings.ContainsAny(*delimiterFlag, value) {
  86. *dictSizeFlag += len(value)
  87. usedCharsets = append(usedCharsets, key)
  88. }
  89. }
  90. }
  91. entropy := math.Log2(math.Pow(float64(*dictSizeFlag), float64(*wordsFlag)))
  92. fmt.Println("\nPassphrase entropy:", entropy)
  93. }
  94. if randomCommand.Parsed() {
  95. if *randomPassphraseFlag == "" {
  96. randomCommand.Usage()
  97. return
  98. }
  99. if *randomPwnedFlag == true {
  100. haveIBeenPwned, err = pwned.IsPasswordCompromised(passphrase)
  101. if haveIBeenPwned == true {
  102. fmt.Println("This password does not have any entropy, because it has been compromised.")
  103. return
  104. }
  105. }
  106. passphraseLength := len(*randomPassphraseFlag)
  107. for key, value := range charsets {
  108. if strings.ContainsAny(*randomPassphraseFlag, value) {
  109. possibleSymbols += len(value)
  110. usedCharsets = append(usedCharsets, key)
  111. }
  112. }
  113. entropy := math.Log2(math.Pow(float64(possibleSymbols), float64(passphraseLength)))
  114. fmt.Println("\nNumber of characters:", passphraseLength)
  115. fmt.Println("\nUsed character sets:", strings.Join(usedCharsets, ", "))
  116. fmt.Println("\nPassphrase entropy:", entropy)
  117. }
  118. if inventedCommand.Parsed() {
  119. if *inventedWords != 0 {
  120. inventedCommand.Usage()
  121. return
  122. }
  123. if *inventedPwnedFlag == true {
  124. haveIBeenPwned, err = pwned.IsPasswordCompromised(passphrase)
  125. }
  126. if err != nil {
  127. fmt.Println("Something went wrong.")
  128. } else if haveIBeenPwned == true {
  129. fmt.Println("This password does not have any entropy, because it has been compromised.")
  130. return
  131. } else {
  132. fmt.Println("Calc entropy here")
  133. }
  134. }
  135. }