1
0
Fork 0
forked from s3lph/matemat

Merge branch '3-constant-time-password-verification' into 'master'

Resolve "Password verification apparently vulnerable to timing attacks"

Closes #3

See merge request s3lph/matemat!11
This commit is contained in:
s3lph 2018-07-13 20:08:11 +00:00
commit b12535bc93

View file

@ -2,6 +2,7 @@
from typing import List, Optional, Any, Type from typing import List, Optional, Any, Type
import crypt import crypt
from hmac import compare_digest
from matemat.primitives import User, Product from matemat.primitives import User, Product
from matemat.exceptions import AuthenticationError, DatabaseConsistencyError from matemat.exceptions import AuthenticationError, DatabaseConsistencyError
@ -144,9 +145,11 @@ class MatematDatabase(object):
if row is None: if row is None:
raise AuthenticationError('User does not exist') raise AuthenticationError('User does not exist')
user_id, username, email, pwhash, tkhash, admin, member = row 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') 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') raise AuthenticationError('Touchkey mismatch')
elif touchkey is not None and tkhash is None: elif touchkey is not None and tkhash is None:
raise AuthenticationError('Touchkey not set') raise AuthenticationError('Touchkey not set')
@ -171,7 +174,7 @@ class MatematDatabase(object):
if row is None: if row is None:
raise AuthenticationError('User does not exist in database.') raise AuthenticationError('User does not exist in database.')
# Verify the old password, if it should be verified. # 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.') raise AuthenticationError('Old password does not match.')
# Hash the new password and write it to the database. # Hash the new password and write it to the database.
pwhash: str = crypt.crypt(newpass, crypt.mksalt(_CRYPT_METHOD)) pwhash: str = crypt.crypt(newpass, crypt.mksalt(_CRYPT_METHOD))
@ -201,7 +204,7 @@ class MatematDatabase(object):
if row is None: if row is None:
raise AuthenticationError('User does not exist in database.') raise AuthenticationError('User does not exist in database.')
# Verify the password, if it should be verified. # 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.') raise AuthenticationError('Password does not match.')
# Hash the new touchkey and write it to the database. # 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 tkhash: str = crypt.crypt(touchkey, crypt.mksalt(_CRYPT_METHOD)) if touchkey is not None else None