tlslite.utils.cryptomath

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