3

I'm trying to find a MD5 hash collision between 2 numbers such that one is prime and the other is composite (at most 1024-bit). I'm using fastcoll with random prefixes for each iteration.

For this I wrote this script:

import subprocess
from Crypto.Util.number import bytes_to_long, isPrime
import string
import random

won = False

N = 10

while not won: # Run the fastcoll executable to generate the two messages pfx = ''.join(random.choices(string.ascii_uppercase + string.digits, k=N)) file = open("prefix", "w") file.write(pfx) file.close()

subprocess.run(["./fastcoll_v1.0.0.5.exe", "-p", "prefix", "-o", "msg1.bin", "msg2.bin"])

# Convert the messages to integers
with open("msg1.bin", "rb") as f:
    msg1_int = bytes_to_long(f.read())
if(msg1_int.bit_length() > 1024):
    continue
with open("msg2.bin", "rb") as f:
    msg2_int = bytes_to_long(f.read())
if(msg2_int.bit_length() > 1024):
    continue

print(msg1_int)
print(isPrime(msg1_int))
print(msg2_int)
print(isPrime(msg2_int))

# Check if one message is prime and the other is composite
if isPrime(msg1_int) and not isPrime(msg2_int):
    won = True
elif isPrime(msg2_int) and not isPrime(msg1_int):
    won = True

However, I'm not sure this is the most efficient way so can someone suggest improvements? Any help would be appreciated.

1 Answers1

3

Using the length extension attack of MD5 as I discussed in the comments, I was able to achieve this.

Here's the script I used:

from Crypto.Util.number import isPrime, bytes_to_long, long_to_bytes
import hashlib

x = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa200a8284bf36e8e4b55b35f427593d849676da0d1555d8360fb5f07fea2" y = "4dc968ff0ee35c209572d4777b721587d36fa7b21bdc56b74a3dc0783e7b9518afbfa202a8284bf36e8e4b55b35f427593d849676da0d1d55d8360fb5f07fea2"

print("x : ", bytes_to_long(bytes.fromhex(x)))

print("md5(x) : ", hashlib.md5(bytes.fromhex(x)).hexdigest()) print("md5(y) : ", hashlib.md5(bytes.fromhex(y)).hexdigest())

z = 1

xx = 0 yy = 0

while True: # append 1s till prime xx = bytes_to_long(bytes.fromhex(x) + long_to_bytes(z)) yy = bytes_to_long(bytes.fromhex(y) + long_to_bytes(z)) if isPrime(xx) and not isPrime(yy): break z += 2

print("x+z :", xx) print("y+z :", yy)

print("md5(x+z) : ", hashlib.md5(long_to_bytes(xx)).hexdigest()) print("md5(y+z) : ", hashlib.md5(long_to_bytes(yy)).hexdigest())