From 9a0dbdbf13f019e414ce3f2b490c3ecd4fa6bdb0 Mon Sep 17 00:00:00 2001 From: Sam Kleinman Date: Fri, 17 Dec 2021 12:15:27 -0500 Subject: [PATCH] libs/rand: remove custom seed function (#7473) --- libs/bits/bit_array.go | 13 +++++++----- libs/events/events_test.go | 6 +++--- libs/rand/random.go | 43 -------------------------------------- 3 files changed, 11 insertions(+), 51 deletions(-) diff --git a/libs/bits/bit_array.go b/libs/bits/bit_array.go index a0258521c..d0f79ce14 100644 --- a/libs/bits/bit_array.go +++ b/libs/bits/bit_array.go @@ -5,13 +5,12 @@ import ( "errors" "fmt" "math" - mrand "math/rand" + "math/rand" "regexp" "strings" "sync" tmmath "github.com/tendermint/tendermint/libs/math" - tmrand "github.com/tendermint/tendermint/libs/rand" tmprotobits "github.com/tendermint/tendermint/proto/tendermint/libs/bits" ) @@ -25,8 +24,6 @@ type BitArray struct { // NewBitArray returns a new bit array. // It returns nil if the number of bits is zero. func NewBitArray(bits int) *BitArray { - // Reseed non-deterministically. - tmrand.Reseed() if bits <= 0 { return nil } @@ -270,8 +267,14 @@ func (bA *BitArray) PickRandom() (int, bool) { if len(trueIndices) == 0 { // no bits set to true return 0, false } + + // NOTE: using the default math/rand might result in somewhat + // amount of determinism here. It would be possible to use + // rand.New(rand.NewSeed(time.Now().Unix())).Intn() to + // counteract this possibility if it proved to be material. + // // nolint:gosec // G404: Use of weak random number generator - return trueIndices[mrand.Intn(len(trueIndices))], true + return trueIndices[rand.Intn(len(trueIndices))], true } func (bA *BitArray) getTrueIndices() []int { diff --git a/libs/events/events_test.go b/libs/events/events_test.go index 5ddf8d93d..288303acc 100644 --- a/libs/events/events_test.go +++ b/libs/events/events_test.go @@ -3,6 +3,7 @@ package events import ( "context" "fmt" + "math/rand" "testing" "time" @@ -10,7 +11,6 @@ import ( "github.com/stretchr/testify/require" "github.com/tendermint/tendermint/libs/log" - "github.com/tendermint/tendermint/libs/rand" ) // TestAddListenerForEventFireOnce sets up an EventSwitch, subscribes a single @@ -469,7 +469,7 @@ func TestRemoveListenersAsync(t *testing.T) { // collect received events for event2 go sumReceivedNumbers(numbers2, doneSum2) addListenersStress := func() { - r1 := rand.NewRand() + r1 := rand.New(rand.NewSource(time.Now().Unix())) r1.Seed(time.Now().UnixNano()) for k := uint16(0); k < 400; k++ { listenerNumber := r1.Intn(100) + 3 @@ -480,7 +480,7 @@ func TestRemoveListenersAsync(t *testing.T) { } } removeListenersStress := func() { - r2 := rand.NewRand() + r2 := rand.New(rand.NewSource(time.Now().Unix())) r2.Seed(time.Now().UnixNano()) for k := uint16(0); k < 80; k++ { listenerNumber := r2.Intn(100) + 3 diff --git a/libs/rand/random.go b/libs/rand/random.go index ee400e195..c6bfa04b2 100644 --- a/libs/rand/random.go +++ b/libs/rand/random.go @@ -1,9 +1,6 @@ package rand import ( - crand "crypto/rand" - "encoding/binary" - "fmt" mrand "math/rand" ) @@ -11,37 +8,6 @@ const ( strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters ) -func init() { - Reseed() -} - -// NewRand returns a prng, that is seeded with OS randomness. -// The OS randomness is obtained from crypto/rand, however, like with any math/rand.Rand -// object none of the provided methods are suitable for cryptographic usage. -// -// Note that the returned instance of math/rand's Rand is not -// suitable for concurrent use by multiple goroutines. -// -// For concurrent use, call Reseed to reseed math/rand's default source and -// use math/rand's top-level convenience functions instead. -func NewRand() *mrand.Rand { - seed := crandSeed() - // nolint:gosec // G404: Use of weak random number generator - return mrand.New(mrand.NewSource(seed)) -} - -// Reseed conveniently re-seeds the default Source of math/rand with -// randomness obtained from crypto/rand. -// -// Note that this does not make math/rand suitable for cryptographic usage. -// -// Use math/rand's top-level convenience functions remain suitable -// for concurrent use by multiple goroutines. -func Reseed() { - seed := crandSeed() - mrand.Seed(seed) -} - // Str constructs a random alphanumeric string of given length // from math/rand's global default Source. func Str(length int) string { @@ -78,12 +44,3 @@ func Bytes(n int) []byte { } return bs } - -func crandSeed() int64 { - var seed int64 - err := binary.Read(crand.Reader, binary.BigEndian, &seed) - if err != nil { - panic(fmt.Sprintf("could nor read random seed from crypto/rand: %v", err)) - } - return seed -}