Hey you!
Come over and help me, please. We discovered a strange key agreement protocol
used on this server: ctf.fluxfingers.net:1330. They send a curve which they
use later. But we think the robots are a bit UBER-cautious and do not use the
curve’s P. So they first exchange their public point with a technique we could
not figure out. It looks like they do not need a public key for this step.
Afterwards they use another technique to agree on a key which they ultimately
use to send some encrypted password.
We need this last
password to shut down the robo-factory on our way to the Oktoberfest.
Oh btw, the robots
use AES-ECB for symmetric encryption.
Hint: He, we have
the latest news for you. The first part of their strange key agreement was
designed by the famous SHA-Robot Мир!
First we started to find out what happens when you connect to the service. So
we found out ECKA stands for Elliptic Curve Key Agreement and learned all
translations for Мир.
After googeling “sha mir” (“mir” is the transcription for “Мир”) we obviously
realized, that the first part of the key agreement could be Shamir’s
three-pass-protocol. For the second part we guessed a Diffie-Hellman key
exchange.
Shamir’s three-pass-protocol with elliptic curves
- Alice and Bob generate a secret and its inverse
- Alice selects a point
- Alice encrypts with her secret:
- Bob encrypts with his secret:
- Alice decrypts with the known inverse
- Bob decrypts with the known inverse
- knows now
Diffie-Hellmann with elliptic curves
- Alice and Bob generate both a secret
- Alice sends to Bob
- Bob sends to Alice
- Both know the secret
The easiest way to implement this key exchange is, by using as a secret
each round.
So the following script decrypts the flag b3nDer_<3_3PDHKE
with about a 50/50 chance.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
| #!/usr/bin/env python
from sock import Sock
from Crypto.Cipher import AES
s = Sock("ctf.fluxfingers.net", 1330)
# ignore first line
s.read_until("\n")
# get a * P
aP = s.read_until("\n")
# send 1 * a * P == a * P
s.send(aP)
# get 1*P = P
P = s.read_until("\n")
# get b * P
bP = s.read_until("\n")
# send P
s.send(P)
# get cypher
cypher = s.read_until("\n")
# decrypt the cypher using b * P as the key
key = ("%064x" % int(bP[1:-2].split(" : ")[0])).decode("hex")
crypt = AES.new(key, AES.MODE_ECB)
flag = crypt.decrypt(cypher.strip().decode("base64")[:-1])
print flag
|