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