summaryrefslogtreecommitdiff
path: root/django/utils/crypto.py
diff options
context:
space:
mode:
authorClaude Paroz <claude@2xlibre.net>2020-01-08 16:27:26 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2020-01-27 12:42:21 +0100
commit50cf183d219face91822c75fa0a15fe2fe3cb32d (patch)
tree56339297b6fd0a7339b9cc749648e7677fec2644 /django/utils/crypto.py
parentc00b863ac6e9f6dfb295d4fc5291726a1112c080 (diff)
Refs #27468 -- Added algorithm parameter to django.utils.crypto.salted_hmac().
Diffstat (limited to 'django/utils/crypto.py')
-rw-r--r--django/utils/crypto.py27
1 files changed, 19 insertions, 8 deletions
diff --git a/django/utils/crypto.py b/django/utils/crypto.py
index 4ec1cfcf77..edeb336f34 100644
--- a/django/utils/crypto.py
+++ b/django/utils/crypto.py
@@ -9,10 +9,16 @@ from django.conf import settings
from django.utils.encoding import force_bytes
-def salted_hmac(key_salt, value, secret=None):
+class InvalidAlgorithm(ValueError):
+ """Algorithm is not supported by hashlib."""
+ pass
+
+
+def salted_hmac(key_salt, value, secret=None, *, algorithm='sha1'):
"""
- Return the HMAC-SHA1 of 'value', using a key generated from key_salt and a
- secret (which defaults to settings.SECRET_KEY).
+ Return the HMAC of 'value', using a key generated from key_salt and a
+ secret (which defaults to settings.SECRET_KEY). Default algorithm is SHA1,
+ but any algorithm name supported by hashlib.new() can be passed.
A different key_salt should be passed in for every application of HMAC.
"""
@@ -21,16 +27,21 @@ def salted_hmac(key_salt, value, secret=None):
key_salt = force_bytes(key_salt)
secret = force_bytes(secret)
-
+ try:
+ hasher = getattr(hashlib, algorithm)
+ except AttributeError as e:
+ raise InvalidAlgorithm(
+ '%r is not an algorithm accepted by the hashlib module.'
+ % algorithm
+ ) from e
# 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 = hashlib.sha1(key_salt + secret).digest()
+ # passing the key_salt and our base key through a pseudo-random function.
+ key = hasher(key_salt + secret).digest()
# If len(key_salt + secret) > block size of the hash algorithm, 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=force_bytes(value), digestmod=hashlib.sha1)
+ return hmac.new(key, msg=force_bytes(value), digestmod=hasher)
def get_random_string(length=12,