Skip to content

Commit

Permalink
Use constant time string comparisons
Browse files Browse the repository at this point in the history
This uses constant time string comparisons everywhere that looked plausibly like it
might matter:

 - Plaintext password comparison
 - Digest nonce comparison
 - Digest hash comparison

Fixes miguelgrinberg#82
  • Loading branch information
brendanlong committed Apr 10, 2019
1 parent 3f743c6 commit 4e89669
Showing 1 changed file with 8 additions and 3 deletions.
11 changes: 8 additions & 3 deletions flask_httpauth.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@

from functools import wraps
from hashlib import md5
from hmac import compare_digest
from random import Random, SystemRandom
from flask import request, make_response, session
from werkzeug.datastructures import Authorization
Expand Down Expand Up @@ -143,7 +144,8 @@ def authenticate(self, auth, stored_password):
client_password = self.hash_password_callback(username,
client_password)
return client_password is not None and \
client_password == stored_password
stored_password is not None and \
compare_digest(client_password, stored_password)


class HTTPDigestAuth(HTTPAuth):
Expand All @@ -169,7 +171,10 @@ def default_generate_nonce():
return session["auth_nonce"]

def default_verify_nonce(nonce):
return nonce == session.get("auth_nonce")
session_nonce = session.get("auth_nonce")
if nonce is None or session_nonce is None:
return False
return compare_digest(nonce, session_nonce)

def default_generate_opaque():
session["auth_opaque"] = _generate_random()
Expand Down Expand Up @@ -235,7 +240,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 response == auth.response
return compare_digest(response, auth.response)


class HTTPTokenAuth(HTTPAuth):
Expand Down

0 comments on commit 4e89669

Please sign in to comment.