Tags: math rsa 

Rating:

# Awesome Mix 1 (Crypto)

In the task we get the source code:

```python
#!/usr/bin/python -u

from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as RSAsign
from Crypto.Hash import SHA
from Util import PKCS1_pad as pad
from SECRET import flag
import sys

def verify(s,m,n,e):
if pow(s,e,n) == pad(m):
return True
else:
return False

key = RSA.generate(1024)

message = "super important information for admin only"

h = SHA.new(message)

signer = RSAsign.new(key)

signature = signer.sign(h)
s = int(signature.encode("hex"),16)

print "Welcome to admin's music portal.\nTo verify that you are the owner of this service\nsend the public key which will verify the following signature :\n"

print "Message ->", message
print
print "Signature ->", signature.encode("hex")
print

sys.stdout.flush()

n = long(raw_input("Enter n:"))
e = long(raw_input("Enter e:"))
sys.stdout.flush()
input_key = RSA.construct((n,e))

if verify(s,h.hexdigest(),n,e):
print flag
else:
print "Music is only for admin's eyes."

sys.stdout.flush()
```

So the server generates a random RSA key, signs a certain message with it and asks us for a public key matching the signature.
The mistake here is that there are no restrictions on the values for the public key.

What we get is:

`signature == message^d mod n`

And we want now values `(e,n)` for which holds:

`signature^e mod n == message`

If we take `e=1` then this equation becomes simply:

`signature mod n == message`

We can select any `n` we want, so we can choose the trivial case where `signature` is larger from `n` exactly by `message`, so that modulo operation will cut `signature` by `n`.

If now:

`n = signature-message`

then

`signature mod (signature-message) = message`

We used for that code:

```python
import re
from Crypto.Hash import SHA
from crypto_commons.netcat.netcat_commons import nc, send, interactive

def PKCS1_pad(data):
asn1 = "003021300906052b0e03021a05000414"
ans = asn1 + data
n = len(ans)
padding = '0001' + 'f' * (1024 / 4 - n - 4)
return int((padding + ans), 16)

def main():
port = 8082
host = "51.15.73.163"
s = nc(host, port)
data = s.recv(99999)
print(data)
sig = re.findall("Signature ->(.*)", data)[0]
signature = int(sig.strip(), 16)
message = "super important information for admin only"

h = SHA.new(message)
m = PKCS1_pad(h.hexdigest())
e = 1
n = signature ** e - m
print('n', n)
print('e', e)
send(s, str(n))
send(s, str(e))
interactive(s)

main()
```

And got `CTF{cryp70_5ur3_15_w13rd}`

Original writeup (https://github.com/p4-team/ctf/tree/master/2018-03-18-backdoor-ctf/crypto_mix1).