Tags: crypto 

Rating:

# Cry - Morphing Time

Elgamal encryption & decryption

``` python
def encrypt_setup(p, g, A):
def encrypt(m):
k = randint(2, p - 1)
c1 = pow(g, k, p)
c2 = pow(A, k, p)
c2 = (m * c2) % p

return c1, c2

return encrypt

def decrypt_setup(a, p):
def decrypt(c1, c2):
m = pow(c1, a, p)
m = pow(m, -1, p)
m = (c2 * m) % p

return m

return decrypt
```

Oracle

```python
m = decrypt((c1 * c1_) % p, (c2 * c2_) % p)
```

looking at how the encryption works

c1 = g^k mod p
c2 = g^ak * m mod p

during the decryption process

c1 --> g^-ak

so when c1 * c2 mod p will return m because c1 is modular inverse of c2/m (c2 before multiplied by m)

so the oracle formula become

(g^k * c1_)^-a * g^ak * m * c2_ mod p = m

g^-ak * c1^-a * g^ak * m * c2_ mod p = m

now our goal is to find c1_ and c2_ value so that it will cancel each other (modular inverse)

we know p, g, A where A is g^a mod p, based on this value we can solve the equation with A

we have to make c1_^-a --> g^-a and c2_ --> A (g^a mod p) those value will cancel each other so the final equation is

g^-ak * g^-a * g^ak * g^a * m mod p = m

c1_^-a = g^-a so c1_ = g = 2, c2_ = A = g^a mod p

we get the msg

```
>>> long_to_bytes(4207564671745017061459002831657829961985417520046041547841180336049591837607722234018405874709347956760957)
b'uiuctf{h0m0m0rpi5sms_ar3_v3ry_fun!!11!!11!!}'
```

Original writeup (https://github.com/UnoArroefy/CTF-Writeups/tree/main/uiuctf-2023/Morphing-time).