We are given the following Python code which encrypts two messages with the SAME KEY in AES Counter mode, we know of the the plaintexts.
from Crypto.Cipher import AES
from Crypto.Util import Counter
import os
KEY = os.urandom(16)
def encrypt(plaintext):
cipher = AES.new(KEY, AES.MODE_CTR, counter=Counter.new(128))
ciphertext = cipher.encrypt(plaintext)
return ciphertext.hex()
test = b"No right of private conversation was enumerated in the Constitution. I don't suppose it occurred to anyone at the time that it could be prevented."
print(encrypt(test))
with open('flag.txt', 'rb') as f:
flag = f.read().strip()
print(encrypt(flag))
Because the key is reused, it is actually fairly easy to decrypt the flag. (See here for someone who knows what they're on about, and a program to do it, but I'm going to do it in CyberChef.) If you're interested, it's called a known-plaintext attack.
Succinctly, because the key is reused in Counter mode:
p1
xor key
== c1
p2
xor key
== c2
But, we know p1
, c1
, and c2
. So, we can work out the key as xor is commutative (a xor b == c, a xor c == b, etc.).
We then just need to xor this key with c2
to get p2
and the flag!
This can be shown as: p1
xor c1
= key
xor c2
= p2
.
This is done in thisXOR(%7B'option':'UTF8','string':'No%20right%20of%20private%20conversation%20was%20enumerated%20in%20the%20Constitution.%20I%20don%5C't%20suppose%20it%20occurred%20to%20anyone%20at%20the%20time%20that%20it%20could%20be%20prevented.'%7D,'Standard',false)XOR(%7B'option':'Hex','string':'4b6f25623a2d3b3833a8405557e7e83257d360a054c2ea'%7D,'Standard',false)&input=NDY0ODUxNTIyODM4NjAzOTI2ZjQ0MjJhNGNhNmQ4MWIwMmYzNTFiNDU0ZTZmOTY4YTMyNGZjYzc3ZGEzMGNmOTc5ZWVjNTdjODY3NWRlM2JiOTJmNmMyMTczMDYwNzA2NjIyNjc4MGE4ZDQ1MzlmY2Y2N2Y5ZjU1ODlkMTUwYTZjNzg2NzE0MGI1YTYzZGUyOTcxZGMyMDlmNDgwYzI3MDg4MjE5NGYyODgxNjdlZDkxMGI2NGNmNjI3ZWE2MzkyNDU2ZmExYjY0OGFmZDBiMjM5YjU5NjUyYmFlZGM1OTVkNGY4NzYzNGNmN2VjNDI2MmY4Yzk1ODFkN2Y1NmRjNmY4MzZjZmU2OTY1MThjZTQzNGVmNDYxNjQzMWQ0ZDFiMzYxYw) recipe, and the flag is CHTB{r3u53d_k3Y_4TT4cK}
.