Writeup for Crypto problems in WMCTF 2020
piece_of_cake 两个函数大概都是一个类似 RSA 的操作,加上一个加密算法,之前的一篇博客有介绍, An Introduction to Mathematical Cryptography 书里称这个算法是 “a toy model of a real public key cryptosystem”。(bitlength 凑的刚刚好可以保证解密,很巧妙) make_cake()这边的cake很小(256bits)符合正常解密的条件,可以直接用高斯格基规约算法,然而eat_cake()这边的cake是比较大的(768bits)就会导致在取模的时候值容易发生改变,所以给它加上几个g,并使用给出的pow来验证是否是正确的cake。 规约得到的密钥对 $(F, G)$ 是不一定等于原来的密钥对 $(f, g)$,但它们在解密过程是等价的,我们得到的密钥对 长度都是 768bits。 exp 多跑几次就能得到 flag。 from gmpy2 import iroot, sqrt, invert from pwn import remote from string import ascii_letters, digits from hashlib import sha256 r = remote('170.106.35.18', 8631) def proof_of_work(txt, Hash): for a in ascii_letters+digits: for b in ascii_letters+digits: for c in ascii_letters+digits: if sha256((a+b+c+txt).encode()).hexdigest() == Hash: return a+b+c def gaussian(v1, v2): while True: if sqrt(v2[0]**2 + v2[1]**2) < sqrt(v1[0]**2 + v1[1]**2): v1, v2 = v2, v1 m = int((v1[0]*v2[0] + v1[1]*v2[1]) / (v1[0]**2 + v1[1]**2)) if m == 0: return (v1, v2) v2 = [v2[0] - m * v1[0], v2[1] - m * v1[1]] r.recvuntil("XXX+") nonce = r.recv(17).decode() r.recvuntil(" == ") target = r.recv(64).decode() r.recvuntil("\nGive me XXX:") w = proof_of_work(nonce, target) r.send(str(w)+"\n") r.recvuntil("What's your choice?\n") r.send("1\n") r.recvline() temp = r.recvline().strip().decode().split(" ") q, h, c = [int(i) for i in temp] N = int(r.recvline().strip().decode()) cip = int(r.recvline().strip().decode()) s1, s2 = gaussian([1, h], [0, q]) f, g = s1[0], s1[1] cake = (c * f % q) % g cake = invert(f, g) * cake % g for k in range(10000): if pow(cake, 0x10001, N) == cip: print("cake is: ", cake) break cake += g r.send(str(cake) + "\n") print(r.recvline().strip().decode()) #WMCTF{Wh4t_A_pi3ce_of_CAKE!} babySum 密度接近 0.8 的子集和问题(Subset sum problem),BKZ-24 跑得比较慢好在成功率高一点。 ...