def determine_pbkdf2_rounds(password_length, salt_length, hash_length, method, duration): # Pure Python implementation based on the CommonCrypto code found at: # http://opensource.apple.com/source/CommonCrypto/CommonCrypto-55010/Source/API/CommonKeyDerivation.c # # TODO: `time.clock()` is not necessarily very precise, it is the most # precise clock available with 2.x though. I haven't looked into # whether this might be an issue on some platforms and I haven't # written bindings for higher precision clocks because the APIs # are different on each platform. However if precision is an # issue this might need to be done. round_measure = 10000 # We use random "passwords" and "salts" to prevent the interpreter from # performing optimizations that mess with the timings. arguments = [ (_generate_password(password_length), os.urandom(salt_length)) for _ in range(5) ] for password, salt in arguments: start = time.clock() pbkdf2(password, salt, round_measure, hash_length, method) end = time.clock() elapsed = (end - start) if elapsed >= 0: return int(math.ceil(duration * round_measure / elapsed)) raise RuntimeError("measurement failed")
def test_pbkdf2(password, salt, rounds, hash_length, expected_hashes, run_fast): if rounds > 100000 and run_fast: pytest.skip(u"too slow for --fast") for method, expected_hash in expected_hashes.items(): try: hash = hexlify(pbkdf2( password, salt, rounds, hash_length, method )) assert hash == expected_hash except NotImplementedError: assert method not in PBKDF2_METHODS with pytest.raises(ValueError): pbkdf2(b"password", b"salt", 0, 20) with pytest.raises(ValueError): pbkdf2(b"password", b"salt", 1, 0)
def _verify_from_bytes(self, password, formatted_hash): parsed = self.parse(formatted_hash) hash = pbkdf2( password, parsed.salt, parsed.rounds, len(parsed.hash), parsed.method ) return constant_time_equal(hash, parsed.hash)
def _create_from_bytes(self, password): salt = generate_salt(self.salt_length) return self.format(PasswordHash( self.name, pbkdf2( password, salt, self.rounds, self.hash_length, self.method ), method=self.method, rounds=self.rounds, salt=salt ))