amuz.es/src/go/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  }