- package rand
-
- import (
- crand "crypto/rand"
- "encoding/binary"
- "fmt"
- mrand "math/rand"
- )
-
- const (
- strChars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz" // 62 characters
- )
-
- func init() {
- Reseed()
- }
-
- // NewRand returns a prng, that is seeded with OS randomness.
- // The OS randomness is obtained from crypto/rand, however, like with any math/rand.Rand
- // object none of the provided methods are suitable for cryptographic usage.
- //
- // Note that the returned instance of math/rand's Rand is not
- // suitable for concurrent use by multiple goroutines.
- //
- // For concurrent use, call Reseed to reseed math/rand's default source and
- // use math/rand's top-level convenience functions instead.
- func NewRand() *mrand.Rand {
- seed := crandSeed()
- // nolint:gosec // G404: Use of weak random number generator
- return mrand.New(mrand.NewSource(seed))
- }
-
- // Reseed conveniently re-seeds the default Source of math/rand with
- // randomness obtained from crypto/rand.
- //
- // Note that this does not make math/rand suitable for cryptographic usage.
- //
- // Use math/rand's top-level convenience functions remain suitable
- // for concurrent use by multiple goroutines.
- func Reseed() {
- seed := crandSeed()
- mrand.Seed(seed)
- }
-
- // Str constructs a random alphanumeric string of given length
- // from math/rand's global default Source.
- func Str(length int) string {
- if length <= 0 {
- return ""
- }
-
- chars := make([]byte, 0, length)
- for {
- // nolint:gosec // G404: Use of weak random number generator
- val := mrand.Int63()
- for i := 0; i < 10; i++ {
- v := int(val & 0x3f) // rightmost 6 bits
- if v >= 62 { // only 62 characters in strChars
- val >>= 6
- continue
- } else {
- chars = append(chars, strChars[v])
- if len(chars) == length {
- return string(chars)
- }
- val >>= 6
- }
- }
- }
- }
-
- // Bytes returns n random bytes generated from math/rand's global default Source.
- func Bytes(n int) []byte {
- bs := make([]byte, n)
- for i := 0; i < len(bs); i++ {
- // nolint:gosec // G404: Use of weak random number generator
- bs[i] = byte(mrand.Int() & 0xFF)
- }
- return bs
- }
-
- func crandSeed() int64 {
- var seed int64
- err := binary.Read(crand.Reader, binary.BigEndian, &seed)
- if err != nil {
- panic(fmt.Sprintf("could nor read random seed from crypto/rand: %v", err))
- }
- return seed
- }
|