This my hash function,it has the following property:
Padding Data:
Before processing, the data is padded to ensure it’s a multiple of the block size (512 bits in this case). Padding involves appending zeros (x00) to the data. The data is converted to bytes if it’s a string.
Initialization:
An Initialization Vector (IV) is set as 256 bits of zeroes (b’x00′ * 32). This IV will be updated as the hash calculation progresses.
Hash Calculation:
The padded data is divided into segments of size 512 bits. Then, each segment undergoes the following steps:
1.Compress the segment using zlib.
2.Generate HMAC of the compressed segment.
3.The resulting HMAC is split into 64-bit words.
4.Each word is added to the corresponding word in the IV modulo 2^64
5.The updated IV is then used as the key for the next segment.
Finalization:
After processing all segments, the final IV is returned as the hash value in hexadecimal format.
*Reading the code would make it pretty understandable
*
def calculate_hash(self, symmetric_key):
“””
Calculate hash of the data using custom hash function.
“””
def generate_hmac(data,key):
“””
Generate HMAC (Data Authentication Code) using a symmetric key.
“””
h = hmac.HMAC(key, hashes.SHA256(), backend=default_backend())
if isinstance(data, str):
h.update(data.encode(‘utf-8’))
elif isinstance(data, bytes):
h.update(data)
else:
raise TypeError(“Data must be either a string or bytes”)
hmac_code = h.finalize()
return hmac_code
def compress_data(data):
"""
Compress data using zlib.
"""
if isinstance(data, str):
compressed_data = zlib.compress(data.encode('utf-8'))
elif isinstance(data, bytes):
compressed_data = zlib.compress(data)
else:
raise TypeError("Data must be either a string or bytes")
return compressed_data
# Define IV as 256 bits of zeroes
IV = b'x00' * 32
# Padding original message to 512-bit blocks
block_size = 512
if isinstance(self.data, str):
padded_data = self.data.encode() + b'x00' * ((block_size - len(self.data.encode()) % block_size) % block_size)
elif isinstance(self.data, bytes):
padded_data = self.data + b'x00' * ((block_size - len(self.data) % block_size) % block_size)
else:
raise TypeError("Data must be either a string or bytes")
# Calculate number of segments
num_segments = len(padded_data) // block_size
# Initialize HMAC key
key = symmetric_key
# Iterate through segments
for i in range(num_segments):
# Extract current segment
segment = padded_data[i * block_size: (i + 1) * block_size]
# Compress the segment
compressed_segment = compress_data(segment)
# Generate HMAC of the compressed segment
hmac_value = generate_hmac(compressed_segment, key)
# Append HMAC to IV, word to word addition modulo 2^64
for j in range(0, len(hmac_value), 8):
word = hmac_value[j:j+8]
IV_word = IV[j:j+8]
IV_word = int.from_bytes(IV_word, 'big')
word = int.from_bytes(word, 'big')
new_word = (IV_word + word) % (2**64)
IV = IV[:j] + new_word.to_bytes(8, 'big') + IV[j+8:]
# Set current HMAC as key for next segment
key = IV
# Return the final hash value (Hn)
return IV.hex()
This is my attack function:
def extend_hash(original_hash,block_size,additional_data):
# Retrieve last HMAC value from the original hash
last_hmac = bytes.fromhex(original_hash)[-32:]
# Create a padding to align the additional data to a block boundary
pad_length = block_size - (len(additional_data) % block_size)
padding = b'x00' * pad_length
# Append the padding and additional data
modified_data = additional_data + padding
# Calculate the new HMAC for the modified data
h = hmac.HMAC(last_hmac, hashes.SHA256())
h.update(modified_data)
new_hmac = h.finalize()
# Retrieve original IV
original_iv = bytes.fromhex(original_hash[:-64])
# Split the original IV into 64-bit words
original_iv_words = [int.from_bytes(original_iv[i:i+8], 'big') for i in range(0, len(original_iv), 8)]
# Split the new HMAC into 64-bit words
new_hmac_words = [int.from_bytes(new_hmac[i:i+8], 'big') for i in range(0, len(new_hmac), 8)]
# Add each word of new HMAC to the corresponding word in the IV modulo 2^64
new_iv_words = [(original_iv_words[i] + new_hmac_words[i]) % (1 << 64) for i in range(len(original_iv_words))]
# Construct the new IV by converting words back to bytes
new_iv = b''
for word in new_iv_words:
new_iv += word.to_bytes(8, 'big')
# Append the last 32 bytes of new HMAC to the new IV
new_iv += new_hmac
# Return the new hash value
return new_iv.hex()
But this wont help me attack the integrity of my hash function compromising its second preimage property.
I have various approaches to my attack but they don’t seem to do anything.
PYTWOLF is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.