1
2
3
4
5
6
7
8 """cryptomath module
9
10 This module has basic math/crypto code."""
11 from __future__ import print_function
12 import os
13 import math
14 import base64
15 import binascii
16 import sys
17
18 from .compat import compat26Str, compatHMAC, compatLong
19
20
21
22
23
24
25
26 try:
27 from M2Crypto import m2
28 m2cryptoLoaded = True
29
30 try:
31 with open('/proc/sys/crypto/fips_enabled', 'r') as fipsFile:
32 if '1' in fipsFile.read():
33 m2cryptoLoaded = False
34 except (IOError, OSError):
35
36 m2cryptoLoaded = True
37
38 except ImportError:
39 m2cryptoLoaded = False
40
41
42 try:
43 import gmpy
44 gmpyLoaded = True
45 except ImportError:
46 gmpyLoaded = False
47
48
49 try:
50 import Crypto.Cipher.AES
51 pycryptoLoaded = True
52 except ImportError:
53 pycryptoLoaded = False
54
55
56
57
58
59
60
61 import zlib
62 assert len(zlib.compress(os.urandom(1000))) > 900
63
65 b = bytearray(os.urandom(howMany))
66 assert(len(b) == howMany)
67 return b
68
69 prngName = "os.urandom"
70
71
72
73
74
75 import hmac
76 from . import tlshashlib as hashlib
77
79 """Return a MD5 digest of data"""
80 return secureHash(b, 'md5')
81
83 """Return a SHA1 digest of data"""
84 return secureHash(b, 'sha1')
85
87 """Return a digest of `data` using `algorithm`"""
88 hashInstance = hashlib.new(algorithm)
89 hashInstance.update(compat26Str(data))
90 return bytearray(hashInstance.digest())
91
93 """Return a HMAC using `b` and `k` using `algorithm`"""
94 k = compatHMAC(k)
95 b = compatHMAC(b)
96 return bytearray(hmac.new(k, b, getattr(hashlib, algorithm)).digest())
97
100
103
106
109
111 N = divceil(L, getattr(hashlib, algorithm)().digest_size)
112 T = bytearray()
113 Titer = bytearray()
114 for x in range(1, N+2):
115 T += Titer
116 Titer = secureHMAC(PRK, Titer + info + bytearray([x]), algorithm)
117 return T[:L]
118
119
120
121
122
124 total = 0
125 multiplier = 1
126 for count in range(len(b)-1, -1, -1):
127 byte = b[count]
128 total += multiplier * byte
129 multiplier *= 256
130 return total
131
133 """Convert an integer into a bytearray, zero-pad to howManyBytes.
134
135 The returned bytearray may be smaller than howManyBytes, but will
136 not be larger. The returned bytearray will contain a big-endian
137 encoding of the input integer (n).
138 """
139 if howManyBytes == None:
140 howManyBytes = numBytes(n)
141 b = bytearray(howManyBytes)
142 for count in range(howManyBytes-1, -1, -1):
143 b[count] = int(n % 256)
144 n >>= 8
145 return b
146
148 if (ord(mpi[4]) & 0x80) !=0:
149 raise AssertionError()
150 b = bytearray(mpi[4:])
151 return bytesToNumber(b)
152
154 b = numberToByteArray(n)
155 ext = 0
156
157
158 if (numBits(n) & 0x7)==0:
159 ext = 1
160 length = numBytes(n) + ext
161 b = bytearray(4+ext) + b
162 b[0] = (length >> 24) & 0xFF
163 b[1] = (length >> 16) & 0xFF
164 b[2] = (length >> 8) & 0xFF
165 b[3] = length & 0xFF
166 return bytes(b)
167
168
169
170
171
172
174 """Return number of bits necessary to represent the integer in binary"""
175 if n==0:
176 return 0
177 if sys.version_info < (2, 7):
178
179
180 return len(bin(n))-2
181 else:
182 return n.bit_length()
183
185 """Return number of bytes necessary to represent the integer in bytes"""
186 if n==0:
187 return 0
188 bits = numBits(n)
189 return (bits + 7) // 8
190
191
192
193
194
196 if low >= high:
197 raise AssertionError()
198 howManyBits = numBits(high)
199 howManyBytes = numBytes(high)
200 lastBits = howManyBits % 8
201 while 1:
202 bytes = getRandomBytes(howManyBytes)
203 if lastBits:
204 bytes[0] = bytes[0] % (1 << lastBits)
205 n = bytesToNumber(bytes)
206 if n >= low and n < high:
207 return n
208
210 a, b = max(a,b), min(a,b)
211 while b:
212 a, b = b, a % b
213 return a
214
216 return (a * b) // gcd(a, b)
217
218
219
221 c, d = a, b
222 uc, ud = 1, 0
223 while c != 0:
224 q = d // c
225 c, d = d-(q*c), c
226 uc, ud = ud - (q * uc), uc
227 if d == 1:
228 return ud % b
229 return 0
230
231
232 if gmpyLoaded:
233 - def powMod(base, power, modulus):
234 base = gmpy.mpz(base)
235 power = gmpy.mpz(power)
236 modulus = gmpy.mpz(modulus)
237 result = pow(base, power, modulus)
238 return compatLong(result)
239
240 else:
241 - def powMod(base, power, modulus):
242 if power < 0:
243 result = pow(base, power*-1, modulus)
244 result = invMod(result, modulus)
245 return result
246 else:
247 return pow(base, power, modulus)
248
249
251 """Integer division with rounding up"""
252 quot, r = divmod(divident, divisor)
253 return quot + int(bool(r))
254
255
256
258 sieve = list(range(n))
259 for count in range(2, int(math.sqrt(n))+1):
260 if sieve[count] == 0:
261 continue
262 x = sieve[count] * 2
263 while x < len(sieve):
264 sieve[x] = 0
265 x += sieve[count]
266 sieve = [x for x in sieve[2:] if x]
267 return sieve
268
270
271 for x in sieve:
272 if x >= n: return True
273 if n % x == 0: return False
274
275
276
277 if display: print("*", end=' ')
278 s, t = n-1, 0
279 while s % 2 == 0:
280 s, t = s//2, t+1
281
282 a = 2
283 for count in range(iterations):
284 v = powMod(a, s, n)
285 if v==1:
286 continue
287 i = 0
288 while v != n-1:
289 if i == t-1:
290 return False
291 else:
292 v, i = powMod(v, 2, n), i+1
293 a = getRandomNumber(2, n)
294 return True
295
297 if bits < 10:
298 raise AssertionError()
299
300
301
302
303
304 low = ((2 ** (bits-1)) * 3) // 2
305 high = 2 ** bits - 30
306 p = getRandomNumber(low, high)
307 p += 29 - (p % 30)
308 while 1:
309 if display: print(".", end=' ')
310 p += 30
311 if p >= high:
312 p = getRandomNumber(low, high)
313 p += 29 - (p % 30)
314 if isPrime(p, display=display):
315 return p
316
317
319 if bits < 10:
320 raise AssertionError()
321
322
323
324
325
326 low = (2 ** (bits-2)) * 3//2
327 high = (2 ** (bits-1)) - 30
328 q = getRandomNumber(low, high)
329 q += 29 - (q % 30)
330 while 1:
331 if display: print(".", end=' ')
332 q += 30
333 if (q >= high):
334 q = getRandomNumber(low, high)
335 q += 29 - (q % 30)
336
337
338 if isPrime(q, 0, display=display):
339 p = (2 * q) + 1
340 if isPrime(p, display=display):
341 if isPrime(q, display=display):
342 return p
343