Skip to content

PBKDF1

PBKDF1

Since the Input to the function is of fixed size and exactly equal to the output size there is a smaller amount of possible inputs and also it makes the 2 iteration have the same possible inputs as the 10th iteration.

Either there will be a larger possibility for collision of two arbitrary messages.
Or there will be a cycle where hashing a message creates the same output as hashing the same message N times.

Implementation

How it works:

import hashlib

def fixedlen_xor(input1, input2):
	assert(len(input1) == len(input2))
	return bytes([input1[i] ^ input2[i] for i in range(len(input1))])

def int_to_bytes_length(i_data, length, be=True):
	if be:
		return (i_data).to_bytes(length, byteorder='big')
	else:
		return (i_data).to_bytes(length, byteorder='little')

def hmac(key, message, hash_function):
	#Get hash_function block_size
	block_size = getattr(hash_function(), 'block_size')

	# Check if key is longer than block size.
	if len(key) > block_size:
		# IF it is then hash the key. This makes the keysize the same as the output of the hashfunction
		key = hash_function(key).digest()

	# IF key is shorter
	if len(key) < block_size:
		# Pad the key to blocksize
		key = key + b"\x00" * (block_size - len(key))

	#print(key, len(key), block_size)

	# Create Keys
	o_key = fixedlen_xor(key, b"\x5c" * block_size)
	i_key = fixedlen_xor(key, b"\x36" * block_size)

	#Hash i_key and message
	tmp = hash_function(i_key + message)

	#Hash the o_key and the hashed output of above
	return hash_function(o_key + tmp.digest()).digest()

def pbkdf1(password, salt, itterations=1000, keylength=24, hashobj=hashlib.sha1):
	output_hash = hashobj(password + salt).digest()

	#Check if keylength is too big for hash function
	if len(output_hash) < keylength:
		raise Exception("Invalid length {} for hash function".format(keylength))

	#Do Loop for itterations
	for idx in range(itterations):
		output_hash = hashobj(output_hash).digest()

	#Return the hash with the correct size
	return output_hash[:keylength]


if __name__ == '__main__':
	print(pbkdf1(b'password', b'salt', 1, 20, hashlib.sha1).hex())
	#47e97e39e2b32b15eb9278e53f7bfca57f8e6b2c