github.com/xushiwei/go@v0.0.0-20130601165731-2b9d83f45bc9/src/pkg/crypto/rand/rand_unix.go (about) 1 // Copyright 2010 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 // +build darwin freebsd linux netbsd openbsd plan9 6 7 // Unix cryptographically secure pseudorandom number 8 // generator. 9 10 package rand 11 12 import ( 13 "bufio" 14 "crypto/aes" 15 "crypto/cipher" 16 "io" 17 "os" 18 "runtime" 19 "sync" 20 "time" 21 ) 22 23 // Easy implementation: read from /dev/urandom. 24 // This is sufficient on Linux, OS X, and FreeBSD. 25 26 func init() { 27 if runtime.GOOS == "plan9" { 28 Reader = newReader(nil) 29 } else { 30 Reader = &devReader{name: "/dev/urandom"} 31 } 32 } 33 34 // A devReader satisfies reads by reading the file named name. 35 type devReader struct { 36 name string 37 f io.Reader 38 mu sync.Mutex 39 } 40 41 func (r *devReader) Read(b []byte) (n int, err error) { 42 r.mu.Lock() 43 defer r.mu.Unlock() 44 if r.f == nil { 45 f, err := os.Open(r.name) 46 if f == nil { 47 return 0, err 48 } 49 if runtime.GOOS == "plan9" { 50 r.f = f 51 } else { 52 r.f = bufio.NewReader(f) 53 } 54 } 55 return r.f.Read(b) 56 } 57 58 // Alternate pseudo-random implementation for use on 59 // systems without a reliable /dev/urandom. 60 61 // newReader returns a new pseudorandom generator that 62 // seeds itself by reading from entropy. If entropy == nil, 63 // the generator seeds itself by reading from the system's 64 // random number generator, typically /dev/random. 65 // The Read method on the returned reader always returns 66 // the full amount asked for, or else it returns an error. 67 // 68 // The generator uses the X9.31 algorithm with AES-128, 69 // reseeding after every 1 MB of generated data. 70 func newReader(entropy io.Reader) io.Reader { 71 if entropy == nil { 72 entropy = &devReader{name: "/dev/random"} 73 } 74 return &reader{entropy: entropy} 75 } 76 77 type reader struct { 78 mu sync.Mutex 79 budget int // number of bytes that can be generated 80 cipher cipher.Block 81 entropy io.Reader 82 time, seed, dst, key [aes.BlockSize]byte 83 } 84 85 func (r *reader) Read(b []byte) (n int, err error) { 86 r.mu.Lock() 87 defer r.mu.Unlock() 88 n = len(b) 89 90 for len(b) > 0 { 91 if r.budget == 0 { 92 _, err := io.ReadFull(r.entropy, r.seed[0:]) 93 if err != nil { 94 return n - len(b), err 95 } 96 _, err = io.ReadFull(r.entropy, r.key[0:]) 97 if err != nil { 98 return n - len(b), err 99 } 100 r.cipher, err = aes.NewCipher(r.key[0:]) 101 if err != nil { 102 return n - len(b), err 103 } 104 r.budget = 1 << 20 // reseed after generating 1MB 105 } 106 r.budget -= aes.BlockSize 107 108 // ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES. 109 // 110 // single block: 111 // t = encrypt(time) 112 // dst = encrypt(t^seed) 113 // seed = encrypt(t^dst) 114 ns := time.Now().UnixNano() 115 r.time[0] = byte(ns >> 56) 116 r.time[1] = byte(ns >> 48) 117 r.time[2] = byte(ns >> 40) 118 r.time[3] = byte(ns >> 32) 119 r.time[4] = byte(ns >> 24) 120 r.time[5] = byte(ns >> 16) 121 r.time[6] = byte(ns >> 8) 122 r.time[7] = byte(ns) 123 r.cipher.Encrypt(r.time[0:], r.time[0:]) 124 for i := 0; i < aes.BlockSize; i++ { 125 r.dst[i] = r.time[i] ^ r.seed[i] 126 } 127 r.cipher.Encrypt(r.dst[0:], r.dst[0:]) 128 for i := 0; i < aes.BlockSize; i++ { 129 r.seed[i] = r.time[i] ^ r.dst[i] 130 } 131 r.cipher.Encrypt(r.seed[0:], r.seed[0:]) 132 133 m := copy(b, r.dst[0:]) 134 b = b[m:] 135 } 136 137 return n, nil 138 }