DESCRIPTION: Qubit Enterprises is a new company touting it's propriety method of qubit stabilization.They expect to be able to build a quantum computer that can factor a RSA-1024 number in the next 10 years.As a promotion they are giving out "time capsules" which contain a message for the future encrypted by 1024 bit RSA.They might be great engineers, but they certainly aren't cryptographers, can you find a way to read themessage without having to wait for their futuristic machine?
https://app.hackthebox.com/challenges/365
Baby Time Capsule is cryptography challenge. we are given with python source code server.py file.
Click to see source code :diamond_shape_with_a_dot_inside:
from Crypto.Util.number import bytes_to_long, getPrime
import socketserver
import json
FLAG = b'HTB{--REDACTED--}'
class TimeCapsule():
def __init__(self, msg):
self.msg = msg
self.bit_size = 1024
self.e = 5
def _get_new_pubkey(self):
while True:
p = getPrime(self.bit_size // 2)
q = getPrime(self.bit_size // 2)
n = p * q
phi = (p - 1) * (q - 1)
try:
pow(self.e, -1, phi)
break
except ValueError:
pass
return n, self.e
def get_new_time_capsule(self):
n, e = self._get_new_pubkey()
m = bytes_to_long(self.msg)
m = pow(m, e, n)
return {"time_capsule": f"{m:X}", "pubkey": [f"{n:X}", f"{e:X}"]}
def challenge(req):
time_capsule = TimeCapsule(FLAG)
while True:
try:
req.sendall(
b'Welcome to Qubit Enterprises. Would you like your own time capsule? (Y/n) '
)
msg = req.recv(4096).decode().strip().upper()
if msg == 'Y' or msg == 'YES':
capsule = time_capsule.get_new_time_capsule()
req.sendall(json.dumps(capsule).encode() + b'\n')
elif msg == 'N' or msg == "NO":
req.sendall(b'Thank you, take care\n')
break
else:
req.sendall(b'I\'m sorry I don\'t understand\n')
except:
# Socket closed, bail
return
class MyTCPRequestHandler(socketserver.BaseRequestHandler):
def handle(self):
req = self.request
challenge(req)
class ThreadingTCPServer(socketserver.ThreadingMixIn, socketserver.TCPServer):
pass
def main():
socketserver.TCPServer.allow_reuse_address = True
server = ThreadingTCPServer(("0.0.0.0", 1337), MyTCPRequestHandler)
server.serve_forever()
if __name__ == '__main__':
main()
To solve this we need knowledge of the Chinese remainder theorem.
m=message, e=5, n=public key, c=cipher text
me mod n = c
let's take x = me
x mod n = c
here x module n is remainder c, so we can say that x anc c are congruent modulo.
x ≡ c (mod n)
Here server encrypt same message with different public keys.
x ≡ c1 (mod n1)
x ≡ c2 (mod n2)
x ≡ c3 (mod n3)
The Chinese Remainder Theorem (CRT) is used to solve a set of different congruent equations with one variable but different moduli which are relatively prime.
To find x:
x = (c1 × N1 × N1-1 + c2 × N2 × N2-1 + c3 × N3 × N3-1) mod N
here, N = n1 × n2 × n3
N1 = N / n1
N2 = N / n2
N3 = N / n3
N1 × N1-1 = 1 mod n1
N2 × N2-1 = 1 mod n2
N3 × N3-1 = 1 mod n3
we can use extended euclidean algorithm to find N1-1.
I used python library to perform CRT.
Python code:
Click to see python code :diamond_shape_with_a_dot_inside:
import json
from Crypto.Util.number import long_to_bytes
from pwn import *
from sympy.ntheory.modular import crt
from sympy.simplify.simplify import nthroot
conn = remote('209.97.185.157', 32141)
rem = list()
num = list()
for i in range(3):
conn.sendline(b'Y')
a = conn.recvline()
r = json.loads(a[74:-1].decode())
m = r['time_capsule']
n = r['pubkey'][0]
e = 5
m = int(m, 16)
n = int(n, 16)
rem.append(m)
num.append(n)
x = crt(num, rem, check=True)
# print(f'x = {x[0]}')
flag = nthroot(x[0], 5)
print(flag)
print(long_to_bytes(flag))
conn.sendline(b'N')
conn.recvline()
conn.close()
Click to see output :diamond_shape_with_a_dot_inside:
[x] Opening connection to 209.97.185.157 on port 32141
[x] Opening connection to 209.97.185.157 on port 32141: Trying 209.97.185.157
[+] Opening connection to 209.97.185.157 on port 32141: Done
3133512701921564926666059129802238375015291423590355094862405004229914481893581069974415008616334994674940586670768933862016098685
b'HTB{t3h_FuTUr3_15_bR1ghT_1_H0p3_y0uR3_W34r1nG_5h4d35!}'
[*] Closed connection to 209.97.185.157 port 32141
Process finished with exit code 0