Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3)

Side by Side Diff: third_party/tlslite/tlslite/utils/cryptomath.py

Issue 210323002: Update tlslite to 0.4.6. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Executable bit and --similarity=80 Created 6 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 # Authors:
2 # Trevor Perrin
3 # Martin von Loewis - python 3 port
4 #
5 # See the LICENSE file for legal information regarding use of this file.
6
1 """cryptomath module 7 """cryptomath module
2 8
3 This module has basic math/crypto code.""" 9 This module has basic math/crypto code."""
4 10 from __future__ import print_function
5 import os 11 import os
6 import math 12 import math
7 import base64 13 import base64
8 import binascii 14 import binascii
9 15
10 # The sha module is deprecated in Python 2.6 16 from .compat import *
11 try:
12 import sha
13 except ImportError:
14 from hashlib import sha1 as sha
15
16 # The md5 module is deprecated in Python 2.6
17 try:
18 import md5
19 except ImportError:
20 from hashlib import md5
21
22 from compat import *
23 17
24 18
25 # ************************************************************************** 19 # **************************************************************************
26 # Load Optional Modules 20 # Load Optional Modules
27 # ************************************************************************** 21 # **************************************************************************
28 22
29 # Try to load M2Crypto/OpenSSL 23 # Try to load M2Crypto/OpenSSL
30 try: 24 try:
31 from M2Crypto import m2 25 from M2Crypto import m2
32 m2cryptoLoaded = True 26 m2cryptoLoaded = True
33 27
34 except ImportError: 28 except ImportError:
35 m2cryptoLoaded = False 29 m2cryptoLoaded = False
36 30
37
38 # Try to load cryptlib
39 try:
40 import cryptlib_py
41 try:
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:
48 raise
49 cryptlibpyLoaded = True
50
51 except ImportError:
52 cryptlibpyLoaded = False
53
54 #Try to load GMPY 31 #Try to load GMPY
55 try: 32 try:
56 import gmpy 33 import gmpy
57 gmpyLoaded = True 34 gmpyLoaded = True
58 except ImportError: 35 except ImportError:
59 gmpyLoaded = False 36 gmpyLoaded = False
60 37
61 #Try to load pycrypto 38 #Try to load pycrypto
62 try: 39 try:
63 import Crypto.Cipher.AES 40 import Crypto.Cipher.AES
64 pycryptoLoaded = True 41 pycryptoLoaded = True
65 except ImportError: 42 except ImportError:
66 pycryptoLoaded = False 43 pycryptoLoaded = False
67 44
68 45
69 # ************************************************************************** 46 # **************************************************************************
70 # PRNG Functions 47 # PRNG Functions
71 # ************************************************************************** 48 # **************************************************************************
72 49
73 # Get os.urandom PRNG 50 # Check that os.urandom works
74 try: 51 import zlib
75 os.urandom(1) 52 length = len(zlib.compress(os.urandom(1000)))
76 def getRandomBytes(howMany): 53 assert(length > 900)
77 return stringToBytes(os.urandom(howMany))
78 prngName = "os.urandom"
79 54
80 except: 55 def getRandomBytes(howMany):
81 # Else get cryptlib PRNG 56 b = bytearray(os.urandom(howMany))
82 if cryptlibpyLoaded: 57 assert(len(b) == howMany)
83 def getRandomBytes(howMany): 58 return b
84 randomKey = cryptlib_py.cryptCreateContext(cryptlib_py.CRYPT_UNUSED,
85 cryptlib_py.CRYPT_ALGO_AE S)
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)
92 return bytes
93 prngName = "cryptlib"
94 59
95 else: 60 prngName = "os.urandom"
96 #Else get UNIX /dev/urandom PRNG 61
97 try: 62 # **************************************************************************
98 devRandomFile = open("/dev/urandom", "rb") 63 # Simple hash functions
99 def getRandomBytes(howMany): 64 # **************************************************************************
100 return stringToBytes(devRandomFile.read(howMany)) 65
101 prngName = "/dev/urandom" 66 import hmac
102 except IOError: 67 import hashlib
103 #Else get Win32 CryptoAPI PRNG 68
104 try: 69 def MD5(b):
105 import win32prng 70 return bytearray(hashlib.md5(compat26Str(b)).digest())
106 def getRandomBytes(howMany): 71
107 s = win32prng.getRandomBytes(howMany) 72 def SHA1(b):
108 if len(s) != howMany: 73 return bytearray(hashlib.sha1(compat26Str(b)).digest())
109 raise AssertionError() 74
110 return stringToBytes(s) 75 def HMAC_MD5(k, b):
111 prngName ="CryptoAPI" 76 k = compatHMAC(k)
112 except ImportError: 77 b = compatHMAC(b)
113 #Else no PRNG :-( 78 return bytearray(hmac.new(k, b, hashlib.md5).digest())
114 def getRandomBytes(howMany): 79
115 raise NotImplementedError("No Random Number Generator "\ 80 def HMAC_SHA1(k, b):
116 "available.") 81 k = compatHMAC(k)
117 prngName = "None" 82 b = compatHMAC(b)
83 return bytearray(hmac.new(k, b, hashlib.sha1).digest())
84
118 85
119 # ************************************************************************** 86 # **************************************************************************
120 # Converter Functions 87 # Converter Functions
121 # ************************************************************************** 88 # **************************************************************************
122 89
123 def bytesToNumber(bytes): 90 def bytesToNumber(b):
124 total = 0L 91 total = 0
125 multiplier = 1L 92 multiplier = 1
126 for count in range(len(bytes)-1, -1, -1): 93 for count in range(len(b)-1, -1, -1):
127 byte = bytes[count] 94 byte = b[count]
128 total += multiplier * byte 95 total += multiplier * byte
129 multiplier *= 256 96 multiplier *= 256
130 return total 97 # Force-cast to long to appease PyCrypto.
98 # https://github.com/trevp/tlslite/issues/15
99 return long(total)
131 100
132 def numberToBytes(n, howManyBytes=None): 101 def numberToByteArray(n, howManyBytes=None):
102 """Convert an integer into a bytearray, zero-pad to howManyBytes.
103
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).
107 """
133 if howManyBytes == None: 108 if howManyBytes == None:
134 howManyBytes = numBytes(n) 109 howManyBytes = numBytes(n)
135 bytes = createByteArrayZeros(howManyBytes) 110 b = bytearray(howManyBytes)
136 for count in range(howManyBytes-1, -1, -1): 111 for count in range(howManyBytes-1, -1, -1):
137 bytes[count] = int(n % 256) 112 b[count] = int(n % 256)
138 n >>= 8 113 n >>= 8
139 return bytes 114 return b
140
141 def bytesToBase64(bytes):
142 s = bytesToString(bytes)
143 return stringToBase64(s)
144
145 def base64ToBytes(s):
146 s = base64ToString(s)
147 return stringToBytes(s)
148
149 def numberToBase64(n):
150 bytes = numberToBytes(n)
151 return bytesToBase64(bytes)
152
153 def base64ToNumber(s):
154 bytes = base64ToBytes(s)
155 return bytesToNumber(bytes)
156
157 def stringToNumber(s):
158 bytes = stringToBytes(s)
159 return bytesToNumber(bytes)
160
161 def numberToString(s):
162 bytes = numberToBytes(s)
163 return bytesToString(bytes)
164
165 def base64ToString(s):
166 try:
167 return base64.decodestring(s)
168 except binascii.Error, e:
169 raise SyntaxError(e)
170 except binascii.Incomplete, e:
171 raise SyntaxError(e)
172
173 def stringToBase64(s):
174 return base64.encodestring(s).replace("\n", "")
175 115
176 def mpiToNumber(mpi): #mpi is an openssl-format bignum string 116 def mpiToNumber(mpi): #mpi is an openssl-format bignum string
177 if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number 117 if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number
178 raise AssertionError() 118 raise AssertionError()
179 bytes = stringToBytes(mpi[4:]) 119 b = bytearray(mpi[4:])
180 return bytesToNumber(bytes) 120 return bytesToNumber(b)
181 121
182 def numberToMPI(n): 122 def numberToMPI(n):
183 bytes = numberToBytes(n) 123 b = numberToByteArray(n)
184 ext = 0 124 ext = 0
185 #If the high-order bit is going to be set, 125 #If the high-order bit is going to be set,
186 #add an extra byte of zeros 126 #add an extra byte of zeros
187 if (numBits(n) & 0x7)==0: 127 if (numBits(n) & 0x7)==0:
188 ext = 1 128 ext = 1
189 length = numBytes(n) + ext 129 length = numBytes(n) + ext
190 bytes = concatArrays(createByteArrayZeros(4+ext), bytes) 130 b = bytearray(4+ext) + b
191 bytes[0] = (length >> 24) & 0xFF 131 b[0] = (length >> 24) & 0xFF
192 bytes[1] = (length >> 16) & 0xFF 132 b[1] = (length >> 16) & 0xFF
193 bytes[2] = (length >> 8) & 0xFF 133 b[2] = (length >> 8) & 0xFF
194 bytes[3] = length & 0xFF 134 b[3] = length & 0xFF
195 return bytesToString(bytes) 135 return bytes(b)
196
197 136
198 137
199 # ************************************************************************** 138 # **************************************************************************
200 # Misc. Utility Functions 139 # Misc. Utility Functions
201 # ************************************************************************** 140 # **************************************************************************
202 141
142 def numBits(n):
143 if n==0:
144 return 0
145 s = "%x" % n
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,
151 }[s[0]]
152 return int(math.floor(math.log(n, 2))+1)
153
203 def numBytes(n): 154 def numBytes(n):
204 if n==0: 155 if n==0:
205 return 0 156 return 0
206 bits = numBits(n) 157 bits = numBits(n)
207 return int(math.ceil(bits / 8.0)) 158 return int(math.ceil(bits / 8.0))
208 159
209 def hashAndBase64(s):
210 return stringToBase64(sha.sha(s).digest())
211
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]
216
217
218 # ************************************************************************** 160 # **************************************************************************
219 # Big Number Math 161 # Big Number Math
220 # ************************************************************************** 162 # **************************************************************************
221 163
222 def getRandomNumber(low, high): 164 def getRandomNumber(low, high):
223 if low >= high: 165 if low >= high:
224 raise AssertionError() 166 raise AssertionError()
225 howManyBits = numBits(high) 167 howManyBits = numBits(high)
226 howManyBytes = numBytes(high) 168 howManyBytes = numBytes(high)
227 lastBits = howManyBits % 8 169 lastBits = howManyBits % 8
228 while 1: 170 while 1:
229 bytes = getRandomBytes(howManyBytes) 171 bytes = getRandomBytes(howManyBytes)
230 if lastBits: 172 if lastBits:
231 bytes[0] = bytes[0] % (1 << lastBits) 173 bytes[0] = bytes[0] % (1 << lastBits)
232 n = bytesToNumber(bytes) 174 n = bytesToNumber(bytes)
233 if n >= low and n < high: 175 if n >= low and n < high:
234 return n 176 return n
235 177
236 def gcd(a,b): 178 def gcd(a,b):
237 a, b = max(a,b), min(a,b) 179 a, b = max(a,b), min(a,b)
238 while b: 180 while b:
239 a, b = b, a % b 181 a, b = b, a % b
240 return a 182 return a
241 183
242 def lcm(a, b): 184 def lcm(a, b):
243 #This will break when python division changes, but we can't use // cause 185 return (a * b) // gcd(a, b)
244 #of Jython
245 return (a * b) / gcd(a, b)
246 186
247 #Returns inverse of a mod b, zero if none 187 #Returns inverse of a mod b, zero if none
248 #Uses Extended Euclidean Algorithm 188 #Uses Extended Euclidean Algorithm
249 def invMod(a, b): 189 def invMod(a, b):
250 c, d = a, b 190 c, d = a, b
251 uc, ud = 1, 0 191 uc, ud = 1, 0
252 while c != 0: 192 while c != 0:
253 #This will break when python division changes, but we can't use // 193 q = d // c
254 #cause of Jython
255 q = d / c
256 c, d = d-(q*c), c 194 c, d = d-(q*c), c
257 uc, ud = ud - (q * uc), uc 195 uc, ud = ud - (q * uc), uc
258 if d == 1: 196 if d == 1:
259 return ud % b 197 return ud % b
260 return 0 198 return 0
261 199
262 200
263 if gmpyLoaded: 201 if gmpyLoaded:
264 def powMod(base, power, modulus): 202 def powMod(base, power, modulus):
265 base = gmpy.mpz(base) 203 base = gmpy.mpz(base)
266 power = gmpy.mpz(power) 204 power = gmpy.mpz(power)
267 modulus = gmpy.mpz(modulus) 205 modulus = gmpy.mpz(modulus)
268 result = pow(base, power, modulus) 206 result = pow(base, power, modulus)
269 return long(result) 207 return long(result)
270 208
271 else: 209 else:
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): 210 def powMod(base, power, modulus):
276 nBitScan = 5 211 if power < 0:
277 212 result = pow(base, power*-1, modulus)
278 """ Return base**power mod modulus, using multi bit scanning 213 result = invMod(result, modulus)
279 with nBitScan bits at a time.""" 214 return result
280 215 else:
281 #TREV - Added support for negative exponents 216 return pow(base, power, modulus)
282 negativeResult = False
283 if (power < 0):
284 power *= -1
285 negativeResult = True
286
287 exp2 = 2**nBitScan
288 mask = exp2 - 1
289
290 # Break power into a list of digits of nBitScan bits.
291 # The list is recursive so easy to read in reverse direction.
292 nibbles = None
293 while power:
294 nibbles = int(power & mask), nibbles
295 power = power >> nBitScan
296
297 # Make a table of powers of base up to 2**nBitScan - 1
298 lowPowers = [1]
299 for i in xrange(1, exp2):
300 lowPowers.append((lowPowers[i-1] * base) % modulus)
301
302 # To exponentiate by the first nibble, look it up in the table
303 nib, nibbles = nibbles
304 prod = lowPowers[nib]
305
306 # For the rest, square nBitScan times, then multiply by
307 # base^nibble
308 while nibbles:
309 nib, nibbles = nibbles
310 for i in xrange(nBitScan):
311 prod = (prod * prod) % modulus
312 if nib: prod = (prod * lowPowers[nib]) % modulus
313
314 #TREV - Added support for negative exponents
315 if negativeResult:
316 prodInv = invMod(prod, modulus)
317 #Check to make sure the inverse is correct
318 if (prod * prodInv) % modulus != 1:
319 raise AssertionError()
320 return prodInv
321 return prod
322
323 217
324 #Pre-calculate a sieve of the ~100 primes < 1000: 218 #Pre-calculate a sieve of the ~100 primes < 1000:
325 def makeSieve(n): 219 def makeSieve(n):
326 sieve = range(n) 220 sieve = list(range(n))
327 for count in range(2, int(math.sqrt(n))): 221 for count in range(2, int(math.sqrt(n))):
328 if sieve[count] == 0: 222 if sieve[count] == 0:
329 continue 223 continue
330 x = sieve[count] * 2 224 x = sieve[count] * 2
331 while x < len(sieve): 225 while x < len(sieve):
332 sieve[x] = 0 226 sieve[x] = 0
333 x += sieve[count] 227 x += sieve[count]
334 sieve = [x for x in sieve[2:] if x] 228 sieve = [x for x in sieve[2:] if x]
335 return sieve 229 return sieve
336 230
337 sieve = makeSieve(1000) 231 sieve = makeSieve(1000)
338 232
339 def isPrime(n, iterations=5, display=False): 233 def isPrime(n, iterations=5, display=False):
340 #Trial division with sieve 234 #Trial division with sieve
341 for x in sieve: 235 for x in sieve:
342 if x >= n: return True 236 if x >= n: return True
343 if n % x == 0: return False 237 if n % x == 0: return False
344 #Passed trial division, proceed to Rabin-Miller 238 #Passed trial division, proceed to Rabin-Miller
345 #Rabin-Miller implemented per Ferguson & Schneier 239 #Rabin-Miller implemented per Ferguson & Schneier
346 #Compute s, t for Rabin-Miller 240 #Compute s, t for Rabin-Miller
347 if display: print "*", 241 if display: print("*", end=' ')
348 s, t = n-1, 0 242 s, t = n-1, 0
349 while s % 2 == 0: 243 while s % 2 == 0:
350 s, t = s/2, t+1 244 s, t = s//2, t+1
351 #Repeat Rabin-Miller x times 245 #Repeat Rabin-Miller x times
352 a = 2 #Use 2 as a base for first iteration speedup, per HAC 246 a = 2 #Use 2 as a base for first iteration speedup, per HAC
353 for count in range(iterations): 247 for count in range(iterations):
354 v = powMod(a, s, n) 248 v = powMod(a, s, n)
355 if v==1: 249 if v==1:
356 continue 250 continue
357 i = 0 251 i = 0
358 while v != n-1: 252 while v != n-1:
359 if i == t-1: 253 if i == t-1:
360 return False 254 return False
361 else: 255 else:
362 v, i = powMod(v, 2, n), i+1 256 v, i = powMod(v, 2, n), i+1
363 a = getRandomNumber(2, n) 257 a = getRandomNumber(2, n)
364 return True 258 return True
365 259
366 def getRandomPrime(bits, display=False): 260 def getRandomPrime(bits, display=False):
367 if bits < 10: 261 if bits < 10:
368 raise AssertionError() 262 raise AssertionError()
369 #The 1.5 ensures the 2 MSBs are set 263 #The 1.5 ensures the 2 MSBs are set
370 #Thus, when used for p,q in RSA, n will have its MSB set 264 #Thus, when used for p,q in RSA, n will have its MSB set
371 # 265 #
372 #Since 30 is lcm(2,3,5), we'll set our test numbers to 266 #Since 30 is lcm(2,3,5), we'll set our test numbers to
373 #29 % 30 and keep them there 267 #29 % 30 and keep them there
374 low = (2L ** (bits-1)) * 3/2 268 low = ((2 ** (bits-1)) * 3) // 2
375 high = 2L ** bits - 30 269 high = 2 ** bits - 30
376 p = getRandomNumber(low, high) 270 p = getRandomNumber(low, high)
377 p += 29 - (p % 30) 271 p += 29 - (p % 30)
378 while 1: 272 while 1:
379 if display: print ".", 273 if display: print(".", end=' ')
380 p += 30 274 p += 30
381 if p >= high: 275 if p >= high:
382 p = getRandomNumber(low, high) 276 p = getRandomNumber(low, high)
383 p += 29 - (p % 30) 277 p += 29 - (p % 30)
384 if isPrime(p, display=display): 278 if isPrime(p, display=display):
385 return p 279 return p
386 280
387 #Unused at the moment... 281 #Unused at the moment...
388 def getRandomSafePrime(bits, display=False): 282 def getRandomSafePrime(bits, display=False):
389 if bits < 10: 283 if bits < 10:
390 raise AssertionError() 284 raise AssertionError()
391 #The 1.5 ensures the 2 MSBs are set 285 #The 1.5 ensures the 2 MSBs are set
392 #Thus, when used for p,q in RSA, n will have its MSB set 286 #Thus, when used for p,q in RSA, n will have its MSB set
393 # 287 #
394 #Since 30 is lcm(2,3,5), we'll set our test numbers to 288 #Since 30 is lcm(2,3,5), we'll set our test numbers to
395 #29 % 30 and keep them there 289 #29 % 30 and keep them there
396 low = (2 ** (bits-2)) * 3/2 290 low = (2 ** (bits-2)) * 3//2
397 high = (2 ** (bits-1)) - 30 291 high = (2 ** (bits-1)) - 30
398 q = getRandomNumber(low, high) 292 q = getRandomNumber(low, high)
399 q += 29 - (q % 30) 293 q += 29 - (q % 30)
400 while 1: 294 while 1:
401 if display: print ".", 295 if display: print(".", end=' ')
402 q += 30 296 q += 30
403 if (q >= high): 297 if (q >= high):
404 q = getRandomNumber(low, high) 298 q = getRandomNumber(low, high)
405 q += 29 - (q % 30) 299 q += 29 - (q % 30)
406 #Ideas from Tom Wu's SRP code 300 #Ideas from Tom Wu's SRP code
407 #Do trial division on p and q before Rabin-Miller 301 #Do trial division on p and q before Rabin-Miller
408 if isPrime(q, 0, display=display): 302 if isPrime(q, 0, display=display):
409 p = (2 * q) + 1 303 p = (2 * q) + 1
410 if isPrime(p, display=display): 304 if isPrime(p, display=display):
411 if isPrime(q, display=display): 305 if isPrime(q, display=display):
412 return p 306 return p
OLDNEW
« no previous file with comments | « third_party/tlslite/tlslite/utils/cryptlib_tripledes.py ('k') | third_party/tlslite/tlslite/utils/datefuncs.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698