def fuzz_verifier_bcrypt(self): # test against bcrypt, if available from passlib.handlers.bcrypt import IDENT_2, IDENT_2A, IDENT_2B, IDENT_2X, IDENT_2Y, _detect_pybcrypt from passlib.utils import to_native_str, to_bytes try: import bcrypt except ImportError: return if _detect_pybcrypt(): return def check_bcrypt(secret, hash): """bcrypt""" secret = to_bytes(secret, self.FuzzHashGenerator.password_encoding) if hash.startswith(IDENT_2B): # bcrypt <1.1 lacks 2B support hash = IDENT_2A + hash[4:] elif hash.startswith(IDENT_2): # bcrypt doesn't support $2$ hashes; but we can fake it # using the $2a$ algorithm, by repeating the password until # it's 72 chars in length. hash = IDENT_2A + hash[3:] if secret: secret = repeat_string(secret, 72) elif hash.startswith(IDENT_2Y) and bcrypt.__version__ == "3.0.0": hash = IDENT_2B + hash[4:] hash = to_bytes(hash) try: return bcrypt.hashpw(secret, hash) == hash except ValueError: raise ValueError("bcrypt rejected hash: %r (secret=%r)" % (hash, secret)) return check_bcrypt
def fuzz_verifier_pybcrypt(self): # test against py-bcrypt, if available from passlib.handlers.bcrypt import IDENT_2, IDENT_2A, IDENT_2B, IDENT_2X, IDENT_2Y, _detect_pybcrypt from passlib.utils import to_native_str try: import bcrypt except ImportError: return if not _detect_pybcrypt(): return def check_pybcrypt(secret, hash): """pybcrypt""" secret = to_native_str(secret, self.fuzz_password_encoding) if len(secret) > 200: # vulnerable to wraparound bug secret = secret[:200] if hash.startswith((IDENT_2B, IDENT_2Y)): hash = IDENT_2A + hash[4:] try: return bcrypt.hashpw(secret, hash) == hash except ValueError: raise ValueError("py-bcrypt rejected hash: %r" % (hash,)) return check_pybcrypt