Skip to content

Commit 120dcbf

Browse files
committed
GODRIVER-2349 Seed all pseudorandom number generators with a crypto-secure random number.
1 parent 57747f8 commit 120dcbf

File tree

4 files changed

+22
-6
lines changed

4 files changed

+22
-6
lines changed

internal/randutil/randutil.go

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22
package randutil
33

44
import (
5+
crand "crypto/rand"
6+
"fmt"
7+
"io"
58
"math/rand"
69
"sync"
710
)
@@ -52,3 +55,17 @@ func (lr *LockedRand) Shuffle(n int, swap func(i, j int)) {
5255
lr.r.Shuffle(n, swap)
5356
lr.mu.Unlock()
5457
}
58+
59+
// CryptoSeed returns a random int64 read from the "crypto/rand" random number generator. It is
60+
// intended to be used to seed pseudorandom number generators at package initialization. It panics
61+
// if it encounters any errors.
62+
func CryptoSeed() int64 {
63+
var b [8]byte
64+
_, err := io.ReadFull(crand.Reader, b[:])
65+
if err != nil {
66+
panic(fmt.Errorf("failed to read 8 bytes from a \"crypto/rand\".Reader: %v", err))
67+
}
68+
69+
return (int64(b[0]) << 0) | (int64(b[1]) << 8) | (int64(b[2]) << 16) | (int64(b[3]) << 24) |
70+
(int64(b[4]) << 32) | (int64(b[5]) << 40) | (int64(b[6]) << 48) | (int64(b[7]) << 56)
71+
}

x/mongo/driver/connstring/connstring.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ import (
2424
)
2525

2626
// random is a package-global pseudo-random number generator.
27-
var random = randutil.NewLockedRand(rand.NewSource(time.Now().UnixNano()))
27+
var random = randutil.NewLockedRand(rand.NewSource(randutil.CryptoSeed()))
2828

2929
// ParseAndValidate parses the provided URI into a ConnString object.
3030
// It check that all values are valid.

x/mongo/driver/topology/topology.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ var ErrServerSelectionTimeout = errors.New("server selection timeout")
5757
type MonitorMode uint8
5858

5959
// random is a package-global pseudo-random number generator.
60-
var random = randutil.NewLockedRand(rand.NewSource(time.Now().UnixNano()))
60+
var random = randutil.NewLockedRand(rand.NewSource(randutil.CryptoSeed()))
6161

6262
// These constants are the available monitoring modes.
6363
const (

x/mongo/driver/uuid/uuid.go

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ package uuid // import "go.mongodb.org/mongo-driver/x/mongo/driver/uuid"
99
import (
1010
"io"
1111
"math/rand"
12-
"time"
1312

1413
"go.mongodb.org/mongo-driver/internal/randutil"
1514
)
@@ -18,10 +17,10 @@ import (
1817
type UUID [16]byte
1918

2019
// random is a package-global pseudo-random number generator.
21-
var random = randutil.NewLockedRand(rand.NewSource(time.Now().UnixNano()))
20+
var random = randutil.NewLockedRand(rand.NewSource(randutil.CryptoSeed()))
2221

23-
// New returns a random UUIDv4. It uses a "math/rand" pseudo-random number generator seeded with the
24-
// package initialization time.
22+
// New returns a random UUIDv4. It uses a "math/rand" pseudo-random number generator seeded with a
23+
// cryptographically-secure random number at package initialization.
2524
//
2625
// New should not be used to generate cryptographically-secure random UUIDs.
2726
func New() (UUID, error) {

0 commit comments

Comments
 (0)