Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import hmac
- import struct
- import hashlib
- import binascii
- import operator
- import time
- def force_bytes(s, encoding='utf-8', strings_only=False, errors='strict'):
- # Handle the common case first for performance reasons.
- if isinstance(s, bytes):
- if encoding == 'utf-8':
- return s
- else:
- return s.decode('utf-8', errors).encode(encoding, errors)
- if strings_only and is_protected_type(s):
- return s
- if isinstance(s, six.memoryview):
- return bytes(s)
- if isinstance(s, Promise):
- return six.text_type(s).encode(encoding, errors)
- if not isinstance(s, six.string_types):
- try:
- if six.PY3:
- return six.text_type(s).encode(encoding)
- else:
- return bytes(s)
- except UnicodeEncodeError:
- if isinstance(s, Exception):
- # An Exception subclass containing non-ASCII data that doesn't
- # know how to print itself properly. We shouldn't raise a
- # further exception.
- return b' '.join([force_bytes(arg, encoding, strings_only,
- errors) for arg in s])
- return six.text_type(s).encode(encoding, errors)
- else:
- return s.encode(encoding, errors)
- def _bin_to_long(x):
- return int(binascii.hexlify(x), 16)
- def _long_to_bin(x, hex_format_string):
- return binascii.unhexlify((hex_format_string % x).encode('ascii'))
- def _fast_hmac(key, msg, digest):
- dig1, dig2 = digest(), digest()
- if len(key) != dig1.block_size:
- raise ValueError('Key size needs to match the block_size of the digest.')
- dig1.update(key.translate(hmac.trans_36))
- dig1.update(msg)
- dig2.update(key.translate(hmac.trans_5C))
- dig2.update(dig1.digest())
- return dig2
- def pbkdf2(password, salt, iterations, dklen=0, digest=None):
- assert iterations > 0
- if not digest:
- digest = hashlib.sha256
- password = force_bytes(password)
- salt = force_bytes(salt)
- hlen = digest().digest_size
- if not dklen:
- dklen = hlen
- if dklen > (2 ** 32 - 1) * hlen:
- raise OverflowError('dklen too big')
- l = -(-dklen // hlen)
- r = dklen - (l - 1) * hlen
- hex_format_string = "%%0%ix" % (hlen * 2)
- inner_digest_size = digest().block_size
- if len(password) > inner_digest_size:
- password = digest(password).digest()
- password += b'\x00' * (inner_digest_size - len(password))
- def F(i):
- def U():
- u = salt + struct.pack(b'>I', i)
- for j in xrange(int(iterations)):
- u = _fast_hmac(password, u, digest).digest()
- yield _bin_to_long(u)
- return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
- T = [F(x) for x in range(1, l + 1)]
- return b''.join(T[:-1]) + T[-1][:r]
- def pbkdf2_(password, salt, iterations, dklen=0, digest=None):
- assert iterations > 0
- if not digest:
- digest = hashlib.sha256
- password = force_bytes(password)
- salt = force_bytes(salt)
- hlen = digest().digest_size
- if not dklen:
- dklen = hlen
- if dklen > (2 ** 32 - 1) * hlen:
- raise OverflowError('dklen too big')
- l = -(-dklen // hlen)
- r = dklen - (l - 1) * hlen
- hex_format_string = "%%0%ix" % (hlen * 2)
- inner, outer = digest(), digest()
- if len(password) > inner.block_size:
- password = digest(password).digest()
- password += b'\x00' * (inner.block_size - len(password))
- inner.update(password.translate(hmac.trans_36))
- outer.update(password.translate(hmac.trans_5C))
- def F(i):
- def U():
- u = salt + struct.pack(b'>I', i)
- for j in xrange(int(iterations)):
- # cached hmac
- dig1, dig2 = inner.copy(), outer.copy()
- dig1.update(u)
- dig2.update(dig1.digest())
- u = dig2.digest()
- yield _bin_to_long(u)
- return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
- T = [F(x) for x in range(1, l + 1)]
- return b''.join(T[:-1]) + T[-1][:r]
- t0 = time.clock()
- for x in range(1, 100):
- out0 = pbkdf2("password", "salt", 10000)
- t0 = time.clock() - t0
- t1 = time.clock()
- for x in range(1, 100):
- out1 = pbkdf2_("password", "salt", 10000)
- t1 = time.clock() - t1
- print 10 * t0, "ms", 10 * t1, "ms"
- print binascii.hexlify(out0)
- print binascii.hexlify(out1)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement