github.com/annchain/OG@v0.0.9/deprecated/ogcrypto/random.go (about) 1 // Copyright 2017 Baptist-Publication Information Technology Services Co.,Ltd. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package ogcrypto 16 17 import ( 18 "crypto/aes" 19 "crypto/cipher" 20 crand "crypto/rand" 21 "encoding/hex" 22 "github.com/annchain/OG/deprecated" 23 "io" 24 "sync" 25 ) 26 27 var gRandInfo *randInfo 28 29 func init() { 30 gRandInfo = &randInfo{} 31 gRandInfo.MixEntropy(randBytes(32)) // init 32 } 33 34 // Mix additional bytes of randomness, e.g. from hardware, user-input, etc. 35 // It is OK to call it multiple times. It does not diminish security. 36 func MixEntropy(seedBytes []byte) { 37 gRandInfo.MixEntropy(seedBytes) 38 } 39 40 // This only uses the OS's randomness 41 func randBytes(numBytes int) []byte { 42 b := make([]byte, numBytes) 43 _, err := crand.Read(b) 44 if err != nil { 45 panic(err) 46 } 47 return b 48 } 49 50 // This uses the OS and the Seed(s). 51 func CRandBytes(numBytes int) []byte { 52 b := make([]byte, numBytes) 53 _, err := gRandInfo.Read(b) 54 if err != nil { 55 panic(err) 56 } 57 return b 58 } 59 60 // RandHex(24) gives 96 bits of randomness, strong enough for most purposes. 61 func CRandHex(numDigits int) string { 62 return hex.EncodeToString(CRandBytes(numDigits / 2)) 63 } 64 65 // Returns a crand.Reader mixed with user-supplied entropy 66 func CReader() io.Reader { 67 return gRandInfo 68 } 69 70 //-------------------------------------------------------------------------------- 71 72 type randInfo struct { 73 mtx sync.Mutex 74 seedBytes [32]byte 75 cipherAES256 cipher.Block 76 streamAES256 cipher.Stream 77 reader io.Reader 78 } 79 80 // You can call this as many times as you'd like. 81 // XXX TODO review 82 func (ri *randInfo) MixEntropy(seedBytes []byte) { 83 ri.mtx.Lock() 84 defer ri.mtx.Unlock() 85 // Make new ri.seedBytes 86 hashBytes := deprecated.Sha256(seedBytes) 87 hashBytes32 := [32]byte{} 88 copy(hashBytes32[:], hashBytes) 89 ri.seedBytes = xorBytes32(ri.seedBytes, hashBytes32) 90 // Create new cipher.Block 91 var err error 92 ri.cipherAES256, err = aes.NewCipher(ri.seedBytes[:]) 93 if err != nil { 94 panic("Error creating AES256 cipher: " + err.Error()) 95 } 96 // Create new stream 97 ri.streamAES256 = cipher.NewCTR(ri.cipherAES256, randBytes(aes.BlockSize)) 98 // Create new reader 99 ri.reader = &cipher.StreamReader{S: ri.streamAES256, R: crand.Reader} 100 } 101 102 func (ri *randInfo) Read(b []byte) (n int, err error) { 103 ri.mtx.Lock() 104 defer ri.mtx.Unlock() 105 return ri.reader.Read(b) 106 } 107 108 func xorBytes32(bytesA [32]byte, bytesB [32]byte) (res [32]byte) { 109 for i, b := range bytesA { 110 res[i] = b ^ bytesB[i] 111 } 112 return res 113 }