1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import os
17 import time
18 from ._compat import long, binary_type
19 try:
20 import threading as _threading
21 except ImportError:
22 import dummy_threading as _threading
23
24
26
28 self.pool_index = 0
29 self.digest = None
30 self.next_byte = 0
31 self.lock = _threading.Lock()
32 try:
33 import hashlib
34 self.hash = hashlib.sha1()
35 self.hash_len = 20
36 except:
37 try:
38 import sha
39 self.hash = sha.new()
40 self.hash_len = 20
41 except:
42 import md5
43 self.hash = md5.new()
44 self.hash_len = 16
45 self.pool = bytearray(b'\0' * self.hash_len)
46 if seed is not None:
47 self.stir(bytearray(seed))
48 self.seeded = True
49 else:
50 self.seeded = False
51
52 - def stir(self, entropy, already_locked=False):
53 if not already_locked:
54 self.lock.acquire()
55 try:
56 for c in entropy:
57 if self.pool_index == self.hash_len:
58 self.pool_index = 0
59 b = c & 0xff
60 self.pool[self.pool_index] ^= b
61 self.pool_index += 1
62 finally:
63 if not already_locked:
64 self.lock.release()
65
67 if not self.seeded:
68 try:
69 seed = os.urandom(16)
70 except:
71 try:
72 r = open('/dev/urandom', 'rb', 0)
73 try:
74 seed = r.read(16)
75 finally:
76 r.close()
77 except:
78 seed = str(time.time())
79 self.seeded = True
80 seed = bytearray(seed)
81 self.stir(seed, True)
82
84 self.lock.acquire()
85 try:
86 self._maybe_seed()
87 if self.digest is None or self.next_byte == self.hash_len:
88 self.hash.update(binary_type(self.pool))
89 self.digest = bytearray(self.hash.digest())
90 self.stir(self.digest, True)
91 self.next_byte = 0
92 value = self.digest[self.next_byte]
93 self.next_byte += 1
94 finally:
95 self.lock.release()
96 return value
97
100
103
105 size = last - first + 1
106 if size > long(4294967296):
107 raise ValueError('too big')
108 if size > 65536:
109 rand = self.random_32
110 max = long(4294967295)
111 elif size > 256:
112 rand = self.random_16
113 max = 65535
114 else:
115 rand = self.random_8
116 max = 255
117 return (first + size * rand() // (max + 1))
118
119 pool = EntropyPool()
120
121
124
125
128