Package tlslite :: Package utils :: Module cryptomath
[hide private]
[frames] | no frames]

Source Code for Module tlslite.utils.cryptomath

  1  # Authors:  
  2  #   Trevor Perrin 
  3  #   Martin von Loewis - python 3 port 
  4  #   Yngve Pettersen (ported by Paul Sokolovsky) - TLS 1.2 
  5  # 
  6  # See the LICENSE file for legal information regarding use of this file. 
  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   
 17  from .compat import * 
 18   
 19   
 20  # ************************************************************************** 
 21  # Load Optional Modules 
 22  # ************************************************************************** 
 23   
 24  # Try to load M2Crypto/OpenSSL 
 25  try: 
 26      from M2Crypto import m2 
 27      m2cryptoLoaded = True 
 28   
 29  except ImportError: 
 30      m2cryptoLoaded = False 
 31   
 32  #Try to load GMPY 
 33  try: 
 34      import gmpy 
 35      gmpyLoaded = True 
 36  except ImportError: 
 37      gmpyLoaded = False 
 38   
 39  #Try to load pycrypto 
 40  try: 
 41      import Crypto.Cipher.AES 
 42      pycryptoLoaded = True 
 43  except ImportError: 
 44      pycryptoLoaded = False 
 45   
 46   
 47  # ************************************************************************** 
 48  # PRNG Functions 
 49  # ************************************************************************** 
 50   
 51  # Check that os.urandom works 
 52  import zlib 
 53  length = len(zlib.compress(os.urandom(1000))) 
 54  assert(length > 900) 
 55   
56 -def getRandomBytes(howMany):
57 b = bytearray(os.urandom(howMany)) 58 assert(len(b) == howMany) 59 return b
60 61 prngName = "os.urandom" 62 63 # ************************************************************************** 64 # Simple hash functions 65 # ************************************************************************** 66 67 import hmac 68 import hashlib 69
70 -def MD5(b):
71 return bytearray(hashlib.md5(compat26Str(b)).digest())
72
73 -def SHA1(b):
74 return bytearray(hashlib.sha1(compat26Str(b)).digest())
75
76 -def HMAC_MD5(k, b):
77 k = compatHMAC(k) 78 b = compatHMAC(b) 79 return bytearray(hmac.new(k, b, hashlib.md5).digest())
80
81 -def HMAC_SHA1(k, b):
82 k = compatHMAC(k) 83 b = compatHMAC(b) 84 return bytearray(hmac.new(k, b, hashlib.sha1).digest())
85
86 -def HMAC_SHA256(k, b):
87 k = compatHMAC(k) 88 b = compatHMAC(b) 89 return bytearray(hmac.new(k, b, hashlib.sha256).digest())
90 91 # ************************************************************************** 92 # Converter Functions 93 # ************************************************************************** 94
95 -def bytesToNumber(b):
96 total = 0 97 multiplier = 1 98 for count in range(len(b)-1, -1, -1): 99 byte = b[count] 100 total += multiplier * byte 101 multiplier *= 256 102 return total
103
104 -def numberToByteArray(n, howManyBytes=None):
105 """Convert an integer into a bytearray, zero-pad to howManyBytes. 106 107 The returned bytearray may be smaller than howManyBytes, but will 108 not be larger. The returned bytearray will contain a big-endian 109 encoding of the input integer (n). 110 """ 111 if howManyBytes == None: 112 howManyBytes = numBytes(n) 113 b = bytearray(howManyBytes) 114 for count in range(howManyBytes-1, -1, -1): 115 b[count] = int(n % 256) 116 n >>= 8 117 return b
118
119 -def mpiToNumber(mpi): #mpi is an openssl-format bignum string
120 if (ord(mpi[4]) & 0x80) !=0: #Make sure this is a positive number 121 raise AssertionError() 122 b = bytearray(mpi[4:]) 123 return bytesToNumber(b) 124
125 -def numberToMPI(n):
126 b = numberToByteArray(n) 127 ext = 0 128 #If the high-order bit is going to be set, 129 #add an extra byte of zeros 130 if (numBits(n) & 0x7)==0: 131 ext = 1 132 length = numBytes(n) + ext 133 b = bytearray(4+ext) + b 134 b[0] = (length >> 24) & 0xFF 135 b[1] = (length >> 16) & 0xFF 136 b[2] = (length >> 8) & 0xFF 137 b[3] = length & 0xFF 138 return bytes(b)
139 140 141 # ************************************************************************** 142 # Misc. Utility Functions 143 # ************************************************************************** 144
145 -def numBits(n):
146 if n==0: 147 return 0 148 s = "%x" % n 149 return ((len(s)-1)*4) + \ 150 {'0':0, '1':1, '2':2, '3':2, 151 '4':3, '5':3, '6':3, '7':3, 152 '8':4, '9':4, 'a':4, 'b':4, 153 'c':4, 'd':4, 'e':4, 'f':4, 154 }[s[0]] 155 return int(math.floor(math.log(n, 2))+1)
156
157 -def numBytes(n):
158 if n==0: 159 return 0 160 bits = numBits(n) 161 return int(math.ceil(bits / 8.0))
162 163 # ************************************************************************** 164 # Big Number Math 165 # ************************************************************************** 166
167 -def getRandomNumber(low, high):
168 if low >= high: 169 raise AssertionError() 170 howManyBits = numBits(high) 171 howManyBytes = numBytes(high) 172 lastBits = howManyBits % 8 173 while 1: 174 bytes = getRandomBytes(howManyBytes) 175 if lastBits: 176 bytes[0] = bytes[0] % (1 << lastBits) 177 n = bytesToNumber(bytes) 178 if n >= low and n < high: 179 return n
180
181 -def gcd(a,b):
182 a, b = max(a,b), min(a,b) 183 while b: 184 a, b = b, a % b 185 return a
186
187 -def lcm(a, b):
188 return (a * b) // gcd(a, b)
189 190 #Returns inverse of a mod b, zero if none 191 #Uses Extended Euclidean Algorithm
192 -def invMod(a, b):
193 c, d = a, b 194 uc, ud = 1, 0 195 while c != 0: 196 q = d // c 197 c, d = d-(q*c), c 198 uc, ud = ud - (q * uc), uc 199 if d == 1: 200 return ud % b 201 return 0
202 203 204 if gmpyLoaded:
205 - def powMod(base, power, modulus):
206 base = gmpy.mpz(base) 207 power = gmpy.mpz(power) 208 modulus = gmpy.mpz(modulus) 209 result = pow(base, power, modulus) 210 return long(result)
211 212 else:
213 - def powMod(base, power, modulus):
214 if power < 0: 215 result = pow(base, power*-1, modulus) 216 result = invMod(result, modulus) 217 return result 218 else: 219 return pow(base, power, modulus)
220 221 #Pre-calculate a sieve of the ~100 primes < 1000:
222 -def makeSieve(n):
223 sieve = list(range(n)) 224 for count in range(2, int(math.sqrt(n))+1): 225 if sieve[count] == 0: 226 continue 227 x = sieve[count] * 2 228 while x < len(sieve): 229 sieve[x] = 0 230 x += sieve[count] 231 sieve = [x for x in sieve[2:] if x] 232 return sieve
233 234 sieve = makeSieve(1000) 235
236 -def isPrime(n, iterations=5, display=False):
237 #Trial division with sieve 238 for x in sieve: 239 if x >= n: return True 240 if n % x == 0: return False 241 #Passed trial division, proceed to Rabin-Miller 242 #Rabin-Miller implemented per Ferguson & Schneier 243 #Compute s, t for Rabin-Miller 244 if display: print("*", end=' ') 245 s, t = n-1, 0 246 while s % 2 == 0: 247 s, t = s//2, t+1 248 #Repeat Rabin-Miller x times 249 a = 2 #Use 2 as a base for first iteration speedup, per HAC 250 for count in range(iterations): 251 v = powMod(a, s, n) 252 if v==1: 253 continue 254 i = 0 255 while v != n-1: 256 if i == t-1: 257 return False 258 else: 259 v, i = powMod(v, 2, n), i+1 260 a = getRandomNumber(2, n) 261 return True
262
263 -def getRandomPrime(bits, display=False):
264 if bits < 10: 265 raise AssertionError() 266 #The 1.5 ensures the 2 MSBs are set 267 #Thus, when used for p,q in RSA, n will have its MSB set 268 # 269 #Since 30 is lcm(2,3,5), we'll set our test numbers to 270 #29 % 30 and keep them there 271 low = ((2 ** (bits-1)) * 3) // 2 272 high = 2 ** bits - 30 273 p = getRandomNumber(low, high) 274 p += 29 - (p % 30) 275 while 1: 276 if display: print(".", end=' ') 277 p += 30 278 if p >= high: 279 p = getRandomNumber(low, high) 280 p += 29 - (p % 30) 281 if isPrime(p, display=display): 282 return p
283 284 #Unused at the moment...
285 -def getRandomSafePrime(bits, display=False):
286 if bits < 10: 287 raise AssertionError() 288 #The 1.5 ensures the 2 MSBs are set 289 #Thus, when used for p,q in RSA, n will have its MSB set 290 # 291 #Since 30 is lcm(2,3,5), we'll set our test numbers to 292 #29 % 30 and keep them there 293 low = (2 ** (bits-2)) * 3//2 294 high = (2 ** (bits-1)) - 30 295 q = getRandomNumber(low, high) 296 q += 29 - (q % 30) 297 while 1: 298 if display: print(".", end=' ') 299 q += 30 300 if (q >= high): 301 q = getRandomNumber(low, high) 302 q += 29 - (q % 30) 303 #Ideas from Tom Wu's SRP code 304 #Do trial division on p and q before Rabin-Miller 305 if isPrime(q, 0, display=display): 306 p = (2 * q) + 1 307 if isPrime(p, display=display): 308 if isPrime(q, display=display): 309 return p
310