Package tlslite :: Module mathtls |
[hide private]
[frames] | no frames]

# Source Code for Module tlslite.mathtls

      1  # Authors:
      2  #   Trevor Perrin
      3  #   Dave Baggett (Arcode Corporation) - MD5 support for MAC_SSL
      4  #
      5  # See the LICENSE file for legal information regarding use of this file.
      6
      7  """Miscellaneous helper functions."""
      8
      9  from .utils.compat import *
     10  from .utils.cryptomath import *
     11
     12  import hmac
     13
     14  #1024, 1536, 2048, 3072, 4096, 6144, and 8192 bit groups]
     15  goodGroupParameters = [(2,0xEEAF0AB9ADB38DD69C33F80AFA8FC5E86072618775FF3C0B9EA2314C9C256576D674DF7496EA81D3383B4813D692C6E0E0D5D8E250B98BE48E495C1D6089DAD15DC7D7B46154D6B6CE8EF4AD69B15D4982559B297BCF1885C529F566660E57EC68EDBC3C05726CC02FD4CBF4976EAA9AFD5138FE8376435B9FC61D2FC0EB06E3),\
     16                         (2,0x9DEF3CAFB939277AB1F12A8617A47BBBDBA51DF499AC4C80BEEEA9614B19CC4D5F4F5F556E27CBDE51C6A94BE4607A291558903BA0D0F84380B655BB9A22E8DCDF028A7CEC67F0D08134B1C8B97989149B609E0BE3BAB63D47548381DBC5B1FC764E3F4B53DD9DA1158BFD3E2B9C8CF56EDF019539349627DB2FD53D24B7C48665772E437D6C7F8CE442734AF7CCB7AE837C264AE3A9BEB87F8A2FE9B8B5292E5A021FFF5E91479E8CE7A28C2442C6F315180F93499A234DCF76E3FED135F9BB),\
     17                         (2, ),\
     18                         (2, ),\
     19                         (5, ),\
     20                         (5, ),\
     21                         (5, )]
     22
     23 -def P_hash(macFunc, secret, seed, length):
     24      bytes = bytearray(length)
     25      A = seed
     26      index = 0
     27      while 1:
     28          A = macFunc(secret, A)
     29          output = macFunc(secret, A + seed)
     30          for c in output:
     31              if index >= length:
     32                  return bytes
     33              bytes[index] = c
     34              index += 1
     35      return bytes
     36
     37 -def PRF(secret, label, seed, length):
     38      #Split the secret into left and right halves
     39      # which may share a byte if len is odd
     40      S1 = secret[ : int(math.ceil(len(secret)/2.0))]
     41      S2 = secret[ int(math.floor(len(secret)/2.0)) : ]
     42
     43      #Run the left half through P_MD5 and the right half through P_SHA1
     44      p_md5 = P_hash(HMAC_MD5, S1, label + seed, length)
     45      p_sha1 = P_hash(HMAC_SHA1, S2, label + seed, length)
     46
     47      #XOR the output values and return the result
     48      for x in range(length):
     49          p_md5[x] ^= p_sha1[x]
     50      return p_md5
     51
     52
     53 -def PRF_SSL(secret, seed, length):
     54      bytes = bytearray(length)
     55      index = 0
     56      for x in range(26):
     57          A = bytearray([ord('A')+x] * (x+1)) # 'A', 'BB', 'CCC', etc..
     58          input = secret + SHA1(A + secret + seed)
     59          output = MD5(input)
     60          for c in output:
     61              if index >= length:
     62                  return bytes
     63              bytes[index] = c
     64              index += 1
     65      return bytes
     66
     67 -def calcMasterSecret(version, premasterSecret, clientRandom, serverRandom):
     68      if version == (3,0):
     69          masterSecret = PRF_SSL(premasterSecret,
     70                              clientRandom + serverRandom, 48)
     71      elif version in ((3,1), (3,2)):
     72          masterSecret = PRF(premasterSecret, b"master secret",
     73                              clientRandom + serverRandom, 48)
     74      else:
     75          raise AssertionError()
     76      return masterSecret
     77
     78
     79 -def makeX(salt, username, password):
     80      if len(username)>=256:
     81          raise ValueError("username too long")
     82      if len(salt)>=256:
     83          raise ValueError("salt too long")
     84      innerHashResult = SHA1(username + bytearray(b":") + password)
     85      outerHashResult = SHA1(salt + innerHashResult)
     86      return bytesToNumber(outerHashResult)
     87
     88  #This function is used by VerifierDB.makeVerifier
     89 -def makeVerifier(username, password, bits):
     90      bitsIndex = {1024:0, 1536:1, 2048:2, 3072:3, 4096:4, 6144:5, 8192:6}[bits]
     91      g,N = goodGroupParameters[bitsIndex]
     92      salt = getRandomBytes(16)
     93      x = makeX(salt, username, password)
     94      verifier = powMod(g, x, N)
     95      return N, g, salt, verifier
     96
     97 -def PAD(n, x):
     98      nLength = len(numberToByteArray(n))
     99      b = numberToByteArray(x)
    100      if len(b) < nLength:
    101          b = (b"\0" * (nLength-len(b))) + b
    102      return b
    103
    104 -def makeU(N, A, B):
    105    return bytesToNumber(SHA1(PAD(N, A) + PAD(N, B)))
    106
    107 -def makeK(N, g):
    108    return bytesToNumber(SHA1(numberToByteArray(N) + PAD(N, g)))
    109
    110 -def createHMAC(k, digestmod=hashlib.sha1):
    111      return hmac.HMAC(k, digestmod=digestmod)
    112
    113 -def createMAC_SSL(k, digestmod=None):
    114      mac = MAC_SSL()
    115      mac.create(k, digestmod=digestmod)
    116      return mac
    117
    118
    119 -class MAC_SSL(object):
    120 -    def create(self, k, digestmod=None):
    121          self.digestmod = digestmod or hashlib.sha1
    122          # Repeat pad bytes 48 times for MD5; 40 times for other hash functions.
    123          self.digest_size = 16 if (self.digestmod is hashlib.md5) else 20
    124          repeat = 40 if self.digest_size == 20 else 48
    125          opad = b"\x5C" * repeat
    126          ipad = b"\x36" * repeat
    127
    128          self.ohash = self.digestmod(k + opad)
    129          self.ihash = self.digestmod(k + ipad)
    130
    131 -    def update(self, m):
    132          self.ihash.update(m)
    133
    134 -    def copy(self):
    135          new = MAC_SSL()
    136          new.ihash = self.ihash.copy()
    137          new.ohash = self.ohash.copy()
    138          new.digestmod = self.digestmod
    139          new.digest_size = self.digest_size
    140          return new
    141
    142 -    def digest(self):
    143          ohash2 = self.ohash.copy()
    144          ohash2.update(self.ihash.digest())
    145          return bytearray(ohash2.digest())
    146