1 # Copyright (C) 2009, 2011 Nominum, Inc.
3 # Permission to use, copy, modify, and distribute this software and its
4 # documentation for any purpose with or without fee is hereby granted,
5 # provided that the above copyright notice and this permission notice
6 # appear in all copies.
8 # THE SOFTWARE IS PROVIDED "AS IS" AND NOMINUM DISCLAIMS ALL WARRANTIES
9 # WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 # MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL NOMINUM BE LIABLE FOR
11 # ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 # WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 # ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
14 # OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
19 import threading
as _threading
21 import dummy_threading
as _threading
23 class EntropyPool(object):
24 def __init__(self
, seed
=None):
28 self
.lock
= _threading
.Lock()
31 self
.hash = hashlib
.sha1()
42 self
.pool
= '\0' * self
.hash_len
49 def stir(self
, entropy
, already_locked
=False):
50 if not already_locked
:
53 bytes
= [ord(c
) for c
in self
.pool
]
55 if self
.pool_index
== self
.hash_len
:
58 bytes
[self
.pool_index
] ^
= b
60 self
.pool
= ''.join([chr(c
) for c
in bytes
])
62 if not already_locked
:
65 def _maybe_seed(self
):
71 r
= file('/dev/urandom', 'r', 0)
77 seed
= str(time
.time())
85 if self
.digest
is None or self
.next_byte
== self
.hash_len
:
86 self
.hash.update(self
.pool
)
87 self
.digest
= self
.hash.digest()
88 self
.stir(self
.digest
, True)
90 value
= ord(self
.digest
[self
.next_byte
])
97 return self
.random_8() * 256 + self
.random_8()
100 return self
.random_16() * 65536 + self
.random_16()
102 def random_between(self
, first
, last
):
103 size
= last
- first
+ 1
104 if size
> 4294967296L:
105 raise ValueError('too big')
107 rand
= self
.random_32
110 rand
= self
.random_16
115 return (first
+ size
* rand() // (max + 1))
120 return pool
.random_16()
122 def between(first
, last
):
123 return pool
.random_between(first
, last
)