forked from neatlib/crypto-go
/
random.go
executable file
·90 lines (73 loc) · 1.67 KB
/
random.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
package crypto
import (
"crypto/aes"
"crypto/cipher"
crand "crypto/rand"
"encoding/hex"
"io"
"sync"
. "github.com/neatio-net/common-go"
)
var gRandInfo *randInfo
func init() {
gRandInfo = &randInfo{}
gRandInfo.MixEntropy(randBytes(32))
}
func MixEntropy(seedBytes []byte) {
gRandInfo.MixEntropy(seedBytes)
}
func randBytes(numBytes int) []byte {
b := make([]byte, numBytes)
_, err := crand.Read(b)
if err != nil {
PanicCrisis(err)
}
return b
}
func CRandBytes(numBytes int) []byte {
b := make([]byte, numBytes)
_, err := gRandInfo.Read(b)
if err != nil {
PanicCrisis(err)
}
return b
}
func CRandHex(numDigits int) string {
return hex.EncodeToString(CRandBytes(numDigits / 2))
}
func CReader() io.Reader {
return gRandInfo
}
type randInfo struct {
mtx sync.Mutex
seedBytes [32]byte
cipherAES256 cipher.Block
streamAES256 cipher.Stream
reader io.Reader
}
func (ri *randInfo) MixEntropy(seedBytes []byte) {
ri.mtx.Lock()
defer ri.mtx.Unlock()
hashBytes := Sha256(seedBytes)
hashBytes32 := [32]byte{}
copy(hashBytes32[:], hashBytes)
ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32)
var err error
ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:])
if err != nil {
PanicSanity("Error creating AES256 cipher: " + err.Error())
}
ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize))
ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader}
}
func (ri *randInfo) Read(b []byte) (n int, err error) {
ri.mtx.Lock()
defer ri.mtx.Unlock()
return ri.reader.Read(b)
}
func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) {
for i, b := range bytesA {
res[i] = b ^ bytesB[i]
}
return res
}