import subprocess, sys, random, os, struct MASK32 = 2**32 - 1 def format_bytes(data): return ''.join('\\x%02x' % byte for byte in data) def lcg_urandom(x0): size = struct.calcsize('LL') x = x0 nonce = [] for index in range(size): x *= 214013 x += 2531011 x &= MASK32 byte = (x >> 16) & 0xff nonce.append(byte) return bytes(nonce) if struct.calcsize('L') == 4: # 32 bits MASK = 2**32-1 else: # 64 bits MASK = 2**64-1 format_hash = "%0" + str(struct.calcsize('L') * 2) + 'x' format_item = "% 5i: " + format_hash + ", " + format_hash def generate_seed_0xCD(): if sys.byteorder == 'little': offset = struct.calcsize('L') - 1 else: # big endian offset = 0 for tries in range(10**5): seed = random.randint(0, MAXSEED) prefix_suffix = lcg_urandom(seed) if prefix_suffix[offset] == 0xCD: return seed else: print("Fail to generate a new seed!") print("# seeds =", len(seeds)) sys.exit(1) hashes = {} seeds = set() secrets = {} MAXSEED = 2**32 - 1 code = r"print(hash(b'\x27\xfd\x5a\x18')); print(hash(b'\x26\xfe\x78\xfa'))" devnull = open(os.devnull, 'wb') while True: for tries in range(1000): #seed = random.randint(0, 4096) seed = random.randint(0, MAXSEED) #seed = random.randint(0, 10) #seed = generate_seed_0xCD() if seed in seeds: continue secret = lcg_urandom(seed) if secret in secrets: continue print("Secret collision!") print("Seed 1=", seed) print("Seed 2=", secrets[secret]) print("Seecret=", format_bytes(secret)) print() else: secrets[secret] = seed break else: print("Fail to generate a new seed!") print("# seeds =", len(seeds)) sys.exit(1) seeds.add(seed) env = os.environ.copy() env['PYTHONHASHSEED'] = str(seed) process = subprocess.Popen( [sys.executable, '-S', '-c', code], env=env, stdout=subprocess.PIPE, stderr=devnull) stdout, stderr = process.communicate() a, b = stdout.rstrip().split(b'\n') a = int(a.rstrip()) & MASK b = int(b) & MASK key = (a, b) if key in hashes: seed2 = hashes[key] print("COLLISION!") print("seed 1", seed) print("seed 2", seed2) print("secret 1", format_bytes(lcg_urandom(seed))) print("secret 2", format_bytes(lcg_urandom(seed2))) print("Hashes=", format_hash % a, format_hash % b) sys.exit(1) hashes[key] = seed #print(format_item % (len(hashes), a, b)) print("% 5i: %s" % (len(hashes), format_bytes(secret)))