github.com/safing/portbase@v0.19.5/rng/get.go (about) 1 package rng 2 3 import ( 4 "encoding/binary" 5 "errors" 6 "io" 7 "math" 8 "time" 9 ) 10 11 const ( 12 reseedAfterSeconds = 600 // ten minutes 13 reseedAfterBytes = 1048576 // one megabyte 14 ) 15 16 var ( 17 // Reader provides a global instance to read from the RNG. 18 Reader io.Reader 19 20 rngBytesRead uint64 21 rngLastFeed = time.Now() 22 ) 23 24 // reader provides an io.Reader interface. 25 type reader struct{} 26 27 func init() { 28 Reader = reader{} 29 } 30 31 func checkEntropy() (err error) { 32 if !rngReady { 33 return errors.New("RNG is not ready yet") 34 } 35 if rngBytesRead > reseedAfterBytes || 36 int(time.Since(rngLastFeed).Seconds()) > reseedAfterSeconds { 37 select { 38 case r := <-rngFeeder: 39 rng.Reseed(r) 40 rngBytesRead = 0 41 rngLastFeed = time.Now() 42 case <-time.After(1 * time.Second): 43 return errors.New("failed to get new entropy") 44 } 45 } 46 return nil 47 } 48 49 // Read reads random bytes into the supplied byte slice. 50 func Read(b []byte) (n int, err error) { 51 rngLock.Lock() 52 defer rngLock.Unlock() 53 54 if err := checkEntropy(); err != nil { 55 return 0, err 56 } 57 58 return copy(b, rng.PseudoRandomData(uint(len(b)))), nil 59 } 60 61 // Read implements the io.Reader interface. 62 func (r reader) Read(b []byte) (n int, err error) { 63 return Read(b) 64 } 65 66 // Bytes allocates a new byte slice of given length and fills it with random data. 67 func Bytes(n int) ([]byte, error) { 68 rngLock.Lock() 69 defer rngLock.Unlock() 70 71 if err := checkEntropy(); err != nil { 72 return nil, err 73 } 74 75 return rng.PseudoRandomData(uint(n)), nil 76 } 77 78 // Number returns a random number from 0 to (incl.) max. 79 func Number(max uint64) (uint64, error) { 80 secureLimit := math.MaxUint64 - (math.MaxUint64 % max) 81 max++ 82 83 for { 84 randomBytes, err := Bytes(8) 85 if err != nil { 86 return 0, err 87 } 88 89 candidate := binary.LittleEndian.Uint64(randomBytes) 90 if candidate < secureLimit { 91 return candidate % max, nil 92 } 93 } 94 }