Crypto rand is a much better seed for math/rand than
time. In the event we use math/rand where we should not,
this will make it a safer source of random numbers.
Although potentially dangerous, this will still fallback
to time should crypto/rand for any reason fail.
Signed-off-by: Eric Windisch <eric@windisch.us>
| ... | ... |
@@ -1,7 +1,10 @@ |
| 1 | 1 |
package random |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
+ cryptorand "crypto/rand" |
|
| 4 | 5 |
"io" |
| 6 |
+ "math" |
|
| 7 |
+ "math/big" |
|
| 5 | 8 |
"math/rand" |
| 6 | 9 |
"sync" |
| 7 | 10 |
"time" |
| ... | ... |
@@ -36,8 +39,15 @@ func (r *lockedSource) Seed(seed int64) {
|
| 36 | 36 |
// NewSource returns math/rand.Source safe for concurrent use and initialized |
| 37 | 37 |
// with current unix-nano timestamp |
| 38 | 38 |
func NewSource() rand.Source {
|
| 39 |
+ var seed int64 |
|
| 40 |
+ if cryptoseed, err := cryptorand.Int(cryptorand.Reader, big.NewInt(math.MaxInt64)); err != nil {
|
|
| 41 |
+ // This should not happen, but worst-case fallback to time-based seed. |
|
| 42 |
+ seed = time.Now().UnixNano() |
|
| 43 |
+ } else {
|
|
| 44 |
+ seed = cryptoseed.Int64() |
|
| 45 |
+ } |
|
| 39 | 46 |
return &lockedSource{
|
| 40 |
- src: rand.NewSource(time.Now().UnixNano()), |
|
| 47 |
+ src: rand.NewSource(seed), |
|
| 41 | 48 |
} |
| 42 | 49 |
} |
| 43 | 50 |
|