Skip to content

Instantly share code, notes, and snippets.

@mikeecb
Created May 9, 2017 14:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save mikeecb/32967dbc2caea9a74a4471126c248dd7 to your computer and use it in GitHub Desktop.
Save mikeecb/32967dbc2caea9a74a4471126c248dd7 to your computer and use it in GitHub Desktop.
Cryptopals Challenge Set 2 Exercise 14 Simplified
from Crypto.Cipher import AES
from random import randint
from collections import defaultdict
def repeated_blocks(buffer, block_length=16):
reps = defaultdict(lambda: -1)
for i in range(0, len(buffer), block_length):
block = bytes(buffer[i:i + block_length])
reps[block] += 1
return sum(reps.values())
def pad_pkcs7(buffer, block_size):
if len(buffer) % block_size:
padding = (len(buffer) / block_size + 1) * block_size - len(buffer)
else:
padding = 0
# Padding size must be less than a byte
assert 0 <= padding <= 255
new_buffer = bytearray()
new_buffer[:] = buffer
new_buffer += bytearray([chr(padding)] * padding)
return new_buffer
def random_key(length):
key = bytearray(length)
for i in range(length):
key[i] = chr(randint(0, 255))
return key
key = bytes(random_key(16))
random_prefix = random_key(randint(0, 15))
def aes_128_ecb_enc(buffer, key):
obj = AES.new(key, AES.MODE_ECB)
return bytearray(obj.encrypt(bytes(buffer)))
def encryption_oracle(data):
unknown_string = bytearray((
"Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkg\n" +
"aGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBq\n" +
"dXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUg\n" +
"YnkK"
).decode("base64"))
plaintext = pad_pkcs7(
random_prefix + data + unknown_string,
AES.block_size,
)
return aes_128_ecb_enc(plaintext, key)
def get_block_size(oracle):
ciphertext_length = len(oracle(bytearray()))
i = 1
while True:
data = bytearray("A" * i)
new_ciphertext_length = len(oracle(data))
if ciphertext_length != new_ciphertext_length:
return new_ciphertext_length - ciphertext_length
i += 1
def is_ecb_mode(buffer, block_size):
return repeated_blocks(buffer, block_size) > 0
def get_unknown_string_size(oracle):
ciphertext_length = len(oracle(bytearray()))
i = 1
while True:
data = bytearray("A" * i)
new_ciphertext_length = len(oracle(data))
if ciphertext_length != new_ciphertext_length:
return new_ciphertext_length - i
i += 1
def get_prefix_padding_size(oracle, unknown_string_size, block_size):
# Only works assuming it's ecb
prefix_padding = bytearray()
for i in range(unknown_string_size):
is_ecb = is_ecb_mode(
oracle(prefix_padding + bytearray("YELLOW SUBMARINE" * 2)),
block_size,
)
if is_ecb:
break
prefix_padding += "A"
return len(prefix_padding)
def get_prefix_size(oracle, block_size, prefix_padding_size):
reps = 10
prefix_padding = bytearray("A" * prefix_padding_size)
buffer = oracle(prefix_padding + bytearray("YELLOW SUBMARINE" * reps))
prev_block = count = index = None
for i in range(0, len(buffer), block_size):
block = buffer[i: i + block_size]
if block == prev_block:
count += 1
else:
index = i
prev_block = block
count = 1
if count == reps:
return index
return -1
def get_unknown_string(oracle):
block_size = get_block_size(oracle)
unknown_string_size = get_unknown_string_size(oracle)
prefix_padding_size = get_prefix_padding_size(oracle, unknown_string_size, block_size)
prefix_size_rounded = get_prefix_size(oracle, block_size, prefix_padding_size)
unknown_string_size -= prefix_size_rounded - prefix_padding_size
unknown_string = bytearray()
unknown_string_size_rounded = ((unknown_string_size / block_size) + 1) * block_size
for i in range(unknown_string_size_rounded - 1, 0, -1):
d1 = bytearray("A" * (i + prefix_padding_size))
c1 = oracle(d1)[prefix_size_rounded:unknown_string_size_rounded + prefix_size_rounded]
for c in range(256):
d2 = d1[:] + unknown_string + chr(c)
c2 = oracle(d2)[prefix_size_rounded:unknown_string_size_rounded + prefix_size_rounded]
if c1 == c2:
unknown_string += chr(c)
break
return unknown_string
get_unknown_string(encryption_oracle)
# Rollin' in my 5.0
# With my rag-top down so my hair can blow
# The girlies on standby waving just to say hi
# Did you stop? No, I just drove by
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment