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  }