diff --git a/src/zope/password/password.py b/src/zope/password/password.py index 3e10921..27821e1 100644 --- a/src/zope/password/password.py +++ b/src/zope/password/password.py @@ -509,11 +509,6 @@ def _clean_clear(self, password): def _clean_hashed(self, hashed_password): return self._to_bytes(hashed_password, 'ascii') - def _unwind_hashed(self, hashed_password, salt_offset=29): - hashed_pw = self._clean_hashed(hashed_password) - deprefixed = hashed_pw[hashed_pw.find(b'}') + 1:] - return (deprefixed[salt_offset:], deprefixed[:-salt_offset]) - gensalt = staticmethod(bcrypt.gensalt) def checkPassword(self, hashed_password, clear_password): @@ -526,11 +521,14 @@ def checkPassword(self, hashed_password, clear_password): :returns: True iif hashed passwords are equal. :rtype: bool """ + if not self.match(hashed_password): + return False pw_bytes = self._clean_clear(clear_password) - (a_hash, a_salt) = self._unwind_hashed(hashed_password) - rehashed = self.encodePassword(pw_bytes, salt=a_salt) - b_hash = self._unwind_hashed(rehashed)[0] - return a_hash == b_hash + pw_hash = hashed_password[len(self._prefix):] + try: + return bcrypt.hashpw(pw_bytes, pw_hash) == pw_hash + except ValueError: + return False def encodePassword(self, password, salt=None): """Encode a `password`, with an optional `salt`. diff --git a/src/zope/password/tests/test_password.py b/src/zope/password/tests/test_password.py index 4bc2047..5691387 100644 --- a/src/zope/password/tests/test_password.py +++ b/src/zope/password/tests/test_password.py @@ -92,7 +92,7 @@ def test_encodePassword_with_salt(self): def test_checkPassword(self): encoded = ( b'{BCRYPT}' - b'$2a$12$58tzOTIlN5FJfgCqC.zIbu0WF8KKIMOaDmdLWGHDEVd5lwRRTCd.y' + b'$2b$12$ez4eHl6W1PfAWix5bPIbe.drdnyqjpuT1Cp0N.xcdxkAEbA7K6AHK' ) pw_mgr = self._make_one() self.assertTrue(pw_mgr.checkPassword(encoded, self.password))