github.com/amazechain/amc@v0.1.3/common/crypto/rand/rand.go (about) 1 /* 2 Package rand defines methods of obtaining random number generators. 3 4 One is expected to use randomness from this package only, without introducing any other packages. 5 This limits the scope of code that needs to be hardened. 6 7 There are two modes, one for deterministic and another non-deterministic randomness: 8 1. If deterministic pseudo-random generator is enough, use: 9 10 import "github.com/prysmaticlabs/prysm/v3/crypto/rand" 11 randGen := rand.NewDeterministicGenerator() 12 randGen.Intn(32) // or any other func defined in math.rand API 13 14 In this mode, only seed is generated using cryptographically secure source (crypto/rand). So, 15 once seed is obtained, and generator is seeded, the next generations are deterministic, thus fast. 16 However given that we only seed this 63 bits from crypto/rand and use math/rand to generate the outputs, 17 this method is not cryptographically secure. This is directly stated in the math/rand package, 18 https://github.com/golang/go/blob/release-branch.go1.17/src/math/rand/rand.go#L15. For any security 19 sensitive work this particular generator is NOT to be used. 20 21 2. For cryptographically secure non-deterministic mode (CSPRNG), use: 22 23 import "github.com/prysmaticlabs/prysm/v3/crypto/rand" 24 randGen := rand.NewGenerator() 25 randGen.Intn(32) // or any other func defined in math.rand API 26 27 Again, any of the functions from `math/rand` can be used, however, they all use custom source 28 of randomness (crypto/rand), on every step. This makes randomness non-deterministic. However, 29 you take a performance hit -- as it is an order of magnitude slower. 30 */ 31 package rand 32 33 import ( 34 "crypto/rand" 35 "encoding/binary" 36 mrand "math/rand" 37 "sync" 38 ) 39 40 type source struct{} 41 42 var lock sync.RWMutex 43 var _ mrand.Source64 = (*source)(nil) // #nosec G404 -- This ensures we meet the interface 44 45 // Seed does nothing when crypto/rand is used as source. 46 func (_ *source) Seed(_ int64) {} 47 48 // Int63 returns uniformly-distributed random (as in CSPRNG) int64 value within [0, 1<<63) range. 49 // Panics if random generator reader cannot return data. 50 func (s *source) Int63() int64 { 51 return int64(s.Uint64() & ^uint64(1<<63)) 52 } 53 54 // Uint64 returns uniformly-distributed random (as in CSPRNG) uint64 value within [0, 1<<64) range. 55 // Panics if random generator reader cannot return data. 56 func (_ *source) Uint64() (val uint64) { 57 lock.RLock() 58 defer lock.RUnlock() 59 if err := binary.Read(rand.Reader, binary.BigEndian, &val); err != nil { 60 panic(err) 61 } 62 return 63 } 64 65 // Rand is alias for underlying random generator. 66 type Rand = mrand.Rand // #nosec G404 67 68 // NewGenerator returns a new generator that uses random values from crypto/rand as a source 69 // (cryptographically secure random number generator). 70 // Panics if crypto/rand input cannot be read. 71 // Use it for everything where crypto secure non-deterministic randomness is required. Performance 72 // takes a hit, so use sparingly. 73 func NewGenerator() *Rand { 74 return mrand.New(&source{}) // #nosec G404 -- excluded 75 } 76 77 // NewDeterministicGenerator returns a random generator which is only seeded with crypto/rand, 78 // but is deterministic otherwise (given seed, produces given results, deterministically). 79 // Panics if crypto/rand input cannot be read. 80 // Use this method for performance, where deterministic pseudo-random behaviour is enough. 81 // Otherwise, rely on NewGenerator(). This method is not cryptographically secure as outputs 82 // can be potentially predicted even without knowledge of the underlying seed. 83 func NewDeterministicGenerator() *Rand { 84 randGen := NewGenerator() 85 return mrand.New(mrand.NewSource(randGen.Int63())) // #nosec G404 -- excluded 86 }