Rating:

### Now We Can Play!! - 200 points (34 solves)

> It is just a simple cryptography game. When you get a flag, YOU WIN!!
>
> nc problem.harekaze.com 30002

The challenge presents us the following code:

```python
#!/usr/bin/python3
from Crypto.Util.number import *
from Crypto.Random.random import randint
from keys import flag

def genKey(k):
p = getStrongPrime(k)
g = 2
x = randint(2, p)
h = pow(g, x, p)

return (p, g, h), x

def encrypt(m, pk):
p, g, h = pk
r = randint(2, p)

c1 = pow(g, r, p)
c2 = m * pow(h, r, p) % p
return c1, c2

def decrypt(c1, c2, pk, sk):
p = pk[0]
m = pow(3, randint(2**16, 2**17), p) * c2 * inverse(pow(c1, sk, p), p) % p
return m

def challenge():
pk, sk = genKey(1024)
m = bytes_to_long(flag)
c1, c2 = encrypt(m, pk)

print("Public Key :", pk)
print("Cipher text :", (c1, c2))

while True:
print("---"*10, "\n")
in_c1 = int(input("Input your ciphertext c1 : "))
in_c2 = int(input("Input your ciphertext c2 : "))

dec = decrypt(in_c1, in_c2, pk, sk)
print("Your Decrypted Message :", dec)

if __name__ == "__main__":
challenge()
```

The `challenge` function is straightforward. Some keys are generated, the flag is encrypted and the `while` loop is just a decryption oracle.

The cryptosystem used here is Elgamal and we are given the public key `(p,g,h)` and the ciphertext `(c1, c2)`. The decryption oracle has a twist and it does not decipher the flag completely as we would expect.

In the Elgamal cryptosystem, the message is given by:

![equation 1](https://github.com/diogoaj/ctf-writeups/blob/master/2019/HarekazeCTF/crypto/now_we_can_play/resources/equation1.png)

Where c1 and c2 are given by:

![equation 2](https://github.com/diogoaj/ctf-writeups/blob/master/2019/HarekazeCTF/crypto/now_we_can_play/resources/equation2.png)

![equation 3](https://github.com/diogoaj/ctf-writeups/blob/master/2019/HarekazeCTF/crypto/now_we_can_play/resources/equation3.png)

Normally, the first equation should give us the plaintext but that is not the case here. Here is the line of code that matters:

```python
m = pow(3, randint(2**16, 2**17), p) * c2 * inverse(pow(c1, sk, p), p) % p
```

With this information, the decryption equation is something like:

![equation 4](https://github.com/diogoaj/ctf-writeups/blob/master/2019/HarekazeCTF/crypto/now_we_can_play/resources/equation4.png)

There is an extra factor here that prevents us to read the flag directly. To get the original message, we need the multiplicative inverse of `3^r` to cancel out that factor. If we look closely at how this number is generated, we see that the random number chosen `r` is very small and so, this allows us to brute-force this value and calculate all inverses between `3^(2^16)` and `3^(2^17)`. Then, multiply each one by `m'` until we see the flag.

Here is the code that solves the problem:

```python
from pwn import *
import gmpy2

r = remote("problem.harekaze.com", 30002)

pk = r.recvuntil("))")
c = r.recvuntil("))")

r.recvuntil(":")

p = long(pk.split(",")[1].replace(" (", ""))

c1 = c.split(",")[1].replace(" (", "")
c2 = c.split(",")[2].replace(" ", "").replace("))", "")

l = []

for i in range(2**16, 2**17):
l.append(gmpy2.invert(pow(3,i,p), p))

r.sendline(c1)
r.sendline(c2)

dec = r.recvuntil(")")

dec = dec.split(",")[1].replace(" ", "").replace(")", "")

dec = long(dec)

for num in l:
m = (dec * num) % p
try:
m = hex(m)[2:].decode("hex")
if "Harekaze" in m:
print m
break
except:
pass
```

And here is the flag;

```
HarekazeCTF{im_caught_in_a_dr3am_and_m7_dr3ams_c0m3_tru3}
```

Original writeup (https://github.com/diogoaj/ctf-writeups/tree/master/2019/HarekazeCTF/crypto/now_we_can_play).