kubeadm: more random tokens

The strategy of hex encoding a random byte array only uses the
following characters:

	0123456789abcdef

Instead of the entire bootstrapping token character set:

	0123456789abcdefghijklmnopqrstuvwxyz

Update the token generation to use the entire character set. This
increases the token secret from 48 bits of entropy to ~82 bits.

256^8 (1.8e+19) vs. 36^16 (7.9e+24).
This commit is contained in:
Eric Chiang 2018-01-08 17:19:12 -08:00
parent df2428c6dd
commit 8debdc1501
2 changed files with 32 additions and 10 deletions

View File

@ -17,8 +17,8 @@ limitations under the License.
package token package token
import ( import (
"bufio"
"crypto/rand" "crypto/rand"
"encoding/hex"
"fmt" "fmt"
"regexp" "regexp"
@ -27,9 +27,9 @@ import (
const ( const (
// TokenIDBytes defines a number of bytes used for a token id // TokenIDBytes defines a number of bytes used for a token id
TokenIDBytes = 3 TokenIDBytes = 6
// TokenSecretBytes defines a number of bytes used for a secret // TokenSecretBytes defines a number of bytes used for a secret
TokenSecretBytes = 8 TokenSecretBytes = 16
) )
var ( var (
@ -43,13 +43,35 @@ var (
TokenRegexp = regexp.MustCompile(TokenRegexpString) TokenRegexp = regexp.MustCompile(TokenRegexpString)
) )
const validBootstrapTokenChars = "0123456789abcdefghijklmnopqrstuvwxyz"
func randBytes(length int) (string, error) { func randBytes(length int) (string, error) {
b := make([]byte, length) // len("0123456789abcdefghijklmnopqrstuvwxyz") = 36 which doesn't evenly divide
_, err := rand.Read(b) // the possible values of a byte: 256 mod 36 = 4. Discard any random bytes we
if err != nil { // read that are >= 252 so the bytes we evenly divide the character set.
return "", err const maxByteValue = 252
var (
b byte
err error
token = make([]byte, length)
)
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
}
}
token[i] = validBootstrapTokenChars[int(b)%len(validBootstrapTokenChars)]
} }
return hex.EncodeToString(b), nil
return string(token), nil
} }
// GenerateToken generates a new token with a token ID that is valid as a // GenerateToken generates a new token with a token ID that is valid as a

View File

@ -147,8 +147,8 @@ func TestRandBytes(t *testing.T) {
if err != nil { if err != nil {
t.Errorf("failed randBytes: %v", err) t.Errorf("failed randBytes: %v", err)
} }
if len(actual) != rt*2 { if len(actual) != rt {
t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt*2, len(actual)) t.Errorf("failed randBytes:\n\texpected: %d\n\t actual: %d\n", rt, len(actual))
} }
} }
} }