diff --git a/staging/src/k8s.io/cluster-bootstrap/token/util/helpers.go b/staging/src/k8s.io/cluster-bootstrap/token/util/helpers.go index f9ea35b5ee3..70abe8f1cb3 100644 --- a/staging/src/k8s.io/cluster-bootstrap/token/util/helpers.go +++ b/staging/src/k8s.io/cluster-bootstrap/token/util/helpers.go @@ -17,9 +17,9 @@ limitations under the License. package util import ( - "bufio" "crypto/rand" "fmt" + "math/big" "regexp" "strings" @@ -59,29 +59,21 @@ func GenerateBootstrapToken() (string, error) { // randBytes returns a random string consisting of the characters in // validBootstrapTokenChars, with the length customized by the parameter func randBytes(length int) (string, error) { - // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide - // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we - // read that are >= 252 so the bytes we evenly divide the character set. - const maxByteValue = 252 - var ( - b byte - err error token = make([]byte, length) + max = new(big.Int).SetUint64(uint64(len(validBootstrapTokenChars))) ) - reader := bufio.NewReaderSize(rand.Reader, length*2) for i := range token { - for { - if b, err = reader.ReadByte(); err != nil { - return "", err - } - if b < maxByteValue { - break - } + val, err := rand.Int(rand.Reader, max) + if err != nil { + return "", fmt.Errorf("could not generate random integer: %w", err) } - - token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)] + // Use simple operations in constant-time to obtain a byte in the a-z,0-9 + // character range + x := val.Uint64() + res := x + 48 + (39 & ((9 - x) >> 8)) + token[i] = byte(res) } return string(token), nil