github.com/number571/tendermint@v0.34.11-gost/libs/rand/random.go (about) 1 package rand 2 3 import ( 4 crand "crypto/rand" 5 "encoding/binary" 6 "fmt" 7 mrand "math/rand" 8 ) 9 10 const ( 11 strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters 12 ) 13 14 func init() { 15 Reseed() 16 } 17 18 // NewRand returns a prng, that is seeded with OS randomness. 19 // The OS randomness is obtained from crypto/rand, however, like with any math/rand.Rand 20 // object none of the provided methods are suitable for cryptographic usage. 21 // 22 // Note that the returned instance of math/rand's Rand is not 23 // suitable for concurrent use by multiple goroutines. 24 // 25 // For concurrent use, call Reseed to reseed math/rand's default source and 26 // use math/rand's top-level convenience functions instead. 27 func NewRand() *mrand.Rand { 28 seed := crandSeed() 29 // nolint:gosec // G404: Use of weak random number generator 30 return mrand.New(mrand.NewSource(seed)) 31 } 32 33 // Reseed conveniently re-seeds the default Source of math/rand with 34 // randomness obtained from crypto/rand. 35 // 36 // Note that this does not make math/rand suitable for cryptographic usage. 37 // 38 // Use math/rand's top-level convenience functions remain suitable 39 // for concurrent use by multiple goroutines. 40 func Reseed() { 41 seed := crandSeed() 42 mrand.Seed(seed) 43 } 44 45 // Str constructs a random alphanumeric string of given length 46 // from math/rand's global default Source. 47 func Str(length int) string { 48 if length <= 0 { 49 return "" 50 } 51 52 chars := make([]byte, 0, length) 53 for { 54 // nolint:gosec // G404: Use of weak random number generator 55 val := mrand.Int63() 56 for i := 0; i < 10; i++ { 57 v := int(val & 0x3f) // rightmost 6 bits 58 if v >= 62 { // only 62 characters in strChars 59 val >>= 6 60 continue 61 } else { 62 chars = append(chars, strChars[v]) 63 if len(chars) == length { 64 return string(chars) 65 } 66 val >>= 6 67 } 68 } 69 } 70 } 71 72 // Bytes returns n random bytes generated from math/rand's global default Source. 73 func Bytes(n int) []byte { 74 bs := make([]byte, n) 75 for i := 0; i < len(bs); i++ { 76 // nolint:gosec // G404: Use of weak random number generator 77 bs[i] = byte(mrand.Int() & 0xFF) 78 } 79 return bs 80 } 81 82 func crandSeed() int64 { 83 var seed int64 84 err := binary.Read(crand.Reader, binary.BigEndian, &seed) 85 if err != nil { 86 panic(fmt.Sprintf("could nor read random seed from crypto/rand: %v", err)) 87 } 88 return seed 89 }