11 . "github.com/tendermint/tmlibs/common"
14 var gRandInfo *randInfo
17 gRandInfo = &randInfo{}
18 gRandInfo.MixEntropy(randBytes(32)) // Init
21 // Mix additional bytes of randomness, e.g. from hardware, user-input, etc.
22 // It is OK to call it multiple times. It does not diminish security.
23 func MixEntropy(seedBytes []byte) {
24 gRandInfo.MixEntropy(seedBytes)
27 // This only uses the OS's randomness
28 func randBytes(numBytes int) []byte {
29 b := make([]byte, numBytes)
30 _, err := crand.Read(b)
37 // This uses the OS and the Seed(s).
38 func CRandBytes(numBytes int) []byte {
39 b := make([]byte, numBytes)
40 _, err := gRandInfo.Read(b)
47 // RandHex(24) gives 96 bits of randomness, strong enough for most purposes.
48 func CRandHex(numDigits int) string {
49 return hex.EncodeToString(CRandBytes(numDigits / 2))
52 // Returns a crand.Reader mixed with user-supplied entropy
53 func CReader() io.Reader {
57 //--------------------------------------------------------------------------------
59 type randInfo struct {
62 cipherAES256 cipher.Block
63 streamAES256 cipher.Stream
67 // You can call this as many times as you'd like.
69 func (ri *randInfo) MixEntropy(seedBytes []byte) {
72 // Make new ri.seedBytes
73 hashBytes := Sha256(seedBytes)
74 hashBytes32 := [32]byte{}
75 copy(hashBytes32[:], hashBytes)
76 ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32)
77 // Create new cipher.Block
79 ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:])
81 PanicSanity("Error creating AES256 cipher: " + err.Error())
84 ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize))
86 ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader}
89 func (ri *randInfo) Read(b []byte) (n int, err error) {
92 return ri.reader.Read(b)
95 func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) {
96 for i, b := range bytesA {
97 res[i] = b ^ bytesB[i]