github.com/spi-ca/misc@v1.0.1/strutil/code.go (about) 1 package strutil 2 3 import ( 4 "context" 5 "crypto/rand" 6 "math" 7 "math/big" 8 "regexp" 9 "strconv" 10 "time" 11 ) 12 13 // PasswordCheck checks a password candidate with minimum length and regexp conditions. 14 func PasswordCheck(source []byte, minLength int, condition ...*regexp.Regexp) (invalid bool) { 15 if len(source) < minLength { 16 return true 17 } 18 for _, cond := range condition { 19 if !cond.Match(source) { 20 return true 21 } 22 } 23 return 24 } 25 26 // RandomDigits returns authenticate code with given length. 27 func RandomDigits(digitLength, limit int) string { 28 ctx, cancel := context.WithTimeout(context.Background(), time.Second) 29 defer cancel() 30 longest := func(source string) (longest int) { 31 var ( 32 current int32 33 count = 0 34 ) 35 for _, digitRune := range source { 36 if digitRune == current { 37 count++ 38 } else { 39 count = 1 40 current = digitRune 41 } 42 if count > longest { 43 longest = count 44 } 45 } 46 return 47 } 48 getNonce := func(digits int) string { 49 seed, _ := rand.Int(rand.Reader, big.NewInt(math.MaxInt64)) 50 return strconv.FormatUint(seed.Uint64(), 10) 51 } 52 nonce := getNonce(digitLength) 53 for longest(nonce) >= limit { 54 select { 55 case <-ctx.Done(): 56 panic(ctx.Err()) 57 default: 58 nonce = getNonce(digitLength) 59 } 60 } 61 return nonce 62 }