diff --git a/pagure/lib/login.py b/pagure/lib/login.py index 0e8bbae..a5b6c58 100644 --- a/pagure/lib/login.py +++ b/pagure/lib/login.py @@ -5,7 +5,7 @@ Authors: Pierre-Yves Chibon - Farhaan Bukhsh + Farhaan Bukhsh """ @@ -13,10 +13,10 @@ import random import string import hashlib import bcrypt +import six import pagure from pagure.lib import model -from kitchen.text.converters import to_unicode, to_bytes from cryptography.hazmat.primitives import constant_time @@ -49,15 +49,32 @@ def get_session_by_visitkey(session, sessionid): def generate_hashed_value(password): - """ Generate hash value for password - """ - return '$2$' + bcrypt.hashpw(password.encode('UTF_8'), + ''' Generate hash value for password. + + :arg password: password for which the hash has to be generated. + :type password: str (Python 3) or unicode (Python 2) + :return: a hashed string of characters. + :rtype: an encoded string(bytes). + ''' + if not isinstance(password, six.text_type): + raise ValueError("Password supplied is not unicode text") + + return '$2$' + bcrypt.hashpw(password.encode('utf-8'), bcrypt.gensalt()) def check_password(entered_password, user_password, seed=None): - """ Version checking and returning the password - """ + ''' Version checking and returning the password + + :arg entered_password: password entered by the user. + :type entered_password: str (Python 3) or unicode (Python 2) + :arg user_password: the hashed string fetched from the database. + :return: a Boolean depending upon the entered_password, True if the + password matches + ''' + if not isinstance(entered_password, six.text_type): + raise ValueError("Entered password is not unicode text") + if not user_password.count('$') >= 2: raise pagure.exceptions.PagureException( 'Password of unknown version found in the database' @@ -66,12 +83,12 @@ def check_password(entered_password, user_password, seed=None): _, version, user_password = user_password.split('$', 2) if version == '2': - password = bcrypt.hashpw(entered_password.encode('UTF_8'), - user_password) - + password = bcrypt.hashpw( + entered_password.encode('utf-8'), + user_password.encode('utf-8')) elif version == '1': - password = '%s%s' % (to_unicode(entered_password), seed) - password = hashlib.sha512(password).hexdigest() + password = '%s%s' % (entered_password, seed) + password = hashlib.sha512(password.encode('utf-8')).hexdigest() else: raise pagure.exceptions.PagureException( @@ -79,4 +96,4 @@ def check_password(entered_password, user_password, seed=None): ) return constant_time.bytes_eq( - to_bytes(password), to_bytes(user_password)) + password.encode('utf-8'), user_password.encode('utf-8')) diff --git a/tests/test_pagure_lib_login.py b/tests/test_pagure_lib_login.py index 68fbe86..1e483fe 100644 --- a/tests/test_pagure_lib_login.py +++ b/tests/test_pagure_lib_login.py @@ -47,7 +47,7 @@ class PagureLibLogintests(tests.Modeltests): def test_generate_hashed_value(self): ''' Test pagure.lib.login.generate_hashed_value. ''' - password = pagure.lib.login.generate_hashed_value('foo') + password = pagure.lib.login.generate_hashed_value(u'foo') self.assertTrue(password.startswith('$2$')) self.assertEqual(len(password), 63) @@ -55,25 +55,25 @@ class PagureLibLogintests(tests.Modeltests): ''' Test pagure.lib.login.check_password. ''' # Version 2 - password = pagure.lib.login.generate_hashed_value('foo') + password = pagure.lib.login.generate_hashed_value(u'foo') self.assertTrue( - pagure.lib.login.check_password('foo', password)) + pagure.lib.login.check_password(u'foo', password)) self.assertFalse( - pagure.lib.login.check_password('bar', password)) + pagure.lib.login.check_password(u'bar', password)) # Version 1 - password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) + password = '%s%s' % (u'foo', pagure.config.config.get('PASSWORD_SEED', None)) password = '$1$' + hashlib.sha512(password).hexdigest() - self.assertTrue(pagure.lib.login.check_password('foo', password)) - self.assertFalse(pagure.lib.login.check_password('bar', password)) + self.assertTrue(pagure.lib.login.check_password(u'foo', password)) + self.assertFalse(pagure.lib.login.check_password(u'bar', password)) # Invalid password - No version - password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) + password = '%s%s' % (u'foo', pagure.config.config.get('PASSWORD_SEED', None)) password = hashlib.sha512(password).hexdigest() self.assertRaises( PagureException, pagure.lib.login.check_password, - 'foo', password + u'foo', password ) # Invalid password - Invalid version @@ -81,15 +81,15 @@ class PagureLibLogintests(tests.Modeltests): self.assertRaises( PagureException, pagure.lib.login.check_password, - 'foo', + u'foo', password ) - password = '%s%s' % ('foo', pagure.config.config.get('PASSWORD_SEED', None)) + password = '%s%s' % (u'foo', pagure.config.config.get('PASSWORD_SEED', None)) password = hashlib.sha512(password).hexdigest() self.assertRaises( PagureException, pagure.lib.login.check_password, - 'foo', password + u'foo', password ) # Invalid password - Invalid version @@ -97,9 +97,26 @@ class PagureLibLogintests(tests.Modeltests): self.assertRaises( PagureException, pagure.lib.login.check_password, - 'foo', + u'foo', password ) + def test_unicode_required(self): + ''' Test to check for non-ascii password + ''' + self.assertRaises( + ValueError, + pagure.lib.login.generate_hashed_value, + u'hunter2'.encode('utf-8') + ) + password = pagure.lib.login.generate_hashed_value(u'foo') + self.assertRaises( + ValueError, + pagure.lib.login.check_password, + u'foo'.encode('utf-8'), + password + ) + + if __name__ == '__main__': unittest.main(verbosity=2)