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 const urandomDevice
= "/dev/urandom"
25 // Easy implementation: read from /dev/urandom.
26 // This is sufficient on Linux, OS X, and FreeBSD.
29 if runtime
.GOOS
== "plan9" {
30 Reader
= newReader(nil)
32 Reader
= &devReader
{name
: urandomDevice
}
36 // A devReader satisfies reads by reading the file named name.
37 type devReader
struct {
43 // altGetRandom if non-nil specifies an OS-specific function to get
44 // urandom-style randomness.
45 var altGetRandom
func([]byte) (ok
bool)
47 func (r
*devReader
) Read(b
[]byte) (n
int, err error
) {
48 if altGetRandom
!= nil && r
.name
== urandomDevice
&& altGetRandom(b
) {
54 f
, err
:= os
.Open(r
.name
)
58 if runtime
.GOOS
== "plan9" {
61 r
.f
= bufio
.NewReader(f
)
67 // Alternate pseudo-random implementation for use on
68 // systems without a reliable /dev/urandom.
70 // newReader returns a new pseudorandom generator that
71 // seeds itself by reading from entropy. If entropy == nil,
72 // the generator seeds itself by reading from the system's
73 // random number generator, typically /dev/random.
74 // The Read method on the returned reader always returns
75 // the full amount asked for, or else it returns an error.
77 // The generator uses the X9.31 algorithm with AES-128,
78 // reseeding after every 1 MB of generated data.
79 func newReader(entropy io
.Reader
) io
.Reader
{
81 entropy
= &devReader
{name
: "/dev/random"}
83 return &reader
{entropy
: entropy
}
88 budget
int // number of bytes that can be generated
91 time
, seed
, dst
, key
[aes
.BlockSize
]byte
94 func (r
*reader
) Read(b
[]byte) (n
int, err error
) {
101 _
, err
:= io
.ReadFull(r
.entropy
, r
.seed
[0:])
103 return n
- len(b
), err
105 _
, err
= io
.ReadFull(r
.entropy
, r
.key
[0:])
107 return n
- len(b
), err
109 r
.cipher
, err
= aes
.NewCipher(r
.key
[0:])
111 return n
- len(b
), err
113 r
.budget
= 1 << 20 // reseed after generating 1MB
115 r
.budget
-= aes
.BlockSize
117 // ANSI X9.31 (== X9.17) algorithm, but using AES in place of 3DES.
121 // dst = encrypt(t^seed)
122 // seed = encrypt(t^dst)
123 ns
:= time
.Now().UnixNano()
124 r
.time
[0] = byte(ns
>> 56)
125 r
.time
[1] = byte(ns
>> 48)
126 r
.time
[2] = byte(ns
>> 40)
127 r
.time
[3] = byte(ns
>> 32)
128 r
.time
[4] = byte(ns
>> 24)
129 r
.time
[5] = byte(ns
>> 16)
130 r
.time
[6] = byte(ns
>> 8)
132 r
.cipher
.Encrypt(r
.time
[0:], r
.time
[0:])
133 for i
:= 0; i
< aes
.BlockSize
; i
++ {
134 r
.dst
[i
] = r
.time
[i
] ^ r
.seed
[i
]
136 r
.cipher
.Encrypt(r
.dst
[0:], r
.dst
[0:])
137 for i
:= 0; i
< aes
.BlockSize
; i
++ {
138 r
.seed
[i
] = r
.time
[i
] ^ r
.dst
[i
]
140 r
.cipher
.Encrypt(r
.seed
[0:], r
.seed
[0:])
142 m
:= copy(b
, r
.dst
[0:])