8
0
Fork 0
mirror of https://gitlab2.federez.net/re2o/re2o synced 2024-10-31 23:22:49 +00:00

login handler: Use constant-time comparaison for hashes.

An attacker knowing the salt but not the hash could try timming-attacks
to guess a password hash and then try to find it from the hash.
Although not a high risk, there is no good reason not to use a
constant-time comparison, hence this commit.
This commit is contained in:
David Sinquin 2018-08-04 22:52:59 +02:00
parent 3244a46d94
commit ca08234a81

View file

@ -35,6 +35,7 @@ import os
from base64 import encodestring, decodestring, b64encode, b64decode from base64 import encodestring, decodestring, b64encode, b64decode
from collections import OrderedDict from collections import OrderedDict
from django.contrib.auth import hashers from django.contrib.auth import hashers
from hmac import compare_digest as constant_time_compare
ALGO_NAME = "{SSHA}" ALGO_NAME = "{SSHA}"
@ -63,12 +64,7 @@ def checkPassword(challenge_password, password):
salt = challenge_bytes[DIGEST_LEN:] salt = challenge_bytes[DIGEST_LEN:]
hr = hashlib.sha1(password.encode()) hr = hashlib.sha1(password.encode())
hr.update(salt) hr.update(salt)
valid_password = True return constant_time_compare(digest, hr.digest())
# La comparaison est volontairement en temps constant
# (pour éviter les timing-attacks)
for i, j in zip(digest, hr.digest()):
valid_password &= i == j
return valid_password
def hash_password_salt(hashed_password): def hash_password_salt(hashed_password):
@ -118,7 +114,8 @@ class CryptPasswordHasher(hashers.BasePasswordHasher):
""" """
assert encoded.startswith(self.algorithm) assert encoded.startswith(self.algorithm)
salt = hash_password_salt(challenge_password) salt = hash_password_salt(challenge_password)
return crypt.crypt(password.encode(), salt) == challenge.encode() return constant_time_compare(crypt.crypt(password.encode(), salt),
challenge.encode())
def safe_summary(self, encoded): def safe_summary(self, encoded):
""" """
@ -159,7 +156,9 @@ class MD5PasswordHasher(hashers.BasePasswordHasher):
""" """
assert encoded.startswith(self.algorithm) assert encoded.startswith(self.algorithm)
salt = hash_password_salt(encoded) salt = hash_password_salt(encoded)
return b64encode(hashlib.md5(password.encode() + salt).digest() + salt) == encoded.encode() return constant_time_compare(
b64encode(hashlib.md5(password.encode() + salt).digest() + salt),
encoded.encode())
def safe_summary(self, encoded): def safe_summary(self, encoded):
""" """