Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Loading…

Fixed #21253 -- PBKDF2 with cached HMAC key #1724

Closed
wants to merge 1 commit into from

3 participants

@timgraham
Owner

This gives a 2x speed increase compared to the existing implementation.

rebased from #1638

https://code.djangoproject.com/ticket/21253

@timgraham
Owner

@dstufft or @PaulMcMillan could either of you review this?

django/utils/crypto.py
@@ -116,18 +116,14 @@ def _long_to_bin(x, hex_format_string):
return binascii.unhexlify((hex_format_string % x).encode('ascii'))
-def _fast_hmac(key, msg, digest):
+def _cached_hmac(msg, inner, outer):
"""
A trimmed down version of Python's HMAC implementation.
@apollo13 Owner

I'd remove this docstring, it no longer has much to do with python's version at all

@apollo13 Owner

Personally I'd just completely inline it into the function, it's not that much code anymore…

@timgraham Owner

done

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
@Sc00bz Sc00bz Fixed #21253 -- PBKDF2 with cached HMAC key
This gives a 2x speed increase compared to the existing implementation.
41c92d7
@timgraham timgraham closed this
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Oct 21, 2013
  1. @Sc00bz @timgraham

    Fixed #21253 -- PBKDF2 with cached HMAC key

    Sc00bz authored timgraham committed
    This gives a 2x speed increase compared to the existing implementation.
This page is out of date. Refresh to see the latest.
Showing with 9 additions and 20 deletions.
  1. +9 −20 django/utils/crypto.py
View
29 django/utils/crypto.py
@@ -116,22 +116,6 @@ def _long_to_bin(x, hex_format_string):
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(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):
"""
Implements PBKDF2 as defined in RFC 2898, section 5.2
@@ -160,16 +144,21 @@ def pbkdf2(password, salt, iterations, dklen=0, digest=None):
hex_format_string = "%%0%ix" % (hlen * 2)
- inner_digest_size = digest().block_size
- if len(password) > inner_digest_size:
+ inner, outer = digest(), digest()
+ if len(password) > inner.block_size:
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 U():
u = salt + struct.pack(b'>I', i)
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)
return _long_to_bin(reduce(operator.xor, U()), hex_format_string)
Something went wrong with that request. Please try again.