Fakultas Ilmu Komputer UI

Skip to content
Snippets Groups Projects
Commit 900cf892 authored by Benny William Pardede's avatar Benny William Pardede Committed by Benny William Pardede
Browse files

Interaction v0.1

parent 4443fc06
Branches master
No related tags found
No related merge requests found
import time
from oracle import encrypt, is_padding_ok, BLOCK_SIZE
def attack(ciphertext):
pause_print("Attacking. . .\n. . .", 2000)
split_string = lambda x, n: [x[i:i + n] for i in range(0, len(x), n)]
blocks = split_string(ciphertext, BLOCK_SIZE)
guessed_clear = b''
for block_n in range(len(blocks) - 1, 0, -1): # build pair of blocks starting from end of message
spliced_ciphertext = blocks[block_n - 1] + blocks[block_n]
decoded_bytes = b'?' * BLOCK_SIZE # output of block cipher decoding values
# GET VALUE OF SECRET BYTE byte
for byte in range(BLOCK_SIZE - 1, -1, -1):
padding_length = BLOCK_SIZE - byte
# Build hacked ciphertext tail with values to obtain desired padding
hacked_ciphertext_tail = b''
for padder_index in range(1, padding_length):
hacked_ciphertext_tail += bytearray.fromhex(
'{:02x}'.format(padding_length ^ decoded_bytes[byte + padder_index]))
for i in range(0, 256):
attack_str = bytearray.fromhex('{:02x}'.format((i ^ spliced_ciphertext[byte])))
hacked_ciphertext = spliced_ciphertext[:byte] + attack_str + hacked_ciphertext_tail + \
spliced_ciphertext[byte + padding_length:]
if is_padding_ok(hacked_ciphertext):
test_correctness = hacked_ciphertext[:byte - 1] + bytearray.fromhex(
'{:02x}'.format((1 ^ hacked_ciphertext[byte]))) + hacked_ciphertext[byte:]
if not is_padding_ok(test_correctness):
continue
decoded_bytes = decoded_bytes[:byte] + bytearray.fromhex(
'{:02x}'.format(hacked_ciphertext[byte] ^ padding_length)) + decoded_bytes[byte + 1:]
guessed_clear = bytearray.fromhex('{:02x}'.format(i ^ padding_length)) + guessed_clear
# pause_print("Decoded bytes: {:s}".format(str(decoded_bytes)), 100)
pause_print("Guessed bytes: {:s}".format(str(guessed_clear)), 100)
pause_print(". . .", 400)
break
return guessed_clear[:-guessed_clear[-1]] # remove padding!
def test_the_attack():
plaintext = input("Enter plaintext: ").encode("UTF-8")
pause_print("Plaintext: {:s}".format(str(plaintext)), 500)
pause_print("Length: {:d}".format(len(plaintext)), 500)
encrypted = encrypt(plaintext)
pause_print("Ciphertext: {:s}".format(str(encrypted)), 700)
pause_print("Block size: {:d}".format(BLOCK_SIZE))
padding_length = BLOCK_SIZE - (len(plaintext) % BLOCK_SIZE)
pause_print("Padding should be: {:d} bytes of {:s}"
.format(padding_length, str(bytes([padding_length]))), 2000)
cracked_ct = attack(encrypted)
pause_print("Remove {:d} paddings and you got:\n{:s}".format(padding_length, str(cracked_ct)))
assert (cracked_ct == plaintext)
def pause_print(msg, ms=1500):
print(msg)
time.sleep(ms / 1000)
if __name__ == '__main__':
test_the_attack()
from Crypto.Cipher import AES
from Crypto import Random
KEY_LENGTH = 16 # AES128
BLOCK_SIZE = AES.block_size
_random_gen = Random.new()
_key = _random_gen.read(KEY_LENGTH)
def _add_padding(msg):
pad_len = BLOCK_SIZE - (len(msg) % BLOCK_SIZE)
padding = bytes([pad_len]) * pad_len
return msg + padding
def _remove_padding(data):
pad_len = data[-1]
if pad_len < 1 or pad_len > BLOCK_SIZE:
return None
for i in range(1, pad_len):
if data[-i - 1] != pad_len:
return None
return data[:-pad_len]
def encrypt(msg):
iv = _random_gen.read(AES.block_size)
cipher = AES.new(_key, AES.MODE_CBC, iv)
return iv + cipher.encrypt(_add_padding(msg))
def _decrypt(data):
iv = data[:BLOCK_SIZE]
cipher = AES.new(_key, AES.MODE_CBC, iv)
return _remove_padding(cipher.decrypt(data[BLOCK_SIZE:]))
def is_padding_ok(data):
return _decrypt(data) is not None
if __name__ == '__main__':
print("RUN attack.py!!")
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment