From c5ceae58191aa0a3913c7099c039f50cd2000a64 Mon Sep 17 00:00:00 2001 From: Nick Daly Date: Sun, 2 Mar 2014 15:36:22 -0600 Subject: [PATCH] Properly use bcrypt: - Don't crypto: use a library provided time-independent comparison. - Document details about max password length and other caveats. --- modules/installed/lib/auth.py | 42 ++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 18 deletions(-) diff --git a/modules/installed/lib/auth.py b/modules/installed/lib/auth.py index 97fecaf05..71b10c387 100644 --- a/modules/installed/lib/auth.py +++ b/modules/installed/lib/auth.py @@ -51,31 +51,37 @@ def add_user(username, passphrase, name='', email='', expert=False): def check_credentials(username, passphrase): """Verifies credentials for username and passphrase. - Returns None on success or a string describing the error on failure""" + Returns None on success or a string describing the error on failure. + + Handles passwords up to 4096 bytes: + + >>> len("A" * 4096) + 4096 + >>> len(u"u|2603" * 682) + 4092 + + """ if not username or not passphrase: error = "No username or password." cfg.log(error) return error - # hash the password whether the user exists, to foil timing - # side-channel attacks - try: - if username in cfg.users: - u = cfg.users[username] - pass_hash = bcrypt.encrypt(passphrase, salt=u['salt']) - else: - u = None - pass_hash = bcrypt.encrypt(passphrase) - except PasswordSizeError: - error = "Password is too long." - cfg.log(error) - return error + bad_authentication = "Bad user-name or password." + hashed_password = None - if u is None or u['passphrase'] != pass_hash: - error = "Bad user-name or password." - else: - error = None + if username in cfg.users: + if "passphrase" in cfg.users[username]: + hashed_password = cfg.users[username]['passphrase'] + + try: + # time-dependent comparison when non-ASCII characters are used. + if not bcrypt.verify(passphrase, hashed_password): + error = bad_authentication + else: + error = None + except PasswordSizeError: + error = bad_authentication if error: cfg.log(error)