diff options
author | Frederick Muriuki Muriithi | 2023-03-08 11:18:35 +0300 |
---|---|---|
committer | Frederick Muriuki Muriithi | 2023-03-08 11:18:35 +0300 |
commit | 5a8cc0d7fc241494580cd4a060690eaf09ff46d7 (patch) | |
tree | eb9a9fa88027f28d2ec1421f0080e4260ecfe12d | |
parent | 8621b737b01be5a6f238725c65771dea1410f0bb (diff) | |
download | genenetwork3-5a8cc0d7fc241494580cd4a060690eaf09ff46d7.tar.gz |
Replace Bcrypt with Argon2 for better security.
Bcrypt is now somewhat vulnerable to offline cracking, so we move our password
hashing over to Argon2.
-rw-r--r-- | README.md | 12 | ||||
-rw-r--r-- | gn3/auth/authentication/users.py | 12 | ||||
-rw-r--r-- | main.py | 4 | ||||
-rw-r--r-- | mypy.ini | 6 |
4 files changed, 23 insertions, 11 deletions
@@ -194,17 +194,17 @@ following environment variable(s): To run tests: ```bash -$ export AUTHLIB_INSECURE_TRANSPORT=true -$ export OAUTH2_ACCESS_TOKEN_GENERATOR="tests.unit.auth.test_token.gen_token" -$ pytest +export AUTHLIB_INSECURE_TRANSPORT=true +export OAUTH2_ACCESS_TOKEN_GENERATOR="tests.unit.auth.test_token.gen_token" +pytest ``` To specify unit-tests: ```bash -$ export AUTHLIB_INSECURE_TRANSPORT=true -$ export OAUTH2_ACCESS_TOKEN_GENERATOR="tests.unit.auth.test_token.gen_token" -$ pytest -k unit_test +export AUTHLIB_INSECURE_TRANSPORT=true +export OAUTH2_ACCESS_TOKEN_GENERATOR="tests.unit.auth.test_token.gen_token" +pytest -k unit_test ``` Running pylint: diff --git a/gn3/auth/authentication/users.py b/gn3/auth/authentication/users.py index 54838a3..5ee148f 100644 --- a/gn3/auth/authentication/users.py +++ b/gn3/auth/authentication/users.py @@ -2,7 +2,8 @@ from uuid import UUID, uuid4 from typing import Any, Tuple, NamedTuple -import bcrypt +from argon2 import PasswordHasher +from argon2.exceptions import VerifyMismatchError from gn3.auth import db from gn3.auth.authorisation.errors import NotFoundError @@ -60,7 +61,11 @@ def valid_login(conn: db.DbConnection, user: User, password: str) -> bool: if row is None: return False - return bcrypt.checkpw(password.encode("utf-8"), row["password"]) + hasher = PasswordHasher() # TODO: Maybe tune the parameters here... + try: + return hasher.verify(row["password"], password) + except VerifyMismatchError as _vme: + return False def save_user(cursor: db.DbCursor, email: str, name: str) -> User: """ @@ -79,7 +84,8 @@ def save_user(cursor: db.DbCursor, email: str, name: str) -> User: def set_user_password( cursor: db.DbCursor, user: User, password: str) -> Tuple[User, bytes]: """Set the given user's password in the database.""" - hashed_password = bcrypt.hashpw(password.encode("utf8"), bcrypt.gensalt()) + hasher = PasswordHasher() # TODO: Maybe tune the parameters here... + hashed_password = hasher.hash(password) cursor.execute( ("INSERT INTO user_credentials VALUES (:user_id, :hash) " "ON CONFLICT (user_id) DO UPDATE SET password=:hash"), @@ -7,7 +7,7 @@ from datetime import datetime import click -import bcrypt +from argon2 import PasswordHasher from yoyo import get_backend, read_migrations from gn3 import migrations @@ -37,7 +37,7 @@ def __init_dev_users__(): "password": "testpasswd"},) def __hash_passwd__(passwd): - return bcrypt.hashpw(passwd.encode("utf8"), bcrypt.gensalt()) + return PasswordHasher().hash(passwd) with db.connection(app.config["AUTH_DB"]) as conn, db.cursor(conn) as cursor: cursor.executemany(dev_users_query, dev_users) @@ -63,3 +63,9 @@ ignore_missing_imports = True [mypy-email_validator] ignore_missing_imports = True + +[mypy-argon2] +ignore_missing_imports = True + +[mypy-argon2.*] +ignore_missing_imports = True
\ No newline at end of file |