You can use example below to generate a strong random password string with a variable length. Obviously if the password is short, it won't be strong! Long password doesn't necessarily mean that it is strong either. Please read comment in the code so that you know how exactly it works.


Password


package main

import (
"fmt"
"math/rand"
"strings"
"time"
)

var list = []string{
"(){}[]<>/+=-_,.~€#!@£$%^&*?|",
"0123456789",
"abcdefghijklmnopqrstuvwxyz",
"ABCDEFGHIJKLMNOPQRSTUVWXYZ",
}

// GeneratePlainPassword generates a random plain password string.
// It consists of four groups which are certain symbols, numbers,
// lower and upper case letters. As per the length and the remainder,
// character selecting is evenly distributed within these groups.
// Although it is unlikely, a final password might contain duplicated
// characters. If a specific character was selected previously, it gets
// dropped in order to increase randomness. Depending on the length
// this is repeated set amount of times to prevent infinite loop and
// applies to all four groups. Greater the length, greater chance in
// duplicated characters.
func GeneratePlainPassword(length int) (string, error) {
if length < 1 {
return "", nil
}

var (
retry int
group int
chars string
)

if length <= 4 {
retry = 1
} else if length > 20 && length <= 50 {
retry = 20
} else if length > 50 {
retry = 30
} else {
retry = 10
}

rand.Seed(time.Now().UnixNano())

for i := 1; i <= length; i++ {
switch group {
case 0:
pick(0, 31, retry, &chars)
group++
case 1:
pick(1, 10, retry, &chars)
group++
case 2:
pick(2, 26, retry, &chars)
group++
case 3:
pick(3, 26, retry, &chars)
group = 0
default:
return "", fmt.Errorf("out of group range")
}
}

psw := []byte(chars)
rand.Shuffle(length, func(i, j int) { psw[i], psw[j] = psw[j], psw[i] })

return string(psw), nil
}

func pick(key, len, retry int, chars *string) {
var try int

for {
try++

idx := rand.Intn(len)
char := list[key][idx:idx+1]
if !strings.Contains(*chars, char) || try == retry {
*chars += char

break
}
}
}

Examples


RETRY: n/a
LENGTH: 0
PASSWR:
------------------------------------------------------------
RETRY: 1
LENGTH: 3
PASSWR: )4a
------------------------------------------------------------
RETRY: 10
LENGTH: 10
PASSWR: +i79d>W=4F
------------------------------------------------------------
RETRY: 20
LENGTH: 25
PASSWR: Mtm*d/>BN39?1y+J,kC54[8Lv
------------------------------------------------------------
RETRY: 30
LENGTH: 55
PASSWR: [QZ2b/=61.z]98^*Txqfst3!u£cS0#?XGVL%U3,0H1yj7KOmvr6&4C5
------------------------------------------------------------
RETRY: 30
LENGTH: 110
PASSWR: MaWYO)Bb3_&95O{qVn3kF,3]yT(R4~9P€7Z[l0N!0U&2#rw37J^Efgo£7.q)c8HL6?Sp44vm1/I=5@46h5stC}2i2uGe-X$zs|+A3xDj*Q4dK%