Essentially a scripting challenge. You'll be given all sorts of parameters and need to calculate the missing one. Instead of going through every possible solution, which would've been really excruciating, I went through this approach -
Create a function that solves for a value.
The function's logic is as follows:
if we want a value that's already defined, just return it
if we want n, call ourself to solve p and q, then multiply
if we want ct, call ourself to solve n, then do pt^e mod n
if we want pt, call ourself to solve d and n, then do ct^d mod n
if we want d, call ourself to solve p and q,compute phi, then return inverse(e,phi)
if we want p, or q, then:
pretend p is the prime we have and q is the prime we want
if we have n, return n // p
if we have phi, return (phi // (p - 1)) + 1
if all else fails and we have e and d, use Crypto.PublicKey.RSA to compute p and q via n, e and d
import socket
from Crypto.Util.number import inverse, GCD
from Crypto.PublicKey import RSA
IP = '95.216.233.106'
PORT = 62467
def dosolve(val):
global cur
if val in cur.keys():
return cur[val]
if val == 'q' or val == 'p':
# Prime solving
# Pretend the prime we want is q and the prime we have is p every time for simplicity.
if 'q' in cur.keys():
cur['p'] = cur['q']
if 'n' in cur.keys():
return cur['n'] // cur['p']
elif 'phi' in cur.keys():
return (cur['phi'] // (cur['p'] - 1)) + 1
elif 'e' in cur.keys() and 'd' in cur.keys():
key = RSA.construct((cur['n'],cur['e'],cur['d']))
primes = [key.p,key.q]
primes.remove(cur['p'])
return primes[0]
elif val == 'd':
cur['p'] = dosolve('p')
cur['q'] = dosolve('q')
phi = (cur['p'] - 1) * (cur['q'] - 1)
d = inverse(cur['e'],phi)
return d
elif val == 'n':
cur['p'] = dosolve('p')
cur['q'] = dosolve('q')
return cur['p'] * cur['q']
elif val == 'ct':
cur['n'] = dosolve('n')
return pow(cur['pt'],cur['e'],cur['n'])
elif val == 'pt':
cur['d'] = dosolve('d')
cur['n'] = dosolve('n')
return pow(cur['ct'],cur['d'],cur['n'])
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.connect((IP, PORT))
s.setblocking(0)
buffer = b''
cur = {}
while True:
# Read until a prompt or line break
try:
chunk = s.recv(4096)
buffer += chunk
print(chunk.decode(), end='')
except BlockingIOError:
pass
if b'\n' not in buffer and not buffer.endswith(b': '):
continue
# Grab the oldest line
buffer = buffer.split(b'\n', 1)
if len(buffer) == 1:
line, buffer = buffer[0], b''
else:
line, buffer = buffer
# Llines start with [<code>]
if line[:1] != b'[':
continue
# Use slicing not indexing because indexing bytes returns ints
mode = line[1:2]
if mode == b'*':
...
elif mode == b'c':
cur = {}
elif mode == b':':
important = line[3:].decode().split(": ")
value = int(important[1])
cur[important[0].strip()] = value
elif mode == b'!':
print(line)
elif mode == b'?':
needed = line[3:].decode().split(": ")[0].strip()
if needed in cur.keys():
s.send(str(cur[needed]).encode() + b'\n')
continue
val = dosolve(needed)
print(val)
print(cur)
s.send(str(val).encode() + b'\n')
else:
...