Path: blob/master/Symmetric Key/AES/padding_oracle/padding_oracle.py
336 views
from Crypto.Cipher import AES1from os import urandom2from base64 import b64decode3from pkcs7 import pkcs74import random56BLOCKSIZE = 1678def xor(ctr, plaintext):9return bytearray((ctr[i] ^ plaintext[i] for i in range(len(ctr))))1011def encrypt(key, ptext):12iv = urandom(16)13c = AES.new(key, AES.MODE_CBC, iv)14return iv + c.encrypt(bytes(pkcs7(ptext, BLOCKSIZE), "latin1"))1516def decrypt(key, ctext):17iv = ctext[:16]18c = AES.new(key, AES.MODE_CBC, iv)19return c.decrypt(ctext)2021def is_valid_pad(data):22return data[-data[-1]:].decode("latin1") == data[-1] * chr(data[-1])2324def oracle(data):25key = open("key", "rb").read()26return is_valid_pad(decrypt(key, data))2728def choose_message():29key = open("key", "rb").read()30data = encrypt(key, b64decode(random.choice(open("data").readlines())))31return data3233def set_pad(Cn_1, I, lbound, target_pad):34for i in range(15, lbound, -1):35t = target_pad ^ target_pad - 136Cn_1[i] = Cn_1[i] ^ t37I[i] = Cn_1[i] ^ target_pad38return Cn_1, I3940def pkcs7_unpad(data):41return data[:-data[-1]]4243def break_cbc(iv, prevblock, target):44P = bytearray(16)45prevblock = bytearray(prevblock)46Cn_1 = bytearray(urandom(16))47index = BLOCKSIZE - 148pad = 149I = bytearray(16)50while index >= 0:51for guess in range(256):52Cn_1[index] = guess53concat = iv + Cn_1 + target54if oracle(concat):55Cn_1, I = set_pad(Cn_1, I, index - 1, pad + 1)56break57pad += 158index -= 15960P = xor(prevblock, I)61return P6263def padding_oracle(data):64iv = data[:16]65data = [data[i:i+16] for i in range(16, len(data), 16)]66prev_block = iv67recovered = bytearray()68for block in data:69recovered += break_cbc(iv, prev_block, block)70prev_block = block7172return pkcs7_unpad(recovered)7374if __name__ == "__main__":75msg = choose_message()76print(padding_oracle(msg))77787980