summaryrefslogtreecommitdiff
path: root/django/contrib
diff options
context:
space:
mode:
authorSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-08-26 13:37:34 +0200
committerSarah Boyce <42296566+sarahboyce@users.noreply.github.com>2025-08-27 10:50:50 +0200
commitd0e4dd5cdd743a5c43c4ccc2c8fa29d3982eaa71 (patch)
treeed64921a0f27e8df1b5ce69b729d34dfbfc9d815 /django/contrib
parentc594574175e379fff356e274893d797f6e6a95fa (diff)
Fixed #36572 -- Revert "Fixed #36546 -- Deprecated django.utils.crypto.constant_time_compare() in favor of hmac.compare_digest()."
This reverts commit 0246f478882c26bc1fe293224653074cd46a90d0.
Diffstat (limited to 'django/contrib')
-rw-r--r--django/contrib/auth/__init__.py14
-rw-r--r--django/contrib/auth/hashers.py16
-rw-r--r--django/contrib/auth/tokens.py5
3 files changed, 19 insertions, 16 deletions
diff --git a/django/contrib/auth/__init__.py b/django/contrib/auth/__init__.py
index f83007ac94..d752e3172b 100644
--- a/django/contrib/auth/__init__.py
+++ b/django/contrib/auth/__init__.py
@@ -1,4 +1,3 @@
-import hmac
import inspect
import re
import warnings
@@ -7,6 +6,7 @@ from django.apps import apps as django_apps
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured, PermissionDenied
from django.middleware.csrf import rotate_token
+from django.utils.crypto import constant_time_compare
from django.utils.deprecation import RemovedInDjango61Warning
from django.utils.module_loading import import_string
from django.views.decorators.debug import sensitive_variables
@@ -175,7 +175,7 @@ def login(request, user, backend=None):
if SESSION_KEY in request.session:
if _get_user_session_key(request) != user.pk or (
session_auth_hash
- and not hmac.compare_digest(
+ and not constant_time_compare(
request.session.get(HASH_SESSION_KEY, ""), session_auth_hash
)
):
@@ -217,7 +217,7 @@ async def alogin(request, user, backend=None):
if await request.session.ahas_key(SESSION_KEY):
if await _aget_user_session_key(request) != user.pk or (
session_auth_hash
- and not hmac.compare_digest(
+ and not constant_time_compare(
await request.session.aget(HASH_SESSION_KEY, ""),
session_auth_hash,
)
@@ -323,7 +323,7 @@ def get_user(request):
session_hash_verified = False
else:
session_auth_hash = user.get_session_auth_hash()
- session_hash_verified = hmac.compare_digest(
+ session_hash_verified = constant_time_compare(
session_hash, session_auth_hash
)
if not session_hash_verified:
@@ -331,7 +331,7 @@ def get_user(request):
# with the fallback secrets and stop when a matching one is
# found.
if session_hash and any(
- hmac.compare_digest(session_hash, fallback_auth_hash)
+ constant_time_compare(session_hash, fallback_auth_hash)
for fallback_auth_hash in user.get_session_auth_fallback_hash()
):
request.session.cycle_key()
@@ -364,7 +364,7 @@ async def aget_user(request):
session_hash_verified = False
else:
session_auth_hash = user.get_session_auth_hash()
- session_hash_verified = hmac.compare_digest(
+ session_hash_verified = constant_time_compare(
session_hash, session_auth_hash
)
if not session_hash_verified:
@@ -372,7 +372,7 @@ async def aget_user(request):
# with the fallback secrets and stop when a matching one is
# found.
if session_hash and any(
- hmac.compare_digest(session_hash, fallback_auth_hash)
+ constant_time_compare(session_hash, fallback_auth_hash)
for fallback_auth_hash in user.get_session_auth_fallback_hash()
):
await request.session.acycle_key()
diff --git a/django/contrib/auth/hashers.py b/django/contrib/auth/hashers.py
index 4767ad560b..4bb518cb89 100644
--- a/django/contrib/auth/hashers.py
+++ b/django/contrib/auth/hashers.py
@@ -2,7 +2,6 @@ import base64
import binascii
import functools
import hashlib
-import hmac
import importlib
import math
import warnings
@@ -13,7 +12,12 @@ from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
from django.core.signals import setting_changed
from django.dispatch import receiver
-from django.utils.crypto import RANDOM_STRING_CHARS, get_random_string, pbkdf2
+from django.utils.crypto import (
+ RANDOM_STRING_CHARS,
+ constant_time_compare,
+ get_random_string,
+ pbkdf2,
+)
from django.utils.encoding import force_bytes, force_str
from django.utils.module_loading import import_string
from django.utils.translation import gettext_noop as _
@@ -345,7 +349,7 @@ class PBKDF2PasswordHasher(BasePasswordHasher):
def verify(self, password, encoded):
decoded = self.decode(encoded)
encoded_2 = self.encode(password, decoded["salt"], decoded["iterations"])
- return hmac.compare_digest(encoded, encoded_2)
+ return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
decoded = self.decode(encoded)
@@ -529,7 +533,7 @@ class BCryptSHA256PasswordHasher(BasePasswordHasher):
algorithm, data = encoded.split("$", 1)
assert algorithm == self.algorithm
encoded_2 = self.encode(password, data.encode("ascii"))
- return hmac.compare_digest(encoded, encoded_2)
+ return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
decoded = self.decode(encoded)
@@ -624,7 +628,7 @@ class ScryptPasswordHasher(BasePasswordHasher):
decoded["block_size"],
decoded["parallelism"],
)
- return hmac.compare_digest(encoded, encoded_2)
+ return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
decoded = self.decode(encoded)
@@ -677,7 +681,7 @@ class MD5PasswordHasher(BasePasswordHasher):
def verify(self, password, encoded):
decoded = self.decode(encoded)
encoded_2 = self.encode(password, decoded["salt"])
- return hmac.compare_digest(encoded, encoded_2)
+ return constant_time_compare(encoded, encoded_2)
def safe_summary(self, encoded):
decoded = self.decode(encoded)
diff --git a/django/contrib/auth/tokens.py b/django/contrib/auth/tokens.py
index 8e5d95cefd..09cc2b5195 100644
--- a/django/contrib/auth/tokens.py
+++ b/django/contrib/auth/tokens.py
@@ -1,8 +1,7 @@
-import hmac
from datetime import datetime
from django.conf import settings
-from django.utils.crypto import salted_hmac
+from django.utils.crypto import constant_time_compare, salted_hmac
from django.utils.http import base36_to_int, int_to_base36
@@ -68,7 +67,7 @@ class PasswordResetTokenGenerator:
# Check that the timestamp/uid has not been tampered with
for secret in [self.secret, *self.secret_fallbacks]:
- if hmac.compare_digest(
+ if constant_time_compare(
self._make_token_with_timestamp(user, ts, secret),
token,
):