From 48ad9bc7df6f0747c6c8e70b4c0e83e6f932e1e8 Mon Sep 17 00:00:00 2001 From: s3lph Date: Fri, 13 Jul 2018 20:04:42 +0200 Subject: [PATCH] Fixed #3 Password verification apparently vulnerable to timing attacks. --- matemat/db/facade.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/matemat/db/facade.py b/matemat/db/facade.py index 4bd27cd..106c792 100644 --- a/matemat/db/facade.py +++ b/matemat/db/facade.py @@ -2,6 +2,7 @@ from typing import List, Optional, Any, Type import crypt +from hmac import compare_digest from matemat.primitives import User, Product from matemat.exceptions import AuthenticationError, DatabaseConsistencyError @@ -144,9 +145,11 @@ class MatematDatabase(object): if row is None: raise AuthenticationError('User does not exist') user_id, username, email, pwhash, tkhash, admin, member = row - if password is not None and crypt.crypt(password, pwhash) != pwhash: + if password is not None and not compare_digest(crypt.crypt(password, pwhash), pwhash): raise AuthenticationError('Password mismatch') - elif touchkey is not None and tkhash is not None and crypt.crypt(touchkey, tkhash) != tkhash: + elif touchkey is not None \ + and tkhash is not None \ + and not compare_digest(crypt.crypt(touchkey, tkhash), tkhash): raise AuthenticationError('Touchkey mismatch') elif touchkey is not None and tkhash is None: raise AuthenticationError('Touchkey not set') @@ -171,7 +174,7 @@ class MatematDatabase(object): if row is None: raise AuthenticationError('User does not exist in database.') # Verify the old password, if it should be verified. - if verify_password and crypt.crypt(oldpass, row[0]) != row[0]: + if verify_password and not compare_digest(crypt.crypt(oldpass, row[0]), row[0]): raise AuthenticationError('Old password does not match.') # Hash the new password and write it to the database. pwhash: str = crypt.crypt(newpass, crypt.mksalt(_CRYPT_METHOD)) @@ -201,7 +204,7 @@ class MatematDatabase(object): if row is None: raise AuthenticationError('User does not exist in database.') # Verify the password, if it should be verified. - if verify_password and crypt.crypt(password, row[0]) != row[0]: + if verify_password and not compare_digest(crypt.crypt(password, row[0]), row[0]): raise AuthenticationError('Password does not match.') # Hash the new touchkey and write it to the database. tkhash: str = crypt.crypt(touchkey, crypt.mksalt(_CRYPT_METHOD)) if touchkey is not None else None