From 50cf183d219face91822c75fa0a15fe2fe3cb32d Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Wed, 8 Jan 2020 16:27:26 +0100 Subject: Refs #27468 -- Added algorithm parameter to django.utils.crypto.salted_hmac(). --- django/utils/crypto.py | 27 +++++++++++++++++++-------- 1 file changed, 19 insertions(+), 8 deletions(-) (limited to 'django') 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, -- cgit v1.3