Files
ctf/2026/cscg/crypto/zipper/challenge.py
2026-04-10 03:31:12 +02:00

91 lines
2.3 KiB
Python

from sage.all import *
from Crypto.Util.number import long_to_bytes
from Crypto.Util.Padding import pad
import gzip, base64, os, string, random
FLAG = os.getenv("FLAG", "dach2026{fake_flag}")
REQUIRED_WINS = 25
p = 0x1337
Fp = GF(p)
I = matrix.random(Fp, 4)
def hash(message: bytes):
m = pad(message, 25)
assert len(m) % 25 == 0
sections = []
for i in range(0, len(m), 25):
block = int(m[i:i+25].hex(), 16)
digits = []
for _ in range(16):
digits.append(block % p)
block //= p
sections.append(matrix(Fp, [digits[:4], digits[4:8], digits[8:12], digits[12:]]))
A = I
for S in sections:
A *= S
hashsum = 0
for el in sum([list(r) for r in A.rows()], [])[::-1]:
hashsum *= p
hashsum += int(el)
return long_to_bytes(hashsum, 25)
def random_hash():
return hash(os.urandom(25))
def random_message(n):
return "".join([random.choice(string.ascii_letters) for _ in range(n)])
def main():
print("Welcome to ZIPPER!")
wins = 0
while True:
target_message = random_message(32)
target_hash = random_hash() # Make this game impossible ( ͡° ͜ʖ ͡°)
print(f"I am thinking of a gzip file that decompresses to '{target_message}' and has a hash of '{target_hash.hex()}'.")
print("What file am I thinking of?")
user_input = input("> ")
try:
file = base64.b64decode(user_input)
file_hash = hash(file)
if len(file) == 0:
continue
if file_hash != target_hash:
wins = 0
print(f"Wrong hash: {file_hash.hex()} != {target_hash.hex()}.")
continue
if gzip.decompress(file).decode() != target_message:
wins = 0
print("Wrong data!")
continue
wins += 1
print(f"CORRECT! You have {REQUIRED_WINS-wins} wins more to go to get a prize!")
if wins >= REQUIRED_WINS:
print("Congratulations, you've outguessed me!")
print("\n" + FLAG + "\n")
wins = 0
except KeyboardInterrupt:
exit(0)
except:
print("Wrong **insert whatever here**!")
wins = 0
if __name__ == "__main__":
main()