Mercurial > kallithea
changeset 8272:1e0632b6ec27
auth: also use safe password hashing on Windows using bcrypt
For unknown reasons, Kallithea used different hashing algorithms on Windows and
Posix. Perhaps because problems with bcrypt on Windows in the past. That should
no longer be an issue, and it doesn't make sense to have different security
properties on the platforms.
While changing to bcrypt everywhere, also remain backwards compatible and
accept existing passwords hashed with sha256 - both on Windows (where it used
to be used), and elsewhere (in case a system has been migrated from Windows to
Unix).
author | Mads Kiilerich <mads@kiilerich.com> |
---|---|
date | Mon, 30 Dec 2019 01:02:36 +0100 |
parents | 2ce0bc6e85f1 |
children | db1fb0a3e7f0 |
files | kallithea/lib/auth.py setup.py |
diffstat | 2 files changed, 17 insertions(+), 29 deletions(-) [+] |
line wrap: on
line diff
--- a/kallithea/lib/auth.py Sun Aug 04 18:35:21 2019 +0200 +++ b/kallithea/lib/auth.py Mon Dec 30 01:02:36 2019 +0100 @@ -30,6 +30,7 @@ import os import string +import bcrypt import ipaddr from decorator import decorator from sqlalchemy.orm import joinedload @@ -38,7 +39,6 @@ from tg.i18n import ugettext as _ from webob.exc import HTTPForbidden, HTTPFound -from kallithea import __platform__, is_unix, is_windows from kallithea.config.routing import url from kallithea.lib.caching_query import FromCache from kallithea.lib.utils import conditional_cache, get_repo_group_slug, get_repo_slug, get_user_group_slug @@ -87,44 +87,34 @@ def get_crypt_password(password): """ - Cryptographic function used for password hashing based on pybcrypt - or Python's own OpenSSL wrapper on windows + Cryptographic function used for bcrypt password hashing. :param password: password to hash """ - if is_windows: - return hashlib.sha256(password).hexdigest() - elif is_unix: - import bcrypt - return ascii_str(bcrypt.hashpw(safe_bytes(password), bcrypt.gensalt(10))) - else: - raise Exception('Unknown or unsupported platform %s' - % __platform__) + return ascii_str(bcrypt.hashpw(safe_bytes(password), bcrypt.gensalt(10))) def check_password(password, hashed): """ - Checks matching password with it's hashed value, runs different - implementation based on platform it runs on + Checks password match the hashed value using bcrypt. + Remains backwards compatible and accept plain sha256 hashes which used to + be used on Windows. :param password: password :param hashed: password in hashed form """ # sha256 hashes will always be 64 hex chars # bcrypt hashes will always contain $ (and be shorter) - if is_windows or len(hashed) == 64 and all(x in string.hexdigits for x in hashed): - return hashlib.sha256(safe_bytes(password)).hexdigest() == hashed - elif is_unix: - import bcrypt - try: - return bcrypt.checkpw(safe_bytes(password), ascii_bytes(hashed)) - except ValueError as e: - # bcrypt will throw ValueError 'Invalid hashed_password salt' on all password errors - log.error('error from bcrypt checking password: %s', e) - return False - else: - raise Exception('Unknown or unsupported platform %s' - % __platform__) + if len(hashed) == 64 and all(x in string.hexdigits for x in hashed): + return hashlib.sha256(password).hexdigest() == hashed + try: + return bcrypt.checkpw(safe_bytes(password), ascii_bytes(hashed)) + except ValueError as e: + # bcrypt will throw ValueError 'Invalid hashed_password salt' on all password errors + log.error('error from bcrypt checking password: %s', e) + return False + log.error('check_password failed - no method found for hash length %s', len(hashed)) + return False def _cached_perms_data(user_id, user_is_admin):
--- a/setup.py Sun Aug 04 18:35:21 2019 +0200 +++ b/setup.py Mon Dec 30 01:02:36 2019 +0100 @@ -71,11 +71,9 @@ "ipaddr >= 2.2.0, < 2.3", "paginate >= 0.5, < 0.6", "paginate_sqlalchemy >= 0.3.0, < 0.4", + "bcrypt >= 3.1.0, < 3.2", ] -if not is_windows: - requirements.append("bcrypt >= 3.1.0, < 3.2") - dependency_links = [ ]