In [59]:
#! python3
from Crypto.Cipher import AES
import string
from itertools import combinations_with_replacement
from binascii import hexlify, unhexlify
# use 0 to replace the unknown info
raw_ct = unhexlify('fe' + '0'*28 + 'c3' + '307df037c689300bbf2812ff89bc0b49')
raw_iv = '0'*16
pt = 'The message is protected by AES!'
key_prefix = '5d6I9pfR7C1JQt'
def recover_key():
for guess in combinations_with_replacement(string.printable, 2):
guess = ''.join(guess)
key = key_prefix + guess
decry_pt = AES.new(key, mode=AES.MODE_CBC, IV=raw_iv).decrypt(raw_ct)
if decry_pt[16] == ord('r') and decry_pt[31] == ord('!'):
return key
def xor_bytes(a,b):
return bytes([i^j for i,j in zip(a,b)])
def recover_ct(key):
right_pt = pt.encode()
wrong_ct = raw_ct
wrong_pt = AES.new(key, mode=AES.MODE_CBC, IV=raw_iv).decrypt(raw_ct)
#
right_first_ct = xor_bytes(wrong_pt[16:], xor_bytes(right_pt[16:], wrong_ct[:16]))
return right_first_ct + raw_ct[16:]
def recover_iv(ct, key):
right_pt = pt.encode()
wrong_iv = raw_iv.encode()
wrong_pt = AES.new(key, mode=AES.MODE_CBC, IV=wrong_iv).decrypt(ct)
#
right_iv = xor_bytes(wrong_pt[:16], xor_bytes(right_pt[:16], wrong_iv))
return right_iv.decode()
key = recover_key()
ct = recover_ct(key)
print(recover_iv(ct, key))