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.
5 // +build darwin dragonfly freebsd linux nacl netbsd openbsd plan9 solaris
7 // Unix cryptographically secure pseudorandom number
23 // Easy implementation: read from /dev/urandom.
24 // This is sufficient on Linux, OS X, and FreeBSD.
27 if runtime
.GOOS
== "plan9" {
28 Reader
= newReader(nil)
30 Reader
= &devReader
{name
: "/dev/urandom"}
34 // A devReader satisfies reads by reading the file named name.
35 type devReader
struct {
41 func (r
*devReader
) Read(b
[]byte) (n
int, err error
) {
45 f
, err
:= os
.Open(r
.name
)
49 if runtime
.GOOS
== "plan9" {
52 r
.f
= bufio
.NewReader(f
)
58 // Alternate pseudo-random implementation for use on
59 // systems without a reliable /dev/urandom.
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.
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
{
72 entropy
= &devReader
{name
: "/dev/random"}
74 return &reader
{entropy
: entropy
}
79 budget
int // number of bytes that can be generated
82 time
, seed
, dst
, key
[aes
.BlockSize
]byte
85 func (r
*reader
) Read(b
[]byte) (n
int, err error
) {
92 _
, err
:= io
.ReadFull(r
.entropy
, r
.seed
[0:])
94 return n
- len(b
), err
96 _
, err
= io
.ReadFull(r
.entropy
, r
.key
[0:])
98 return n
- len(b
), err
100 r
.cipher
, err
= aes
.NewCipher(r
.key
[0:])
102 return n
- len(b
), err
104 r
.budget
= 1 << 20 // reseed after generating 1MB
106 r
.budget
-= aes
.BlockSize
108 // ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
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)
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
]
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
]
131 r
.cipher
.Encrypt(r
.seed
[0:], r
.seed
[0:])
133 m
:= copy(b
, r
.dst
[0:])