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