1 """Module containing a cryptographic-quality source of randomness and
2 other cryptographically useful functionality
3
4 Python 2.4 needs no external support for this module, nor does Python
5 2.3 on a system with /dev/urandom.
6
7 Other configurations will need a quality source of random bytes and
8 access to a function that will convert binary strings to long
9 integers. This module will work with the Python Cryptography Toolkit
10 (pycrypto) if it is present. pycrypto can be found with a search
11 engine, but is currently found at:
12
13 http://www.amk.ca/python/code/crypto
14 """
15
16 __all__ = [
17 'base64ToLong',
18 'binaryToLong',
19 'hmacSha1',
20 'hmacSha256',
21 'longToBase64',
22 'longToBinary',
23 'randomString',
24 'randrange',
25 'sha1',
26 'sha256',
27 ]
28
29 import hmac
30 import os
31 import random
32
33 from openid.oidutil import toBase64, fromBase64
34
35 try:
36 import hashlib
37 except ImportError:
38 import sha as sha1_module
39
40 try:
41 from Crypto.Hash import SHA256 as sha256_module
42 except ImportError:
43 sha256_module = None
44
45 else:
48 self.new = hash_constructor
49 self.digest_size = hash_constructor().digest_size
50
51 sha1_module = HashContainer(hashlib.sha1)
52 sha256_module = HashContainer(hashlib.sha256)
53
56
59
60 if sha256_module is not None:
63
66
67 SHA256_AVAILABLE = True
68
69 else:
70 _no_sha256 = NotImplementedError(
71 'Use Python 2.5, install pycrypto or install hashlib to use SHA256')
72
75
78
79 SHA256_AVAILABLE = False
80
81 try:
82 from Crypto.Util.number import long_to_bytes, bytes_to_long
83 except ImportError:
84 import pickle
85 try:
86
87
88
89 pickle.encode_long
90 pickle.decode_long
91 except AttributeError:
92 raise ImportError(
93 'No functionality for serializing long integers found')
94
95
96 try:
97 reversed
98 except NameError:
100 return map(seq.__getitem__, xrange(len(seq) - 1, -1, -1))
101
103 if l == 0:
104 return '\x00'
105
106 return ''.join(reversed(pickle.encode_long(l)))
107
109 return pickle.decode_long(''.join(reversed(s)))
110 else:
111
112
114 if l < 0:
115 raise ValueError('This function only supports positive integers')
116
117 bytes = long_to_bytes(l)
118 if ord(bytes[0]) > 127:
119 return '\x00' + bytes
120 else:
121 return bytes
122
124 if not bytes:
125 raise ValueError('Empty string passed to strToLong')
126
127 if ord(bytes[0]) > 127:
128 raise ValueError('This function only supports positive integers')
129
130 return bytes_to_long(bytes)
131
132
133 try:
134 getBytes = os.urandom
135 except AttributeError:
136 try:
137 from Crypto.Util.randpool import RandomPool
138 except ImportError:
139
140
141
142 try:
143 _urandom = file('/dev/urandom', 'rb')
144 except IOError:
145 raise ImportError('No adequate source of randomness found!')
146 else:
148 bytes = []
149 while n:
150 chunk = _urandom.read(n)
151 n -= len(chunk)
152 bytes.append(chunk)
153 assert n >= 0
154 return ''.join(bytes)
155 else:
156 _pool = RandomPool()
158 if pool.entropy < n:
159 pool.randomize()
160 return pool.get_bytes(n)
161
162
163 try:
164 randrange = random.SystemRandom().randrange
165 except AttributeError:
166
167
168
169
170 from math import log, ceil
171
172 _duplicate_cache = {}
174 if stop is None:
175 stop = start
176 start = 0
177
178 r = (stop - start) // step
179 try:
180 (duplicate, nbytes) = _duplicate_cache[r]
181 except KeyError:
182 rbytes = longToBinary(r)
183 if rbytes[0] == '\x00':
184 nbytes = len(rbytes) - 1
185 else:
186 nbytes = len(rbytes)
187
188 mxrand = (256 ** nbytes)
189
190
191
192 duplicate = mxrand % r
193
194 if len(_duplicate_cache) > 10:
195 _duplicate_cache.clear()
196
197 _duplicate_cache[r] = (duplicate, nbytes)
198
199 while 1:
200 bytes = '\x00' + getBytes(nbytes)
201 n = binaryToLong(bytes)
202
203 if n >= duplicate:
204 break
205
206 return start + (n % r) * step
207
210
213
215 """Produce a string of length random bytes, chosen from chrs."""
216 if chrs is None:
217 return getBytes(length)
218 else:
219 n = len(chrs)
220 return ''.join([chrs[randrange(n)] for _ in xrange(length)])
221
223 if len(s1) != len(s2):
224 return False
225
226 result = True
227 for i in range(len(s1)):
228 result = result and (s1[i] == s2[i])
229
230 return result
231