2023-01-30 16:27:06 +03:00
|
|
|
package mox
|
|
|
|
|
|
|
|
import (
|
|
|
|
cryptorand "crypto/rand"
|
|
|
|
"encoding/binary"
|
|
|
|
"fmt"
|
2024-11-29 15:45:19 +03:00
|
|
|
mathrand2 "math/rand/v2"
|
2023-11-09 19:15:46 +03:00
|
|
|
"sync"
|
2023-01-30 16:27:06 +03:00
|
|
|
)
|
|
|
|
|
2023-11-09 19:15:46 +03:00
|
|
|
type rand struct {
|
2024-11-29 15:45:19 +03:00
|
|
|
rand *mathrand2.Rand
|
2023-11-09 19:15:46 +03:00
|
|
|
sync.Mutex
|
|
|
|
}
|
|
|
|
|
2024-03-07 12:05:35 +03:00
|
|
|
// NewPseudoRand returns a new PRNG seeded with random bytes from crypto/rand. Its
|
|
|
|
// functions can be called concurrently.
|
2023-11-09 19:15:46 +03:00
|
|
|
func NewPseudoRand() *rand {
|
2024-11-29 15:45:19 +03:00
|
|
|
var seed [32]byte
|
|
|
|
if _, err := cryptorand.Read(seed[:]); err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
return &rand{rand: mathrand2.New(mathrand2.NewChaCha8(seed))}
|
2024-03-07 12:05:35 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *rand) Float64() float64 {
|
|
|
|
r.Lock()
|
|
|
|
defer r.Unlock()
|
|
|
|
return r.rand.Float64()
|
|
|
|
}
|
|
|
|
|
2024-11-29 15:45:19 +03:00
|
|
|
func (r *rand) IntN(n int) int {
|
2023-11-09 19:15:46 +03:00
|
|
|
r.Lock()
|
|
|
|
defer r.Unlock()
|
2024-11-29 15:45:19 +03:00
|
|
|
return r.rand.IntN(n)
|
2023-01-30 16:27:06 +03:00
|
|
|
}
|
|
|
|
|
2023-02-05 18:29:03 +03:00
|
|
|
// CryptoRandInt returns a cryptographically random number.
|
|
|
|
func CryptoRandInt() int64 {
|
2023-01-30 16:27:06 +03:00
|
|
|
buf := make([]byte, 8)
|
|
|
|
_, err := cryptorand.Read(buf)
|
|
|
|
if err != nil {
|
|
|
|
panic(fmt.Errorf("reading random bytes: %v", err))
|
|
|
|
}
|
|
|
|
return int64(binary.LittleEndian.Uint64(buf))
|
|
|
|
}
|