From c930b2e9e2ce65af87d2c70ddb53026e6fda79fc Mon Sep 17 00:00:00 2001 From: greatroar <61184462+greatroar@users.noreply.github.com> Date: Mon, 30 Mar 2020 23:26:28 +0200 Subject: [PATCH] lib/rand: Various fixes (#6474) --- lib/rand/random.go | 35 ++++++++--------------------------- lib/rand/random_test.go | 17 ----------------- lib/rand/securesource.go | 9 +++++---- 3 files changed, 13 insertions(+), 48 deletions(-) diff --git a/lib/rand/random.go b/lib/rand/random.go index 262669e02..2faa04b70 100644 --- a/lib/rand/random.go +++ b/lib/rand/random.go @@ -9,10 +9,7 @@ package rand import ( - "crypto/md5" cryptoRand "crypto/rand" - "encoding/binary" - "io" mathRand "math/rand" "reflect" ) @@ -20,16 +17,16 @@ import ( // Reader is the standard crypto/rand.Reader, re-exported for convenience var Reader = cryptoRand.Reader -// randomCharset contains the characters that can make up a randomString(). +// randomCharset contains the characters that can make up a rand.String(). const randomCharset = "2345679abcdefghijkmnopqrstuvwxyzACDEFGHJKLMNPQRSTUVWXYZ" var ( // defaultSecureSource is a concurrency safe math/rand.Source with a // cryptographically sound base. - defaltSecureSource = newSecureSource() + defaultSecureSource = newSecureSource() // defaultSecureRand is a math/rand.Rand based on the secure source. - defaultSecureRand = mathRand.New(defaltSecureSource) + defaultSecureRand = mathRand.New(defaultSecureSource) ) // String returns a strongly random string of characters (taken from @@ -43,19 +40,14 @@ func String(l int) string { return string(bs) } -// Int63 returns a strongly random int63 +// Int63 returns a strongly random int63. func Int63() int64 { - return defaltSecureSource.Int63() + return defaultSecureSource.Int63() } -// Int64 returns a strongly random int64 +// Int64 returns a strongly random int64. func Int64() int64 { - var bs [8]byte - _, err := io.ReadFull(cryptoRand.Reader, bs[:]) - if err != nil { - panic("randomness failure: " + err.Error()) - } - return int64(binary.BigEndian.Uint64(bs[:])) + return int64(defaultSecureSource.Uint64()) } // Intn returns, as an int, a non-negative strongly random number in [0,n). @@ -64,18 +56,7 @@ func Intn(n int) int { return defaultSecureRand.Intn(n) } -// SeedFromBytes calculates a weak 64 bit hash from the given byte slice, -// suitable for use a predictable random seed. -func SeedFromBytes(bs []byte) int64 { - h := md5.New() - h.Write(bs) - s := h.Sum(nil) - // The MD5 hash of the byte slice is 16 bytes long. We interpret it as two - // uint64s and XOR them together. - return int64(binary.BigEndian.Uint64(s[0:]) ^ binary.BigEndian.Uint64(s[8:])) -} - -// Shuffle the order of elements +// Shuffle the order of elements in slice. func Shuffle(slice interface{}) { rv := reflect.ValueOf(slice) swap := reflect.Swapper(slice) diff --git a/lib/rand/random_test.go b/lib/rand/random_test.go index d3e90b9ba..2c15b312e 100644 --- a/lib/rand/random_test.go +++ b/lib/rand/random_test.go @@ -8,23 +8,6 @@ package rand import "testing" -func TestSeedFromBytes(t *testing.T) { - // should always return the same seed for the same bytes - tcs := []struct { - bs []byte - v int64 - }{ - {[]byte("hello world"), -3639725434188061933}, - {[]byte("hello worlx"), -2539100776074091088}, - } - - for _, tc := range tcs { - if v := SeedFromBytes(tc.bs); v != tc.v { - t.Errorf("Unexpected seed value %d != %d", v, tc.v) - } - } -} - func TestRandomString(t *testing.T) { for _, l := range []int{0, 1, 2, 3, 4, 8, 42} { s := String(l) diff --git a/lib/rand/securesource.go b/lib/rand/securesource.go index 3d8b69e66..7315c04bb 100644 --- a/lib/rand/securesource.go +++ b/lib/rand/securesource.go @@ -37,6 +37,10 @@ func (s *secureSource) Seed(int64) { } func (s *secureSource) Int63() int64 { + return int64(s.Uint64() & (1<<63 - 1)) +} + +func (s *secureSource) Uint64() uint64 { var buf [8]byte // Read eight bytes of entropy from the buffered, secure random number @@ -50,8 +54,5 @@ func (s *secureSource) Int63() int64 { } // Grab those bytes as an uint64 - v := binary.BigEndian.Uint64(buf[:]) - - // Mask of the high bit and return the resulting int63 - return int64(v & (1<<63 - 1)) + return binary.BigEndian.Uint64(buf[:]) }