TCP1P-CTF 2023 - One Pad Time
Description
Category: Cryptography
Author:
Wrth
At the wrong place at the wrong time
Attachments:
Solution
1. Overview
The flag has been encrypted with AES-CBC and we have the ciphertext xored with the key and the IV.
1
2
3
4
5
pt = open("flag.txt", "rb").read()
ct = pad(cipher.encrypt(pt), 16)
ct = xor(ct, key)
print(f"{iv = }")
print(f"{ct = }")
The goal is to decrypt the ciphertext but we are missing the key.
2. Padding
We can see that the ciphertext is the encryption of the flag with padding:
1
ct = pad(cipher.encrypt(pt), 16)
However AES is a block cipher with a block size of 128 bits (16 bytes).
It means that it can only encrypt data that length is a multiple of 16 bytes.
If the length is not a multiple of 16 bytes, we use padding to fill the missing bytes.
In this challenge, we didn’t have to pad the plaintext which means that the length of the plaintext is a multiple of 16 bytes.
So the pad
function in our case is only adding 16 times \x10
(PKCS padding method - IBM) to the ciphertext.
Knowing that we can recover the key and decrypt the ciphertext:
1
2
3
4
5
6
7
8
9
10
11
12
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
iv = b'\xf5\x8e\x85ye\xc8j(%\xc4K\xc1g#\x86\x1a'
ct = b'h\x08\xafmDV\xaa\xcd\xea\xe9C\xdd7/\x1fF\xe2?\xcb\xb0\x1d F\xcc\xe5\xa6\x9dTJ\\\xd1\x90\xac\xe0\x1c\x891}\x83*\x86\xee\xc4~\xa0\x18\xa8\x06\xea"{|\x0b\x92[\x9a[\x91\xc8\x19\xb7FK\x01\xb5\xf98\x80\x9bR)2\x84`\xb3E\t\xd5\xe5\xf0[\x83\xc6\x19\x82\r\x7f\xfaGF\xdb\xcb\xab\xd5~\x95\t\xdd\xb5E>F\xdd\xa9\xa6\x82\x86\xee"\x99\xd9\xcc\xaf\xce\xf0\'\xb3\xf4~\xcf\xdb\xc8\xbd3\x01\xd0,}]\xd5V\xd3?\xb0\xe7\xb4[4\x8a\xa2[\xa1TV\xd16\x1f\xbd"\xc8\xa2\\K\x16I%\xdaL\xc6\xfb\xb7f.\x98\xc3\xf4J\x1b\xe9TT\x83-\x98BO\xb4\x00~\xb5w\xcf7m\xa1\xea\xa9\xf6\xa6\xee\x00Y\xdfE\x9c7\xe3\xa3\xa2\x1f=.\x85\x08l\xacN\xfb2\x89\x8bB\x7f\x94\x91p\x10ep\x9b\x06oz\x87&U]J\x019\x12W\xce<\xc8\xa8\xb4v\xaf,\xb1n\x8b\xf5\xfe\xf8\r\xa7:r\xe8\xe0fvKN\\\xea\xe0\xa1\xe3\x99\xcc\xfd\x1a\x99Q\x90\xdf}\xae\xad'
key = xor(ct[-16:], b"\x10"*16)
cipher = AES.new(key, AES.MODE_CBC, iv)
print(cipher.decrypt(xor(ct, key)))
# b'TCP1P{why_did_the_chicken_cross_the_road?To_ponder_the_meaning_of_life_on_the_other_side_only_to_realize_that_the_road_itself_was_an_arbitrary_construct_with_no_inherent_purpose_and_that_true_enlightenment_could_only_be_found_within_its_own_existence_1234}\xbau\xb9\x0cV\xc4R\x95O\r\x85\x18\tH#F'
and get the flag: TCP1P{why_did_the_chicken_cross_the_road?To_ponder_the_meaning_of_life_on_the_other_side_only_to_realize_that_the_road_itself_was_an_arbitrary_construct_with_no_inherent_purpose_and_that_true_enlightenment_could_only_be_found_within_its_own_existence_1234}