import randomimport timeimport datetime import base64from Crypto.Cipher import AESflag =b"find_me"iv =b"\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"for i inrange(0, 16-(len(flag) %16)): flag +=b"\0"ts = time.time()print("Flag Encrypted on %s"% datetime.datetime.fromtimestamp(ts).strftime('%Y-%m-%d %H:%M'))seed =round(ts*1000)random.seed(seed)key = []for i inrange(0,16): key.append(random.randint(0,255))key =bytearray(key)cipher = AES.new(key, AES.MODE_CBC, iv)ciphertext = cipher.encrypt(flag)print(base64.b64encode(ciphertext).decode('utf-8'))
Solution
So we just need to bruteforce the seed to get valid key then decrypt the ciphertext. Time used as seed was 2023-08-02 10:27 (author local time). Based on time used in ctf (platform) we get the timezone then convert that local time to unix timestamp. Here is script i used to get the flag
import numpy as npimport randomfrom base64 import b64encode, b64decodefrom Crypto.Cipher import AESfrom Crypto.Util.Padding import pad...# computational basis statesone_state = np.array([[1.0],[0.0]])zero_state = np.array([[0.0],[1.0]])# Hadamard and X-pauli gatesH = np.array([[1.0,1.0],[1.0,-1.0]])/np.sqrt(2),X = np.array([[0.0,1.0],[1.0,0.0]])defget_quantum_key(state_list,basis_list): key_bits =''if(len(state_list)!=1024orlen(basis_list)!=1024):return-1for basis in basis_list:if(str.upper(basis)notin ['H','X']):return-1 our_basis = []for i inrange(0, 1024): our_basis.append(random.choice(["H", "X"]))for i inrange(0, 1024):if(our_basis[i]== basis_list[i]):if(basis_list[i]=="H"): state = np.dot(H, state_list[i])else: state = np.dot(X, state_list[i])if(state[0][0] >.99): key_bits +='1'else: key_bits +='0'if(len(key_bits)<128):return-1 key =bitstring_to_bytes(key_bits[0:128]) cipher = AES.new(key, AES.MODE_CBC) cipher_text = cipher.encrypt(pad(flag, AES.block_size)) iv = cipher.ivreturn{"basis": our_basis,"iv":b64encode(iv),"ciphertext":b64encode(cipher_text)}
Solution
So we need to send basis and state with length 1024. We can see that the key bits must greater or equal than 128. Since our input is 1024 so it has bigger chance to get valid basis with length greater or equal than 128. For the state we just need to send valid state that result 2 decimal points to make state[0][0] valid. Here is script i used to get the flag
import requestsimport randomfrom base64 import b64encode, b64decodefrom Crypto.Cipher import AESfrom Crypto.Util.Padding import padimport numpy as npimport jsondefbitstring_to_bytes(s): v =int(s, 2) b =bytearray()while v: b.append(v &0xff) v >>=8returnbytes(b[::-1])defget_quantum_key(state_list,basis_list,our_basis,iv,ct): iv =b64decode(iv) ct =b64decode(ct) key_bits =''if(len(state_list)!=1024orlen(basis_list)!=1024):return-1for basis in basis_list:if(str.upper(basis)notin ['H','X']):return-1for i inrange(0, 1024):if(our_basis[i]== basis_list[i]):if(basis_list[i]=="H"): state = np.dot(H, state_list[i])else: state = np.dot(X, state_list[i])if(state[0][0] >.99): key_bits +='1'else: key_bits +='0'if(len(key_bits)<128):return-1 key =bitstring_to_bytes(key_bits[0:128]) cipher = AES.new(key, AES.MODE_CBC, iv) pt = cipher.decrypt(ct)return ptH = np.array([[1.0,1.0],[1.0,-1.0]])/np.sqrt(2),X = np.array([[0.0,1.0],[1.0,0.0]])r = requests.session()url ="https://nessus-quantumcrypto.chals.io/quantum_key"basis = []for i inrange(1024): basis.append("H")state = []for i inrange(1024): state.append([1.1, 1.1])json_data ={"state_list": state,"basis_list": basis}resp = r.post(url, json = json_data)data = json.loads(resp.text)our_basis = data["basis"]iv = data["iv"]ct = data["ciphertext"]print(get_quantum_key(state, basis, our_basis, iv, ct))