1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21 import sys
22 import threading
23 from Crypto.Util.randpool import RandomPool as _RandomPool
24
25 try:
26 import platform
27 except ImportError:
28 platform = None
29
31 assert len(a) == len(b)
32 return "".join(map(lambda x, y: chr(ord(x) ^ ord(y)), a, b))
33
34
35
36
37
38
39
40
41
42
43
44 if ((platform is not None and platform.system().lower() == 'windows') or
45 sys.platform == 'win32'):
46
47 from paramiko import rng_win32
48 rng_device = rng_win32.open_rng_device()
49 else:
50
51 from paramiko import rng_posix
52 rng_device = rng_posix.open_rng_device()
53
54
56 """Wrapper around RandomPool guaranteeing strong random numbers.
57
58 Crypto.Util.randpool.RandomPool will silently operate even if it is seeded
59 with little or no entropy, and it provides no prediction resistance if its
60 state is ever compromised throughout its runtime. It is also not thread-safe.
61
62 This wrapper augments RandomPool by XORing its output with random bits from
63 the operating system, and by controlling access to the underlying
64 RandomPool using an exclusive lock.
65 """
66
68 if instance is None:
69 instance = _RandomPool()
70 self.randpool = instance
71 self.randpool_lock = threading.Lock()
72 self.entropy = rng_device
73
74
75 self.randpool.stir(self.entropy.read(32))
76 self.entropy.randomize()
77
78 - def stir(self, s=''):
79 self.randpool_lock.acquire()
80 try:
81 self.randpool.stir(s)
82 finally:
83 self.randpool_lock.release()
84 self.entropy.randomize()
85
87 self.randpool_lock.acquire()
88 try:
89 self.randpool.randomize(N)
90 finally:
91 self.randpool_lock.release()
92 self.entropy.randomize()
93
95 self.randpool_lock.acquire()
96 try:
97 self.randpool.add_event(s)
98 finally:
99 self.randpool_lock.release()
100
102 self.randpool_lock.acquire()
103 try:
104 randpool_data = self.randpool.get_bytes(N)
105 finally:
106 self.randpool_lock.release()
107 entropy_data = self.entropy.read(N)
108 result = _strxor(randpool_data, entropy_data)
109 assert len(randpool_data) == N and len(entropy_data) == N and len(result) == N
110 return result
111
112
113