66 lines
1.6 KiB
Go
66 lines
1.6 KiB
Go
package password
|
|
|
|
import (
|
|
"crypto/rand"
|
|
"fmt"
|
|
"math/big"
|
|
)
|
|
|
|
var upperRunes = []rune("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
var lowerRunes = []rune("abcdefghijklmnopqrstuvwxyz")
|
|
var numberRunes = []rune("0123456789")
|
|
var symbolRunes = []rune("!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~")
|
|
|
|
// Generate generates a random string with the specified size containing runes from the designated sets.
|
|
func Generate(upper, lower, number, symbol bool, size int) (string, error) {
|
|
if size <= 0 {
|
|
return "", fmt.Errorf("password: Password size must be greater than 0")
|
|
}
|
|
|
|
runeSet := []rune{}
|
|
|
|
if upper {
|
|
runeSet = append(runeSet, upperRunes...)
|
|
}
|
|
if lower {
|
|
runeSet = append(runeSet, lowerRunes...)
|
|
}
|
|
if number {
|
|
runeSet = append(runeSet, numberRunes...)
|
|
}
|
|
if symbol {
|
|
runeSet = append(runeSet, symbolRunes...)
|
|
}
|
|
|
|
if len(runeSet) == 0 {
|
|
return "", fmt.Errorf("password: No runes selected for password")
|
|
}
|
|
|
|
password := make([]rune, size)
|
|
for i := 0; i < size; i++ {
|
|
n, err := rand.Int(rand.Reader, big.NewInt(int64(len(runeSet))))
|
|
if err != nil {
|
|
return "", fmt.Errorf("password: Error while generating random number: %v", err)
|
|
}
|
|
password[i] = runeSet[n.Int64()]
|
|
}
|
|
|
|
return string(password), nil
|
|
}
|
|
|
|
// Random creates an array of random bytes with specified size.
|
|
// If used to generate password salt, then size of 16 bytes (128 bits) is recommended.
|
|
func Random(size int) ([]byte, error) {
|
|
if size < 0 {
|
|
return nil, fmt.Errorf("password: Size cannot be less than zero")
|
|
}
|
|
random := make([]byte, size)
|
|
|
|
_, err := rand.Read(random)
|
|
if err != nil {
|
|
return nil, fmt.Errorf("password: Error while reading random bytes: %v", err)
|
|
}
|
|
|
|
return random, nil
|
|
}
|