Skip to content

Commit

Permalink
use werkzeug's safe_str_cmp instead of compare_digest
Browse files Browse the repository at this point in the history
  • Loading branch information
miguelgrinberg committed May 19, 2019
1 parent 788d42e commit 97f0e64
Showing 1 changed file with 10 additions and 27 deletions.
37 changes: 10 additions & 27 deletions flask_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,11 @@
from random import Random, SystemRandom
from flask import request, make_response, session
from werkzeug.datastructures import Authorization
from werkzeug.security import safe_str_cmp

__version__ = '3.2.4'


try:
from hmac import compare_digest
except ImportError:
import operator

# This fallback is not constant-time, but making it constant-time
# introduces additional complexity. For full-secure password
# comparison, applications should use Python 2 >= 2.7.7 or
# Python 3 >= 3.4, or use hashed passwords.
compare_digest = operator.eq


class HTTPAuth(object):
def __init__(self, scheme=None, realm=None):
self.scheme = scheme
Expand Down Expand Up @@ -154,18 +143,9 @@ def authenticate(self, auth, stored_password):
except TypeError:
client_password = self.hash_password_callback(username,
client_password)
if stored_password is None or client_password is None:
return False

try:
stored_password = stored_password.encode("utf-8")
except AttributeError:
pass
try:
client_password = client_password.encode("utf-8")
except AttributeError:
pass
return compare_digest(client_password, stored_password)
return client_password is not None and \
stored_password is not None and \
safe_str_cmp(client_password, stored_password)


class HTTPDigestAuth(HTTPAuth):
Expand Down Expand Up @@ -194,14 +174,17 @@ def default_verify_nonce(nonce):
session_nonce = session.get("auth_nonce")
if nonce is None or session_nonce is None:
return False
return compare_digest(nonce, session_nonce)
return safe_str_cmp(nonce, session_nonce)

def default_generate_opaque():
session["auth_opaque"] = _generate_random()
return session["auth_opaque"]

def default_verify_opaque(opaque):
return opaque == session.get("auth_opaque")
session_opaque = session.get("auth_opaque")
if opaque is None or session_opaque is None:
return False
return safe_str_cmp(opaque, session_opaque)

self.generate_nonce(default_generate_nonce)
self.generate_opaque(default_generate_opaque)
Expand Down Expand Up @@ -260,7 +243,7 @@ def authenticate(self, auth, stored_password_or_ha1):
ha2 = md5(a2.encode('utf-8')).hexdigest()
a3 = ha1 + ":" + auth.nonce + ":" + ha2
response = md5(a3.encode('utf-8')).hexdigest()
return compare_digest(response, auth.response)
return safe_str_cmp(response, auth.response)


class HTTPTokenAuth(HTTPAuth):
Expand Down

0 comments on commit 97f0e64

Please sign in to comment.