3 This module has basic math/crypto code."""
10 # The sha module is deprecated in Python 2.6
14 from hashlib import sha1 as sha
16 # The md5 module is deprecated in Python 2.6
20 from hashlib import md5
25 # **************************************************************************
26 # Load Optional Modules
27 # **************************************************************************
29 # Try to load M2Crypto/OpenSSL
31 from M2Crypto import m2
35 m2cryptoLoaded = False
38 # Try to load cryptlib
42 cryptlib_py.cryptInit()
43 except cryptlib_py.CryptException, e:
44 #If tlslite and cryptoIDlib are both present,
45 #they might each try to re-initialize this,
46 #so we're tolerant of that.
47 if e[0] != cryptlib_py.CRYPT_ERROR_INITED:
49 cryptlibpyLoaded = True
52 cryptlibpyLoaded = False
63 import Crypto.Cipher.AES
66 pycryptoLoaded = False
69 # **************************************************************************
71 # **************************************************************************
76 def getRandomBytes(howMany):
77 return stringToBytes(os.urandom(howMany))
78 prngName = "os.urandom"
81 # Else get cryptlib PRNG
83 def getRandomBytes(howMany):
84 randomKey = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED,
85 cryptlib_py.CRYPT_ALGO_AES)
86 cryptlib_py.cryptSetAttribute(randomKey,
87 cryptlib_py.CRYPT_CTXINFO_MODE,
88 cryptlib_py.CRYPT_MODE_OFB)
89 cryptlib_py.cryptGenerateKey(randomKey)
90 bytes = createByteArrayZeros(howMany)
91 cryptlib_py.cryptEncrypt(randomKey, bytes)
96 #Else get UNIX /dev/urandom PRNG
98 devRandomFile = open("/dev/urandom", "rb")
99 def getRandomBytes(howMany):
100 return stringToBytes(devRandomFile.read(howMany))
101 prngName = "/dev/urandom"
103 #Else get Win32 CryptoAPI PRNG
106 def getRandomBytes(howMany):
107 s = win32prng.getRandomBytes(howMany)
108 if len(s) != howMany:
109 raise AssertionError()
110 return stringToBytes(s)
111 prngName ="CryptoAPI"
114 def getRandomBytes(howMany):
115 raise NotImplementedError("No Random Number Generator "\
119 # **************************************************************************
120 # Converter Functions
121 # **************************************************************************
123 def bytesToNumber(bytes):
126 for count in range(len(bytes)-1, -1, -1):
128 total += multiplier * byte
132 def numberToBytes(n, howManyBytes=None):
133 if howManyBytes == None:
134 howManyBytes = numBytes(n)
135 bytes = createByteArrayZeros(howManyBytes)
136 for count in range(howManyBytes-1, -1, -1):
137 bytes[count] = int(n % 256)
141 def bytesToBase64(bytes):
142 s = bytesToString(bytes)
143 return stringToBase64(s)
145 def base64ToBytes(s):
146 s = base64ToString(s)
147 return stringToBytes(s)
149 def numberToBase64(n):
150 bytes = numberToBytes(n)
151 return bytesToBase64(bytes)
153 def base64ToNumber(s):
154 bytes = base64ToBytes(s)
155 return bytesToNumber(bytes)
157 def stringToNumber(s):
158 bytes = stringToBytes(s)
159 return bytesToNumber(bytes)
161 def numberToString(s):
162 bytes = numberToBytes(s)
163 return bytesToString(bytes)
165 def base64ToString(s):
167 return base64.decodestring(s)
168 except binascii.Error, e:
170 except binascii.Incomplete, e:
173 def stringToBase64(s):
174 return base64.encodestring(s).replace("\n", "")
176 def mpiToNumber(mpi): #mpi is an openssl-format bignum string
177 if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number
178 raise AssertionError()
179 bytes = stringToBytes(mpi[4:])
180 return bytesToNumber(bytes)
183 bytes = numberToBytes(n)
185 #If the high-order bit is going to be set,
186 #add an extra byte of zeros
187 if (numBits(n) & 0x7)==0:
189 length = numBytes(n) + ext
190 bytes = concatArrays(createByteArrayZeros(4+ext), bytes)
191 bytes[0] = (length >> 24) & 0xFF
192 bytes[1] = (length >> 16) & 0xFF
193 bytes[2] = (length >> 8) & 0xFF
194 bytes[3] = length & 0xFF
195 return bytesToString(bytes)
199 # **************************************************************************
200 # Misc. Utility Functions
201 # **************************************************************************
207 return int(math.ceil(bits / 8.0))
209 def hashAndBase64(s):
210 return stringToBase64(sha.sha(s).digest())
212 def getBase64Nonce(numChars=22): #defaults to an 132 bit nonce
213 bytes = getRandomBytes(numChars)
214 bytesStr = "".join([chr(b) for b in bytes])
215 return stringToBase64(bytesStr)[:numChars]
218 # **************************************************************************
220 # **************************************************************************
222 def getRandomNumber(low, high):
224 raise AssertionError()
225 howManyBits = numBits(high)
226 howManyBytes = numBytes(high)
227 lastBits = howManyBits % 8
229 bytes = getRandomBytes(howManyBytes)
231 bytes[0] = bytes[0] % (1 << lastBits)
232 n = bytesToNumber(bytes)
233 if n >= low and n < high:
237 a, b = max(a,b), min(a,b)
243 #This will break when python division changes, but we can't use // cause
245 return (a * b) / gcd(a, b)
247 #Returns inverse of a mod b, zero if none
248 #Uses Extended Euclidean Algorithm
253 #This will break when python division changes, but we can't use //
257 uc, ud = ud - (q * uc), uc
264 def powMod(base, power, modulus):
265 base = gmpy.mpz(base)
266 power = gmpy.mpz(power)
267 modulus = gmpy.mpz(modulus)
268 result = pow(base, power, modulus)
272 #Copied from Bryan G. Olson's post to comp.lang.python
273 #Does left-to-right instead of pow()'s right-to-left,
274 #thus about 30% faster than the python built-in with small bases
275 def powMod(base, power, modulus):
278 """ Return base**power mod modulus, using multi bit scanning
279 with nBitScan bits at a time."""
281 #TREV - Added support for negative exponents
282 negativeResult = False
285 negativeResult = True
290 # Break power into a list of digits of nBitScan bits.
291 # The list is recursive so easy to read in reverse direction.
294 nibbles = int(power & mask), nibbles
295 power = power >> nBitScan
297 # Make a table of powers of base up to 2**nBitScan - 1
299 for i in xrange(1, exp2):
300 lowPowers.append((lowPowers[i-1] * base) % modulus)
302 # To exponentiate by the first nibble, look it up in the table
303 nib, nibbles = nibbles
304 prod = lowPowers[nib]
306 # For the rest, square nBitScan times, then multiply by
309 nib, nibbles = nibbles
310 for i in xrange(nBitScan):
311 prod = (prod * prod) % modulus
312 if nib: prod = (prod * lowPowers[nib]) % modulus
314 #TREV - Added support for negative exponents
316 prodInv = invMod(prod, modulus)
317 #Check to make sure the inverse is correct
318 if (prod * prodInv) % modulus != 1:
319 raise AssertionError()
324 #Pre-calculate a sieve of the ~100 primes < 1000:
327 for count in range(2, int(math.sqrt(n))):
328 if sieve[count] == 0:
331 while x < len(sieve):
334 sieve = [x for x in sieve[2:] if x]
337 sieve = makeSieve(1000)
339 def isPrime(n, iterations=5, display=False):
340 #Trial division with sieve
342 if x >= n: return True
343 if n % x == 0: return False
344 #Passed trial division, proceed to Rabin-Miller
345 #Rabin-Miller implemented per Ferguson & Schneier
346 #Compute s, t for Rabin-Miller
347 if display: print "*",
351 #Repeat Rabin-Miller x times
352 a = 2 #Use 2 as a base for first iteration speedup, per HAC
353 for count in range(iterations):
362 v, i = powMod(v, 2, n), i+1
363 a = getRandomNumber(2, n)
366 def getRandomPrime(bits, display=False):
368 raise AssertionError()
369 #The 1.5 ensures the 2 MSBs are set
370 #Thus, when used for p,q in RSA, n will have its MSB set
372 #Since 30 is lcm(2,3,5), we'll set our test numbers to
373 #29 % 30 and keep them there
374 low = (2L ** (bits-1)) * 3/2
375 high = 2L ** bits - 30
376 p = getRandomNumber(low, high)
379 if display: print ".",
382 p = getRandomNumber(low, high)
384 if isPrime(p, display=display):
387 #Unused at the moment...
388 def getRandomSafePrime(bits, display=False):
390 raise AssertionError()
391 #The 1.5 ensures the 2 MSBs are set
392 #Thus, when used for p,q in RSA, n will have its MSB set
394 #Since 30 is lcm(2,3,5), we'll set our test numbers to
395 #29 % 30 and keep them there
396 low = (2 ** (bits-2)) * 3/2
397 high = (2 ** (bits-1)) - 30
398 q = getRandomNumber(low, high)
401 if display: print ".",
404 q = getRandomNumber(low, high)
406 #Ideas from Tom Wu's SRP code
407 #Do trial division on p and q before Rabin-Miller
408 if isPrime(q, 0, display=display):
410 if isPrime(p, display=display):
411 if isPrime(q, display=display):