Change summary
main.go | 76 +++++++++++++++++++++++++++++++++++++++++++++++++++-------
1 file changed, 66 insertions(+), 10 deletions(-)
Detailed changes
@@ -14,14 +14,25 @@ import (
)
var (
- length = 20
- version = ""
+ length = 20
+ version = ""
+ consonants = "bcdfghjklmnpqrstvwxyz"
+ vowels = "aeiou"
+ numbers = "0123456789"
+ newBase60Chars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz"
)
func main() {
if len(os.Args) > 1 && os.Args[1] == "-h" {
printHelp()
os.Exit(0)
+ } else if len(os.Args) > 1 && os.Args[1] == "-t" {
+ switch os.Args[2] {
+ case "nb60":
+ fmt.Println(generate(length))
+ case "friendly":
+ fmt.Println(generateFriendly())
+ }
} else if len(os.Args) > 3 {
fmt.Print("Error: too many arguments...\n\n")
printHelp()
@@ -57,8 +68,6 @@ func main() {
}
func generate(length int) string {
- const newBase60Chars = "0123456789ABCDEFGHJKLMNPQRSTUVWXYZ_abcdefghijkmnopqrstuvwxyz"
-
rng := rand.New(rand.NewSource(time.Now().UnixNano()))
var sb strings.Builder
@@ -71,14 +80,61 @@ func generate(length int) string {
return sb.String()
}
+func generateFriendly() string {
+ rng := rand.New(rand.NewSource(time.Now().UnixNano()))
+
+ sets := make([]string, 3)
+ for i := 0; i < 3; i++ {
+ sets[i] = genFriendlySet(rng)
+ }
+
+ result := strings.Join(sets, "-")
+
+ letterPos := rng.Intn(len(result))
+ // Generate a different position until a non-separator is found
+ for result[letterPos] == '-' {
+ letterPos = rng.Intn(len(result))
+ }
+ existingLetter := result[letterPos]
+ var newLetter string
+ if strings.Contains(consonants, string(existingLetter)) {
+ newLetter = string(consonants[rng.Intn(len(consonants))])
+ } else if strings.Contains(vowels, string(existingLetter)) {
+ newLetter = string(vowels[rng.Intn(len(vowels))])
+ }
+ result = result[:letterPos] + newLetter + result[letterPos+1:]
+
+ // Generate a different position until a non-separator and non-uppercase-letter
+ // is found
+ numberPos := rng.Intn(len(result))
+ for result[numberPos] == '-' || result[numberPos] == result[letterPos] {
+ numberPos = rng.Intn(len(result))
+ }
+ result = result[:numberPos] + string(numbers[rng.Intn(len(numbers))]) + result[numberPos+1:]
+
+ return result
+}
+
+func genFriendlySet(rng *rand.Rand) string {
+ set := make([]byte, 6)
+ set[0] = consonants[rng.Intn(len(consonants))]
+ set[1] = vowels[rng.Intn(len(vowels))]
+ set[2] = consonants[rng.Intn(len(consonants))]
+ set[3] = consonants[rng.Intn(len(consonants))]
+ set[4] = vowels[rng.Intn(len(vowels))]
+ set[5] = consonants[rng.Intn(len(consonants))]
+ return string(set)
+}
+
func printHelp() {
- fmt.Println(`Usage: eow [-h] <length> <count>
+ fmt.Println(`Usage: eow [-h|-t] <length> <count>
-h prints this help message
-Arguments are positional, so length AND count
-may be omitted OR count may be omitted. If
-specifying count, length must also be
-specified. When ommitted, length defaults to
-20 and count defaults to 1.`)
+-t <type> prints a single 20-character NewBase60 (nb60) or friendly (friendly)
+ password.
+
+Arguments are positional, so length AND count may be omitted OR count may be
+omitted. If specifying count, length must also be specified. When ommitted,
+length defaults to 20 and count defaults to 1.`)
}