| """ |
| Django's standard crypto functions and utilities. |
| """ |
| import hmac |
| |
| from django.conf import settings |
| from django.utils.hashcompat import sha_constructor, sha_hmac |
| |
| |
| def salted_hmac(key_salt, value, secret=None): |
| """ |
| Returns the HMAC-SHA1 of 'value', using a key generated from key_salt and a |
| secret (which defaults to settings.SECRET_KEY). |
| |
| A different key_salt should be passed in for every application of HMAC. |
| """ |
| if secret is None: |
| secret = settings.SECRET_KEY |
| |
| # We need to generate a derived key from our base key. We can do this by |
| # passing the key_salt and our base key through a pseudo-random function and |
| # SHA1 works nicely. |
| |
| key = sha_constructor(key_salt + secret).digest() |
| |
| # If len(key_salt + secret) > sha_constructor().block_size, the above |
| # line is redundant and could be replaced by key = key_salt + secret, since |
| # the hmac module does the same thing for keys longer than the block size. |
| # However, we need to ensure that we *always* do this. |
| |
| return hmac.new(key, msg=value, digestmod=sha_hmac) |
| |
| |
| def constant_time_compare(val1, val2): |
| """ |
| Returns True if the two strings are equal, False otherwise. |
| |
| The time taken is independent of the number of characters that match. |
| """ |
| if len(val1) != len(val2): |
| return False |
| result = 0 |
| for x, y in zip(val1, val2): |
| result |= ord(x) ^ ord(y) |
| return result == 0 |