Skip to content

Commit 55f3f55

Browse files
committed
Remove constant_time_compare util
1 parent b9ded8f commit 55f3f55

File tree

5 files changed

+29
-20
lines changed

5 files changed

+29
-20
lines changed

plain-auth/plain/auth/sessions.py

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
import hmac
2+
13
from plain.exceptions import ImproperlyConfigured
24
from plain.models import models_registry
35
from plain.runtime import settings
4-
from plain.utils.crypto import constant_time_compare, salted_hmac
6+
from plain.utils.crypto import salted_hmac
7+
from plain.utils.encoding import force_bytes
58

69
USER_ID_SESSION_KEY = "_auth_user_id"
710
USER_HASH_SESSION_KEY = "_auth_user_hash"
@@ -60,8 +63,9 @@ def login(request, user):
6063
# session if the existing session corresponds to a different
6164
# authenticated user.
6265
request.session.flush()
63-
elif session_auth_hash and not constant_time_compare(
64-
request.session.get(USER_HASH_SESSION_KEY, ""), session_auth_hash
66+
elif session_auth_hash and not hmac.compare_digest(
67+
force_bytes(request.session.get(USER_HASH_SESSION_KEY, "")),
68+
force_bytes(session_auth_hash),
6569
):
6670
# If the session hash does not match the current hash, reset the
6771
# session. Most likely this means the password was changed.
@@ -131,15 +135,17 @@ def get_user(request):
131135
session_hash_verified = False
132136
else:
133137
session_auth_hash = get_session_auth_hash(user)
134-
session_hash_verified = constant_time_compare(
135-
session_hash, session_auth_hash
138+
session_hash_verified = hmac.compare_digest(
139+
force_bytes(session_hash), force_bytes(session_auth_hash)
136140
)
137141
if not session_hash_verified:
138142
# If the current secret does not verify the session, try
139143
# with the fallback secrets and stop when a matching one is
140144
# found.
141145
if session_hash and any(
142-
constant_time_compare(session_hash, fallback_auth_hash)
146+
hmac.compare_digest(
147+
force_bytes(session_hash), force_bytes(fallback_auth_hash)
148+
)
143149
for fallback_auth_hash in get_session_auth_fallback_hash(user)
144150
):
145151
request.session.cycle_key()

plain-passwords/plain/passwords/hashers.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import binascii
33
import functools
44
import hashlib
5+
import hmac
56
import importlib
67
import math
78
import warnings
@@ -10,10 +11,10 @@
1011
from plain.runtime import settings
1112
from plain.utils.crypto import (
1213
RANDOM_STRING_CHARS,
13-
constant_time_compare,
1414
get_random_string,
1515
pbkdf2,
1616
)
17+
from plain.utils.encoding import force_bytes
1718
from plain.utils.module_loading import import_string
1819

1920

@@ -289,7 +290,7 @@ def decode(self, encoded):
289290
def verify(self, password, encoded):
290291
decoded = self.decode(encoded)
291292
encoded_2 = self.encode(password, decoded["salt"], decoded["iterations"])
292-
return constant_time_compare(encoded, encoded_2)
293+
return hmac.compare_digest(force_bytes(encoded), force_bytes(encoded_2))
293294

294295
def safe_summary(self, encoded):
295296
decoded = self.decode(encoded)
@@ -472,7 +473,7 @@ def verify(self, password, encoded):
472473
algorithm, data = encoded.split("$", 1)
473474
assert algorithm == self.algorithm
474475
encoded_2 = self.encode(password, data.encode("ascii"))
475-
return constant_time_compare(encoded, encoded_2)
476+
return hmac.compare_digest(force_bytes(encoded), force_bytes(encoded_2))
476477

477478
def safe_summary(self, encoded):
478479
decoded = self.decode(encoded)
@@ -567,7 +568,7 @@ def verify(self, password, encoded):
567568
decoded["block_size"],
568569
decoded["parallelism"],
569570
)
570-
return constant_time_compare(encoded, encoded_2)
571+
return hmac.compare_digest(force_bytes(encoded), force_bytes(encoded_2))
571572

572573
def safe_summary(self, encoded):
573574
decoded = self.decode(encoded)

plain-passwords/plain/passwords/views.py

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import hmac
12
from datetime import datetime
23

34
from plain import signing
@@ -10,7 +11,7 @@
1011
)
1112
from plain.urls import reverse
1213
from plain.utils.cache import add_never_cache_headers
13-
from plain.utils.crypto import constant_time_compare
14+
from plain.utils.encoding import force_bytes
1415
from plain.views import CreateView, FormView
1516

1617
from .forms import (
@@ -73,11 +74,13 @@ def check_password_reset_token(self, token):
7374

7475
# If the password has changed since the token was generated, the token is invalid.
7576
# (These are the hashed passwords, not the raw passwords.)
76-
if not constant_time_compare(user.password, data["password"]):
77+
if not hmac.compare_digest(
78+
force_bytes(user.password), force_bytes(data["password"])
79+
):
7780
return
7881

7982
# If the email has changed since the token was generated, the token is invalid.
80-
if not constant_time_compare(user.email, data["email"]):
83+
if not hmac.compare_digest(force_bytes(user.email), force_bytes(data["email"])):
8184
return
8285

8386
return user

plain/plain/signing.py

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,14 @@
3535

3636
import base64
3737
import datetime
38+
import hmac
3839
import json
3940
import time
4041
import zlib
4142

4243
from plain.runtime import settings
43-
from plain.utils.crypto import constant_time_compare, salted_hmac
44+
from plain.utils.crypto import salted_hmac
45+
from plain.utils.encoding import force_bytes
4446
from plain.utils.regex_helper import _lazy_re_compile
4547

4648
_SEP_UNSAFE = _lazy_re_compile(r"^[A-z0-9-_=]*$")
@@ -196,7 +198,9 @@ def unsign(self, signed_value):
196198
raise BadSignature(f'No "{self.sep}" found in value')
197199
value, sig = signed_value.rsplit(self.sep, 1)
198200
for key in [self.key, *self.fallback_keys]:
199-
if constant_time_compare(sig, self.signature(value, key)):
201+
if hmac.compare_digest(
202+
force_bytes(sig), force_bytes(self.signature(value, key))
203+
):
200204
return value
201205
raise BadSignature(f'Signature "{sig}" does not match')
202206

plain/plain/utils/crypto.py

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,11 +62,6 @@ def get_random_string(length, allowed_chars=RANDOM_STRING_CHARS):
6262
return "".join(secrets.choice(allowed_chars) for i in range(length))
6363

6464

65-
def constant_time_compare(val1, val2):
66-
"""Return True if the two strings are equal, False otherwise."""
67-
return secrets.compare_digest(force_bytes(val1), force_bytes(val2))
68-
69-
7065
def pbkdf2(password, salt, iterations, dklen=0, digest=None):
7166
"""Return the hash of password using pbkdf2."""
7267
if digest is None:

0 commit comments

Comments
 (0)