From a3df06d08133920b9bea3a2f92d9dc0ba9669a19 Mon Sep 17 00:00:00 2001 From: ValarDragon Date: Sat, 14 Jul 2018 15:31:25 -0700 Subject: [PATCH] libs/common/rand: Update godocs The godocs fell out of sync with the code here. Additionally we had warning that these randomness functions weren't for cryptographic use on every function. However these warnings are confusing, since there was no implication that they would be secure there, and a single warning on the actual Rand type would suffice. (This is what is done in golang's math/rand godoc) Additionally we indicated that rand.Bytes() was reading OS randomness but in fact that had been changed. --- libs/common/random.go | 41 ++++++++++++----------------------------- 1 file changed, 12 insertions(+), 29 deletions(-) diff --git a/libs/common/random.go b/libs/common/random.go index 389a32fc2..0c44568e0 100644 --- a/libs/common/random.go +++ b/libs/common/random.go @@ -11,9 +11,13 @@ const ( strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters ) -// pseudo random number generator. -// seeded with OS randomness (crand) - +// Rand is a prng, that is seeded with OS randomness. +// The OS randomness is obtained from crypto/rand, however none of the provided +// methods are suitable for cryptographic usage. +// They all utilize math/rand's prng internally. +// +// All of the methods here are suitable for concurrent use. +// This is achieved by using a mutex lock on all of the provided methods. type Rand struct { sync.Mutex rand *mrand.Rand @@ -150,8 +154,7 @@ func (r *Rand) Seed(seed int64) { r.Unlock() } -// Constructs an alphanumeric string of given length. -// It is not safe for cryptographic usage. +// Str constructs a random alphanumeric string of given length. func (r *Rand) Str(length int) string { chars := []byte{} MAIN_LOOP: @@ -175,12 +178,10 @@ MAIN_LOOP: return string(chars) } -// It is not safe for cryptographic usage. func (r *Rand) Uint16() uint16 { return uint16(r.Uint32() & (1<<16 - 1)) } -// It is not safe for cryptographic usage. func (r *Rand) Uint32() uint32 { r.Lock() u32 := r.rand.Uint32() @@ -188,12 +189,10 @@ func (r *Rand) Uint32() uint32 { return u32 } -// It is not safe for cryptographic usage. func (r *Rand) Uint64() uint64 { return uint64(r.Uint32())<<32 + uint64(r.Uint32()) } -// It is not safe for cryptographic usage. func (r *Rand) Uint() uint { r.Lock() i := r.rand.Int() @@ -201,22 +200,18 @@ func (r *Rand) Uint() uint { return uint(i) } -// It is not safe for cryptographic usage. func (r *Rand) Int16() int16 { return int16(r.Uint32() & (1<<16 - 1)) } -// It is not safe for cryptographic usage. func (r *Rand) Int32() int32 { return int32(r.Uint32()) } -// It is not safe for cryptographic usage. func (r *Rand) Int64() int64 { return int64(r.Uint64()) } -// It is not safe for cryptographic usage. func (r *Rand) Int() int { r.Lock() i := r.rand.Int() @@ -224,7 +219,6 @@ func (r *Rand) Int() int { return i } -// It is not safe for cryptographic usage. func (r *Rand) Int31() int32 { r.Lock() i31 := r.rand.Int31() @@ -232,7 +226,6 @@ func (r *Rand) Int31() int32 { return i31 } -// It is not safe for cryptographic usage. func (r *Rand) Int31n(n int32) int32 { r.Lock() i31n := r.rand.Int31n(n) @@ -240,7 +233,6 @@ func (r *Rand) Int31n(n int32) int32 { return i31n } -// It is not safe for cryptographic usage. func (r *Rand) Int63() int64 { r.Lock() i63 := r.rand.Int63() @@ -248,7 +240,6 @@ func (r *Rand) Int63() int64 { return i63 } -// It is not safe for cryptographic usage. func (r *Rand) Int63n(n int64) int64 { r.Lock() i63n := r.rand.Int63n(n) @@ -257,7 +248,6 @@ func (r *Rand) Int63n(n int64) int64 { } // Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. func (r *Rand) Uint16Exp() uint16 { bits := r.Uint32() % 16 if bits == 0 { @@ -269,7 +259,6 @@ func (r *Rand) Uint16Exp() uint16 { } // Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. func (r *Rand) Uint32Exp() uint32 { bits := r.Uint32() % 32 if bits == 0 { @@ -281,7 +270,6 @@ func (r *Rand) Uint32Exp() uint32 { } // Distributed pseudo-exponentially to test for various cases -// It is not safe for cryptographic usage. func (r *Rand) Uint64Exp() uint64 { bits := r.Uint32() % 64 if bits == 0 { @@ -292,7 +280,6 @@ func (r *Rand) Uint64Exp() uint64 { return n } -// It is not safe for cryptographic usage. func (r *Rand) Float32() float32 { r.Lock() f32 := r.rand.Float32() @@ -300,7 +287,6 @@ func (r *Rand) Float32() float32 { return f32 } -// It is not safe for cryptographic usage. func (r *Rand) Float64() float64 { r.Lock() f64 := r.rand.Float64() @@ -308,13 +294,12 @@ func (r *Rand) Float64() float64 { return f64 } -// It is not safe for cryptographic usage. func (r *Rand) Time() time.Time { return time.Unix(int64(r.Uint64Exp()), 0) } -// RandBytes returns n random bytes from the OS's source of entropy ie. via crypto/rand. -// It is not safe for cryptographic usage. +// Bytes returns n random bytes generated from the internal +// prng. func (r *Rand) Bytes(n int) []byte { // cRandBytes isn't guaranteed to be fast so instead // use random bytes generated from the internal PRNG @@ -325,9 +310,8 @@ func (r *Rand) Bytes(n int) []byte { return bs } -// RandIntn returns, as an int, a non-negative pseudo-random number in [0, n). +// Intn returns, as an int, a uniform pseudo-random number in the range [0, n). // It panics if n <= 0. -// It is not safe for cryptographic usage. func (r *Rand) Intn(n int) int { r.Lock() i := r.rand.Intn(n) @@ -335,8 +319,7 @@ func (r *Rand) Intn(n int) int { return i } -// RandPerm returns a pseudo-random permutation of n integers in [0, n). -// It is not safe for cryptographic usage. +// Perm returns a pseudo-random permutation of n integers in [0, n). func (r *Rand) Perm(n int) []int { r.Lock() perm := r.rand.Perm(n)