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 = '\0' * 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 bytes = [ord(c) for c in self.pool]
54 for c in entropy:
55 if self.pool_index == self.hash_len:
56 self.pool_index = 0
57 b = ord(c) & 0xff
58 bytes[self.pool_index] ^= b
59 self.pool_index += 1
60 self.pool = ''.join([chr(c) for c in bytes])
61 finally:
62 if not already_locked:
63 self.lock.release()
64
66 if not self.seeded:
67 try:
68 seed = os.urandom(16)
69 except:
70 try:
71 r = file('/dev/urandom', 'r', 0)
72 try:
73 seed = r.read(16)
74 finally:
75 r.close()
76 except:
77 seed = str(time.time())
78 self.seeded = True
79 self.stir(seed, True)
80
82 self.lock.acquire()
83 self._maybe_seed()
84 try:
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)
89 self.next_byte = 0
90 value = ord(self.digest[self.next_byte])
91 self.next_byte += 1
92 finally:
93 self.lock.release()
94 return value
95
98
101
103 size = last - first + 1
104 if size > 4294967296L:
105 raise ValueError('too big')
106 if size > 65536:
107 rand = self.random_32
108 max = 4294967295L
109 elif size > 256:
110 rand = self.random_16
111 max = 65535
112 else:
113 rand = self.random_8
114 max = 255
115 return (first + size * rand() // (max + 1))
116
117 pool = EntropyPool()
118
121
124