mirror of https://github.com/django/django.git
[1.5.x] Fixed #21253 -- PBKDF2 with cached HMAC key
This gives a 2x speed increase compared to the existing implementation.
Thanks to Steve Thomas for the initial patch and Tim Graham for finishing it.
Backport of 1e4f53a6eb
from master.
This commit is contained in:
parent
045d192222
commit
166be6a77e
|
@ -115,22 +115,6 @@ def _long_to_bin(x, hex_format_string):
|
||||||
return binascii.unhexlify((hex_format_string % x).encode('ascii'))
|
return binascii.unhexlify((hex_format_string % x).encode('ascii'))
|
||||||
|
|
||||||
|
|
||||||
def _fast_hmac(key, msg, digest):
|
|
||||||
"""
|
|
||||||
A trimmed down version of Python's HMAC implementation.
|
|
||||||
|
|
||||||
This function operates on bytes.
|
|
||||||
"""
|
|
||||||
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(_trans_36))
|
|
||||||
dig1.update(msg)
|
|
||||||
dig2.update(key.translate(_trans_5c))
|
|
||||||
dig2.update(dig1.digest())
|
|
||||||
return dig2
|
|
||||||
|
|
||||||
|
|
||||||
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
||||||
"""
|
"""
|
||||||
Implements PBKDF2 as defined in RFC 2898, section 5.2
|
Implements PBKDF2 as defined in RFC 2898, section 5.2
|
||||||
|
@ -158,16 +142,21 @@ def pbkdf2(password, salt, iterations, dklen=0, digest=None):
|
||||||
|
|
||||||
hex_format_string = "%%0%ix" % (hlen * 2)
|
hex_format_string = "%%0%ix" % (hlen * 2)
|
||||||
|
|
||||||
inner_digest_size = digest().block_size
|
inner, outer = digest(), digest()
|
||||||
if len(password) > inner_digest_size:
|
if len(password) > inner.block_size:
|
||||||
password = digest(password).digest()
|
password = digest(password).digest()
|
||||||
password += b'\x00' * (inner_digest_size - len(password))
|
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 F(i):
|
||||||
def U():
|
def U():
|
||||||
u = salt + struct.pack(b'>I', i)
|
u = salt + struct.pack(b'>I', i)
|
||||||
for j in xrange(int(iterations)):
|
for j in xrange(int(iterations)):
|
||||||
u = _fast_hmac(password, u, digest).digest()
|
dig1, dig2 = inner.copy(), outer.copy()
|
||||||
|
dig1.update(u)
|
||||||
|
dig2.update(dig1.digest())
|
||||||
|
u = dig2.digest()
|
||||||
yield _bin_to_long(u)
|
yield _bin_to_long(u)
|
||||||
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
|
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue