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