github.com/Finschia/ostracon@v1.1.5/libs/rand/random.go (about)

     1  package rand
     2  
     3  import (
     4  	crand "crypto/rand"
     5  	mrand "math/rand"
     6  	"time"
     7  
     8  	tmsync "github.com/Finschia/ostracon/libs/sync"
     9  )
    10  
    11  const (
    12  	strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
    13  )
    14  
    15  // Rand is a prng, that is seeded with OS randomness.
    16  // The OS randomness is obtained from crypto/rand, however none of the provided
    17  // methods are suitable for cryptographic usage.
    18  // They all utilize math/rand's prng internally.
    19  //
    20  // All of the methods here are suitable for concurrent use.
    21  // This is achieved by using a mutex lock on all of the provided methods.
    22  type Rand struct {
    23  	tmsync.Mutex
    24  	rand *mrand.Rand
    25  }
    26  
    27  var grand *Rand
    28  
    29  func init() {
    30  	grand = NewRand()
    31  }
    32  
    33  func NewRand() *Rand {
    34  	rand := &Rand{}
    35  	rand.init()
    36  	return rand
    37  }
    38  
    39  func (r *Rand) init() {
    40  	bz := cRandBytes(8)
    41  	var seed uint64
    42  	for i := 0; i < 8; i++ {
    43  		seed |= uint64(bz[i])
    44  		seed <<= 8
    45  	}
    46  	r.reset(int64(seed))
    47  }
    48  
    49  func (r *Rand) reset(seed int64) {
    50  	r.rand = mrand.New(mrand.NewSource(seed)) //nolint:gosec,nolintlint // G404: Use of weak random number generator
    51  }
    52  
    53  //----------------------------------------
    54  // Global functions
    55  
    56  func Seed(seed int64) {
    57  	grand.Seed(seed)
    58  }
    59  
    60  func Str(length int) string {
    61  	return grand.Str(length)
    62  }
    63  
    64  func Uint16() uint16 {
    65  	return grand.Uint16()
    66  }
    67  
    68  func Uint32() uint32 {
    69  	return grand.Uint32()
    70  }
    71  
    72  func Uint64() uint64 {
    73  	return grand.Uint64()
    74  }
    75  
    76  func Uint() uint {
    77  	return grand.Uint()
    78  }
    79  
    80  func Int16() int16 {
    81  	return grand.Int16()
    82  }
    83  
    84  func Int32() int32 {
    85  	return grand.Int32()
    86  }
    87  
    88  func Int64() int64 {
    89  	return grand.Int64()
    90  }
    91  
    92  func Int() int {
    93  	return grand.Int()
    94  }
    95  
    96  func Int31() int32 {
    97  	return grand.Int31()
    98  }
    99  
   100  func Int31n(n int32) int32 {
   101  	return grand.Int31n(n)
   102  }
   103  
   104  func Int63() int64 {
   105  	return grand.Int63()
   106  }
   107  
   108  func Int63n(n int64) int64 {
   109  	return grand.Int63n(n)
   110  }
   111  
   112  func Bool() bool {
   113  	return grand.Bool()
   114  }
   115  
   116  func Float32() float32 {
   117  	return grand.Float32()
   118  }
   119  
   120  func Float64() float64 {
   121  	return grand.Float64()
   122  }
   123  
   124  func Time() time.Time {
   125  	return grand.Time()
   126  }
   127  
   128  func Bytes(n int) []byte {
   129  	return grand.Bytes(n)
   130  }
   131  
   132  func Intn(n int) int {
   133  	return grand.Intn(n)
   134  }
   135  
   136  func Perm(n int) []int {
   137  	return grand.Perm(n)
   138  }
   139  
   140  //----------------------------------------
   141  // Rand methods
   142  
   143  func (r *Rand) Seed(seed int64) {
   144  	r.Lock()
   145  	r.reset(seed)
   146  	r.Unlock()
   147  }
   148  
   149  // Str constructs a random alphanumeric string of given length.
   150  func (r *Rand) Str(length int) string {
   151  	if length <= 0 {
   152  		return ""
   153  	}
   154  
   155  	chars := []byte{}
   156  MAIN_LOOP:
   157  	for {
   158  		val := r.Int63()
   159  		for i := 0; i < 10; i++ {
   160  			v := int(val & 0x3f) // rightmost 6 bits
   161  			if v >= 62 {         // only 62 characters in strChars
   162  				val >>= 6
   163  				continue
   164  			} else {
   165  				chars = append(chars, strChars[v])
   166  				if len(chars) == length {
   167  					break MAIN_LOOP
   168  				}
   169  				val >>= 6
   170  			}
   171  		}
   172  	}
   173  
   174  	return string(chars)
   175  }
   176  
   177  func (r *Rand) Uint16() uint16 {
   178  	return uint16(r.Uint32() & (1<<16 - 1))
   179  }
   180  
   181  func (r *Rand) Uint32() uint32 {
   182  	r.Lock()
   183  	u32 := r.rand.Uint32()
   184  	r.Unlock()
   185  	return u32
   186  }
   187  
   188  func (r *Rand) Uint64() uint64 {
   189  	return uint64(r.Uint32())<<32 + uint64(r.Uint32())
   190  }
   191  
   192  func (r *Rand) Uint() uint {
   193  	r.Lock()
   194  	i := r.rand.Int()
   195  	r.Unlock()
   196  	return uint(i)
   197  }
   198  
   199  func (r *Rand) Int16() int16 {
   200  	return int16(r.Uint32() & (1<<16 - 1))
   201  }
   202  
   203  func (r *Rand) Int32() int32 {
   204  	return int32(r.Uint32())
   205  }
   206  
   207  func (r *Rand) Int64() int64 {
   208  	return int64(r.Uint64())
   209  }
   210  
   211  func (r *Rand) Int() int {
   212  	r.Lock()
   213  	i := r.rand.Int()
   214  	r.Unlock()
   215  	return i
   216  }
   217  
   218  func (r *Rand) Int31() int32 {
   219  	r.Lock()
   220  	i31 := r.rand.Int31()
   221  	r.Unlock()
   222  	return i31
   223  }
   224  
   225  func (r *Rand) Int31n(n int32) int32 {
   226  	r.Lock()
   227  	i31n := r.rand.Int31n(n)
   228  	r.Unlock()
   229  	return i31n
   230  }
   231  
   232  func (r *Rand) Int63() int64 {
   233  	r.Lock()
   234  	i63 := r.rand.Int63()
   235  	r.Unlock()
   236  	return i63
   237  }
   238  
   239  func (r *Rand) Int63n(n int64) int64 {
   240  	r.Lock()
   241  	i63n := r.rand.Int63n(n)
   242  	r.Unlock()
   243  	return i63n
   244  }
   245  
   246  func (r *Rand) Float32() float32 {
   247  	r.Lock()
   248  	f32 := r.rand.Float32()
   249  	r.Unlock()
   250  	return f32
   251  }
   252  
   253  func (r *Rand) Float64() float64 {
   254  	r.Lock()
   255  	f64 := r.rand.Float64()
   256  	r.Unlock()
   257  	return f64
   258  }
   259  
   260  func (r *Rand) Time() time.Time {
   261  	return time.Unix(int64(r.Uint64()), 0)
   262  }
   263  
   264  // Bytes returns n random bytes generated from the internal
   265  // prng.
   266  func (r *Rand) Bytes(n int) []byte {
   267  	// cRandBytes isn't guaranteed to be fast so instead
   268  	// use random bytes generated from the internal PRNG
   269  	bs := make([]byte, n)
   270  	for i := 0; i < len(bs); i++ {
   271  		bs[i] = byte(r.Int() & 0xFF)
   272  	}
   273  	return bs
   274  }
   275  
   276  // Intn returns, as an int, a uniform pseudo-random number in the range [0, n).
   277  // It panics if n <= 0.
   278  func (r *Rand) Intn(n int) int {
   279  	r.Lock()
   280  	i := r.rand.Intn(n)
   281  	r.Unlock()
   282  	return i
   283  }
   284  
   285  // Bool returns a uniformly random boolean
   286  func (r *Rand) Bool() bool {
   287  	// See https://github.com/golang/go/issues/23804#issuecomment-365370418
   288  	// for reasoning behind computing like this
   289  	return r.Int63()%2 == 0
   290  }
   291  
   292  // Perm returns a pseudo-random permutation of n integers in [0, n).
   293  func (r *Rand) Perm(n int) []int {
   294  	r.Lock()
   295  	perm := r.rand.Perm(n)
   296  	r.Unlock()
   297  	return perm
   298  }
   299  
   300  // NOTE: This relies on the os's random number generator.
   301  // For real security, we should salt that with some seed.
   302  // See github.com/Finschia/ostracon/crypto for a more secure reader.
   303  func cRandBytes(numBytes int) []byte {
   304  	b := make([]byte, numBytes)
   305  	_, err := crand.Read(b)
   306  	if err != nil {
   307  		panic(err)
   308  	}
   309  	return b
   310  }