#!/usr/bin/env python3from Crypto.Util.number import*from Crypto.Cipher import AESfrom Crypto.Util.Padding import padfrom Crypto.Hash import SHA256import osbits =256bs = AES.block_sizeFLAG =open('flag.txt').read()menu ="""+-------------------------+| || M E N U | | || [1] DH Parameters || [2] View PublicKeys || [3] Encrypt Flag || [4] Generate PublicKey || |+-------------------------+"""defencrypt(m,key): key = SHA256.new(str(key).encode()).digest()[:bs] iv = os.urandom(bs) cipher = AES.new(key, AES.MODE_CBC, iv) enc = cipher.encrypt(pad(m.encode(), 16))return (enc.hex(), iv.hex())defgen_pubkey(g,p,privkey): l = privkey.bit_length() m =int(input("Enter some random integer > ")) new_privkey = privkey ^ m new_pubkey =pow(g, new_privkey, p)return new_pubkeyif__name__=='__main__': g =2 p =getPrime(bits)# Rick Astley a =getRandomRange(1, p-1) R =pow(g,a,p)# Kermit the Frog b =getRandomRange(1, p-1) K =pow(g,b,p) s =pow(R,b,p) enc_flag, iv =encrypt(FLAG, s)# testwithopen('priv.txt','w')as f: f.write('a='+str(a)+'\n') f.write('b='+str(b))print(menu) l = p.bit_length()+4try:for _ inrange(l): ch =input("Choice ? ").strip().lower()if ch =='1':print("[DH parameters]")print(f"{g = }")print(f"{p = }\n")elif ch =='2':print("[Rick's PublicKey]")print(f"{R = }\n")print("[Kermit's PublicKey]")print(f"{K = }\n")elif ch =='3':print("[ENC FLAG]")print(f"{enc_flag = }\n")print("[IV]")print(f"{iv = }\n")elif ch =='4': npk =gen_pubkey(g, p, b)print("[Kermit's New PublicKey]")print(f"{npk = }\n")else:print(f":( Invalid Choice !!!")breakexceptExceptionas e:print(e)exit()
After connecting to the server, we can see that the server runs a Diffie Hellman Oracle which provides 4 options. It's generic DH and the 4thoption is for generating a new public key by XORing the original secret key with any value we provide. As we can control this value (let's say mask), we can leak the bits of the secret key!
If we select the mask as the power of2, then we can check the following properties (basically the properties of XOR) for any integer.
b⊕20={b+20,b−20,if 1st bit was 0if 1st bit was 1b⊕21={b+21,b−21,if 2nd bit was 0if 2nd bit was 1b⊕22={b+22,b−22,if 3rd bit was 0if 3rd bit was 1
Now we can jump back to the challenge and use this knowledge to leak the private key(b). Let's see what happens actually when we send20as the mask.
npk≡gb⊕2n≡{gb+2n≡gb∗g2n≡K∗g2n,gb−2n≡gb∗g−2n≡K∗g−2n,if nth bit was 0if nth bit was 1(modp)
As we have K,gandp we can calculate g−2n(modp)and check if
With this knowledge, we can easily leak the individual/multiple bits of the secret_key (b) and then calculate s≡Rb≡gab(modp) and use it as the AES key to decrypt the FLAG.