Advertisement
Guest User

PBKDF2

a guest
Sep 29th, 2013
23
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.46 KB | None | 0 0
  1. import hmac
  2. import struct
  3. import hashlib
  4. import binascii
  5. import operator
  6. import time
  7.  
  8. def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
  9.     # Handle the common case first for performance reasons.
  10.     if isinstance(s, bytes):
  11.         if encoding == 'utf-8':
  12.             return s
  13.         else:
  14.             return s.decode('utf-8', errors).encode(encoding, errors)
  15.     if strings_only and is_protected_type(s):
  16.         return s
  17.     if isinstance(s, six.memoryview):
  18.         return bytes(s)
  19.     if isinstance(s, Promise):
  20.         return six.text_type(s).encode(encoding, errors)
  21.     if not isinstance(s, six.string_types):
  22.         try:
  23.             if six.PY3:
  24.                 return six.text_type(s).encode(encoding)
  25.             else:
  26.                 return bytes(s)
  27.         except UnicodeEncodeError:
  28.             if isinstance(s, Exception):
  29.                 # An Exception subclass containing non-ASCII data that doesn't
  30.                 # know how to print itself properly. We shouldn't raise a
  31.                 # further exception.
  32.                 return b' '.join([force_bytes(arg, encoding, strings_only,
  33.                         errors) for arg in s])
  34.             return six.text_type(s).encode(encoding, errors)
  35.     else:
  36.         return s.encode(encoding, errors)
  37.  
  38. def _bin_to_long(x):
  39.     return int(binascii.hexlify(x), 16)
  40.  
  41. def _long_to_bin(x, hex_format_string):
  42.     return binascii.unhexlify((hex_format_string % x).encode('ascii'))
  43.  
  44. def _fast_hmac(key, msg, digest):
  45.     dig1, dig2 = digest(), digest()
  46.     if len(key) != dig1.block_size:
  47.         raise ValueError('Key size needs to match the block_size of the digest.')
  48.     dig1.update(key.translate(hmac.trans_36))
  49.     dig1.update(msg)
  50.     dig2.update(key.translate(hmac.trans_5C))
  51.     dig2.update(dig1.digest())
  52.     return dig2
  53.  
  54. def pbkdf2(password, salt, iterations, dklen=0, digest=None):
  55.     assert iterations > 0
  56.     if not digest:
  57.         digest = hashlib.sha256
  58.     password = force_bytes(password)
  59.     salt = force_bytes(salt)
  60.     hlen = digest().digest_size
  61.     if not dklen:
  62.         dklen = hlen
  63.     if dklen > (2 ** 32 - 1) * hlen:
  64.         raise OverflowError('dklen too big')
  65.     l = -(-dklen // hlen)
  66.     r = dklen - (l - 1) * hlen
  67.  
  68.     hex_format_string = "%%0%ix" % (hlen * 2)
  69.  
  70.     inner_digest_size = digest().block_size
  71.     if len(password) > inner_digest_size:
  72.         password = digest(password).digest()
  73.     password += b'\x00' * (inner_digest_size - len(password))
  74.  
  75.     def F(i):
  76.         def U():
  77.             u = salt + struct.pack(b'>I', i)
  78.             for j in xrange(int(iterations)):
  79.                 u = _fast_hmac(password, u, digest).digest()
  80.                 yield _bin_to_long(u)
  81.         return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
  82.  
  83.     T = [F(x) for x in range(1, l + 1)]
  84.     return b''.join(T[:-1]) + T[-1][:r]
  85.  
  86. def pbkdf2_(password, salt, iterations, dklen=0, digest=None):
  87.     assert iterations > 0
  88.     if not digest:
  89.         digest = hashlib.sha256
  90.     password = force_bytes(password)
  91.     salt = force_bytes(salt)
  92.     hlen = digest().digest_size
  93.     if not dklen:
  94.         dklen = hlen
  95.     if dklen > (2 ** 32 - 1) * hlen:
  96.         raise OverflowError('dklen too big')
  97.     l = -(-dklen // hlen)
  98.     r = dklen - (l - 1) * hlen
  99.  
  100.     hex_format_string = "%%0%ix" % (hlen * 2)
  101.  
  102.     inner, outer = digest(), digest()
  103.     if len(password) > inner.block_size:
  104.         password = digest(password).digest()
  105.     password += b'\x00' * (inner.block_size - len(password))
  106.     inner.update(password.translate(hmac.trans_36))
  107.     outer.update(password.translate(hmac.trans_5C))
  108.  
  109.     def F(i):
  110.         def U():
  111.             u = salt + struct.pack(b'>I', i)
  112.             for j in xrange(int(iterations)):
  113.                 # cached hmac
  114.                 dig1, dig2 = inner.copy(), outer.copy()
  115.                 dig1.update(u)
  116.                 dig2.update(dig1.digest())
  117.                 u = dig2.digest()
  118.                 yield _bin_to_long(u)
  119.         return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
  120.  
  121.     T = [F(x) for x in range(1, l + 1)]
  122.     return b''.join(T[:-1]) + T[-1][:r]
  123.  
  124.  
  125. t0 = time.clock()
  126. for x in range(1, 100):
  127.     out0 = pbkdf2("password", "salt", 10000)
  128. t0 = time.clock() - t0
  129.  
  130. t1 = time.clock()
  131. for x in range(1, 100):
  132.     out1 = pbkdf2_("password", "salt", 10000)
  133. t1 = time.clock() - t1
  134.  
  135. print 10 * t0, "ms", 10 * t1, "ms"
  136. print binascii.hexlify(out0)
  137. print binascii.hexlify(out1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement