diff --git a/libs/common/random.go b/libs/common/random.go index 389a32fc..0c44568e 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)