3 # Martin von Loewis - python 3 port
5 # See the LICENSE file for legal information regarding use of this file.
9 This module has basic math/crypto code."""
10 from __future__ import print_function
19 # **************************************************************************
20 # Load Optional Modules
21 # **************************************************************************
23 # Try to load M2Crypto/OpenSSL
25 from M2Crypto import m2
29 m2cryptoLoaded = False
40 import Crypto.Cipher.AES
43 pycryptoLoaded = False
46 # **************************************************************************
48 # **************************************************************************
50 # Check that os.urandom works
52 length = len(zlib.compress(os.urandom(1000)))
55 def getRandomBytes(howMany):
56 b = bytearray(os.urandom(howMany))
57 assert(len(b) == howMany)
60 prngName = "os.urandom"
62 # **************************************************************************
63 # Simple hash functions
64 # **************************************************************************
70 return bytearray(hashlib.md5(compat26Str(b)).digest())
73 return bytearray(hashlib.sha1(compat26Str(b)).digest())
78 return bytearray(hmac.new(k, b, hashlib.md5).digest())
83 return bytearray(hmac.new(k, b, hashlib.sha1).digest())
86 # **************************************************************************
88 # **************************************************************************
93 for count in range(len(b)-1, -1, -1):
95 total += multiplier * byte
97 # Force-cast to long to appease PyCrypto.
98 # https://github.com/trevp/tlslite/issues/15
101 def numberToByteArray(n, howManyBytes=None):
102 """Convert an integer into a bytearray, zero-pad to howManyBytes.
104 The returned bytearray may be smaller than howManyBytes, but will
105 not be larger. The returned bytearray will contain a big-endian
106 encoding of the input integer (n).
108 if howManyBytes == None:
109 howManyBytes = numBytes(n)
110 b = bytearray(howManyBytes)
111 for count in range(howManyBytes-1, -1, -1):
112 b[count] = int(n % 256)
116 def mpiToNumber(mpi): #mpi is an openssl-format bignum string
117 if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number
118 raise AssertionError()
119 b = bytearray(mpi[4:])
120 return bytesToNumber(b)
123 b = numberToByteArray(n)
125 #If the high-order bit is going to be set,
126 #add an extra byte of zeros
127 if (numBits(n) & 0x7)==0:
129 length = numBytes(n) + ext
130 b = bytearray(4+ext) + b
131 b[0] = (length >> 24) & 0xFF
132 b[1] = (length >> 16) & 0xFF
133 b[2] = (length >> 8) & 0xFF
138 # **************************************************************************
139 # Misc. Utility Functions
140 # **************************************************************************
146 return ((len(s)-1)*4) + \
147 {'0':0, '1':1, '2':2, '3':2,
148 '4':3, '5':3, '6':3, '7':3,
149 '8':4, '9':4, 'a':4, 'b':4,
150 'c':4, 'd':4, 'e':4, 'f':4,
152 return int(math.floor(math.log(n, 2))+1)
158 return int(math.ceil(bits / 8.0))
160 # **************************************************************************
162 # **************************************************************************
164 def getRandomNumber(low, high):
166 raise AssertionError()
167 howManyBits = numBits(high)
168 howManyBytes = numBytes(high)
169 lastBits = howManyBits % 8
171 bytes = getRandomBytes(howManyBytes)
173 bytes[0] = bytes[0] % (1 << lastBits)
174 n = bytesToNumber(bytes)
175 if n >= low and n < high:
179 a, b = max(a,b), min(a,b)
185 return (a * b) // gcd(a, b)
187 #Returns inverse of a mod b, zero if none
188 #Uses Extended Euclidean Algorithm
195 uc, ud = ud - (q * uc), uc
202 def powMod(base, power, modulus):
203 base = gmpy.mpz(base)
204 power = gmpy.mpz(power)
205 modulus = gmpy.mpz(modulus)
206 result = pow(base, power, modulus)
210 def powMod(base, power, modulus):
212 result = pow(base, power*-1, modulus)
213 result = invMod(result, modulus)
216 return pow(base, power, modulus)
218 #Pre-calculate a sieve of the ~100 primes < 1000:
220 sieve = list(range(n))
221 for count in range(2, int(math.sqrt(n))):
222 if sieve[count] == 0:
225 while x < len(sieve):
228 sieve = [x for x in sieve[2:] if x]
231 sieve = makeSieve(1000)
233 def isPrime(n, iterations=5, display=False):
234 #Trial division with sieve
236 if x >= n: return True
237 if n % x == 0: return False
238 #Passed trial division, proceed to Rabin-Miller
239 #Rabin-Miller implemented per Ferguson & Schneier
240 #Compute s, t for Rabin-Miller
241 if display: print("*", end=' ')
245 #Repeat Rabin-Miller x times
246 a = 2 #Use 2 as a base for first iteration speedup, per HAC
247 for count in range(iterations):
256 v, i = powMod(v, 2, n), i+1
257 a = getRandomNumber(2, n)
260 def getRandomPrime(bits, display=False):
262 raise AssertionError()
263 #The 1.5 ensures the 2 MSBs are set
264 #Thus, when used for p,q in RSA, n will have its MSB set
266 #Since 30 is lcm(2,3,5), we'll set our test numbers to
267 #29 % 30 and keep them there
268 low = ((2 ** (bits-1)) * 3) // 2
269 high = 2 ** bits - 30
270 p = getRandomNumber(low, high)
273 if display: print(".", end=' ')
276 p = getRandomNumber(low, high)
278 if isPrime(p, display=display):
281 #Unused at the moment...
282 def getRandomSafePrime(bits, display=False):
284 raise AssertionError()
285 #The 1.5 ensures the 2 MSBs are set
286 #Thus, when used for p,q in RSA, n will have its MSB set
288 #Since 30 is lcm(2,3,5), we'll set our test numbers to
289 #29 % 30 and keep them there
290 low = (2 ** (bits-2)) * 3//2
291 high = (2 ** (bits-1)) - 30
292 q = getRandomNumber(low, high)
295 if display: print(".", end=' ')
298 q = getRandomNumber(low, high)
300 #Ideas from Tom Wu's SRP code
301 #Do trial division on p and q before Rabin-Miller
302 if isPrime(q, 0, display=display):
304 if isPrime(p, display=display):
305 if isPrime(q, display=display):