github.com/tommi2day/gomodules/pwlib@v0.0.0-20230217211148-82cdbcf0a79d/password_generate.go (about) 1 package pwlib 2 3 import ( 4 "crypto/rand" 5 "fmt" 6 "math/big" 7 8 log "github.com/sirupsen/logrus" 9 ) 10 11 // generateRandomString generate a randow string with the given length and out of allowed charset 12 func generateRandomString(length int, allowedChars string) string { 13 letters := allowedChars 14 ret := make([]byte, length) 15 for i := 0; i < length; i++ { 16 num, _ := rand.Int(rand.Reader, big.NewInt(int64(len(letters)))) 17 ret[i] = letters[num.Int64()] 18 } 19 log.Debugf("Password candidate: %s", string(ret)) 20 return string(ret) 21 } 22 23 // GenPassword generates a password with the given complexity 24 func GenPassword(length int, upper int, lower int, numeric int, special int, firstCharCheck bool) (string, error) { 25 log.Debug("GenPassword entered") 26 // allowed chars 27 var ok = false 28 var err error 29 30 var allowedChars = "" 31 // define allowed charset based on parameters 32 if upper > 0 { 33 allowedChars += UpperChar 34 } 35 if lower > 0 { 36 allowedChars += LowerChar 37 } 38 if numeric > 0 { 39 allowedChars += Digits 40 } 41 if special > 0 { 42 allowedChars += SpecialChar 43 } 44 45 newPassword := "" 46 // max 50 tries to generate a valid password 47 for c := 0; c < 50; c++ { 48 newPassword = generateRandomString(length, allowedChars) 49 ok = DoPasswordCheck(newPassword, length, upper, lower, numeric, special, firstCharCheck, allowedChars) 50 if ok { 51 break 52 } 53 newPassword = "" 54 log.Debugf("generate retry %d", c) 55 } 56 57 if !ok { 58 err = fmt.Errorf("unable to create required Password") 59 } else { 60 log.Debug("Generation succeeded") 61 } 62 return newPassword, err 63 }