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