Skip to main content

Quatum Safe

I heard Shor's algorithm can do all sorts of nasty things to RSA, so I've decided to be super modern and protect my flag with cool new maffs!

source.sage
from random import randint
from file import flag,r

pubkey = Matrix(ZZ, [
[47, -77, -85],
[-49, 78, 50],
[57, -78, 99]
])

for c in flag:
v = vector([ord(c), r1:=randint(0, 100), r2:=randint(0, 100)]) * pubkey + r
print(v)
enc.txt
(-981, 1395, -1668)
(6934, -10059, 4270)
(3871, -5475, 3976)
(4462, -7368, -8954)
(2794, -4413, -3461)
(5175, -7518, 3201)
(3102, -5051, -5457)
(7255, -10884, -266)
(5694, -8016, 6237)
(4160, -6038, 2582)
(4940, -7069, 3770)
(3185, -5158, -4939)
(7669, -11686, -2231)
(5601, -9013, -7971)
(5600, -8355, 575)
(1739, -2838, -3037)
(2572, -4120, -3788)
(8055, -11985, 1137)
(7088, -10247, 5141)
(8384, -12679, -1381)
(-785, 1095, -1841)
(4250, -6762, -5242)
(3716, -5364, 2126)
(5673, -7968, 6741)
(5877, -9190, -4803)
(5639, -8865, -5356)
(1980, -3230, -3366)
(6183, -9334, -1002)
(2575, -4068, -2828)
(7521, -11374, -1137)
(5639, -8551, -1501)
(4194, -6039, 3213)
(2072, -3025, 383)
(2444, -3699, -502)
(6313, -9653, -2447)
(4502, -7090, -4435)
(-421, 894, 2912)
(4667, -7142, -2266)
(4228, -6616, -3749)
(6258, -9719, -4407)
(6044, -9561, -6463)
(266, -423, -637)
(3849, -6223, -5988)
(5809, -9021, -4115)
(4794, -7128, 918)
(6340, -9442, 892)
(5322, -8614, -8334)

Solution

This WriteUp Solution is password protected by the flag of the challenge.

we know the format of the flag HTB{....} so we know 5 charcters of the flag.

To find flag we need vector r so we have to make equations like

pubkey[0][0]*ord('H') + pubkey[0][1]*r1 + pubkey[0][2]*r2 +rx = -981
pubkey[1][0]*ord('H') + pubkey[1][1]*r1 + pubkey[1][2]*r2 +ry = 6934
pubkey[2][0]*ord('H') + pubkey[2][1]*r1 + pubkey[2][2]*r2 +rz = 3871

since we know 5 chacters so there will be 5*3 equations and 13 variables (3 for r and 10 for flag) so we can easily find vector 'r'. Once we have vector 'r'

pubkey[0][0]*fi + pubkey[0][1]*r1 + pubkey[0][2]*r2 = -981-rx
pubkey[1][0]*fi + pubkey[1][1]*r1 + pubkey[1][2]*r2 = 6934-ry
pubkey[2][0]*fi + pubkey[2][1]*r1 + pubkey[2][2]*r2 = 3871-rz

we can easily find the fc(character corresponding to ith output). The complete solution for this challenge is following

solve.sage
pubkey = Matrix(ZZ, [
[47, -77, -85],
[-49, 78, 50],
[57, -78, 99]
])

cipher = [(-981, 1395, -1668),(6934, -10059, 4270),(3871, -5475, 3976),(4462, -7368, -8954),(2794, -4413, -3461),(5175, -7518, 3201),(3102, -5051, -5457),(7255, -10884, -266),(5694, -8016, 6237),(4160, -6038, 2582),(4940, -7069, 3770),(3185, -5158, -4939),(7669, -11686, -2231),(5601, -9013, -7971),(5600, -8355, 575),(1739, -2838, -3037),(2572, -4120, -3788),(8055, -11985, 1137),(7088, -10247, 5141),(8384, -12679, -1381),(-785, 1095, -1841),(4250, -6762, -5242),(3716, -5364, 2126),(5673, -7968, 6741),(5877, -9190, -4803),(5639, -8865, -5356),(1980, -3230, -3366),(6183, -9334, -1002),(2575, -4068, -2828),(7521, -11374, -1137),(5639, -8551, -1501),(4194, -6039, 3213),(2072, -3025, 383),(2444, -3699, -502),(6313, -9653, -2447),(4502, -7090, -4435),(-421, 894, 2912),(4667, -7142, -2266),(4228, -6616, -3749),(6258, -9719, -4407),(6044, -9561, -6463),(266, -423, -637),(3849, -6223, -5988),(5809, -9021, -4115),(4794, -7128, 918),(6340, -9442, 892),(5322, -8614, -8334)]

import numpy as np

A = np.array([[-49,57,0,0,0,0,0,0,0,0,1,0,0],
[78,-78,0,0,0,0,0,0,0,0,0,1,0],
[50,99,0,0,0,0,0,0,0,0,0,0,1],
[0,0,-49,57,0,0,0,0,0,0,1,0,0],
[0,0,78,-78,0,0,0,0,0,0,0,1,0],
[0,0,50,99,0,0,0,0,0,0,0,0,1],
[0,0,0,0,-49,57,0,0,0,0,1,0,0],
[0,0,0,0,78,-78,0,0,0,0,0,1,0],
[0,0,0,0,50,99,0,0,0,0,0,0,1],
[0,0,0,0,0,0,-49,57,0,0,1,0,0],
[0,0,0,0,0,0,78,-78,0,0,0,1,0],
[0,0,0,0,0,0,50,99,0,0,0,0,1],
[0,0,0,0,0,0,0,0,-49,57,1,0,0],
])

y = np.array([-981-47*ord('H') , 1395+77*ord('H') , -1668+85*ord('H') , 6934-47*ord('T') , -10059+77*ord('T') , 4270+85*ord('T') , 3871-47*ord('B') , -5475+77*ord('B') , 3976+85*ord('B') , 4462-47*ord('{') , -7368+77*ord('{') , -8954+85*ord('{') , 5322-47*ord('}')])

A_inv = np.linalg.pinv(A) # pseudo-inverse of A

x = np.dot(A_inv, y) # solve the linear system
# last 3 elements of x are the (rx, ry, rz)
r=vector([(x[-3]),(x[-2]),(x[-1])])
flag = "HTB{"
for i in range(4,len(cipher)):
B = np.array([[47,-49,57],
[-77,78,-78],
[-85,50,99]
])
z = np.array([cipher[i][0]-r[0],cipher[i][1]-r[1],cipher[i][2]-r[2]])
x=np.dot(np.linalg.pinv(B),z)
flag+=chr(int(x[0]))
print(flag)

After running the script we get the flag HTB{r3duc1nG_tH3_l4tTicE_l1kE_n0b0dY's_pr0bl3M}