Currently the global rand
is seeded using time.Now().UnixNano()
. That approach has its` drawbacks:
- The randomness is presented in the lower bits only, whereas the higher bits remain the same and very predictable.
- Some systems do not provide the granularity of single nanoseconds, sometimes it’s up to tens of milliseconds. That also increases predictability significantly.
Although for cryptographically strong random values the crypto/rand
must be used, that’s not always the case where it’s needed. And some innocently looking predictable values may lead to serious exploits. Like jitter value for retries back-off.
- Versions: Nakama 3.9.0
- Server Framework Runtime language Go
At the same time, the fix is quite straightforward and comparatively easy to implement. Here’s example I came up with:
func getSeedForGlobalRand() (int64, error) {
var seed int64
err := binary.Read(cryptorand.Reader, binary.BigEndian, &seed)
if err != nil {
return time.Now().UnixNano(), err
}
return seed, nil
}