Skip to content
{{ message }}

Instantly share code, notes, and snippets.

# mikeecb/cryptopals_1_16.py

Created May 13, 2017
Cryptopals Set 1 Exercise 16
 from Crypto.Cipher import AES from random import randint def xor(b1, b2): b = bytearray(len(b1)) for i in range(len(b1)): b[i] = b1[i] ^ b2[i] return b def random_key(length): key = bytearray(length) for i in range(length): key[i] = chr(randint(0, 255)) return key 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 unpad_pkcs7(buffer): padding = buffer[-1] for i in range(len(buffer)-1, len(buffer)-padding, -1): if buffer[i] != buffer[-1]: return buffer new_buffer = bytearray() new_buffer[:] = buffer[:-padding] return new_buffer def aes_128_ecb_enc(buffer, key): obj = AES.new(key, AES.MODE_ECB) return bytearray(obj.encrypt(bytes(buffer))) def aes_128_ecb_dec(buffer, key): obj = AES.new(key, AES.MODE_ECB) return bytearray(obj.decrypt(bytes(buffer))) def aes_128_cbc_enc(buffer, key, iv): plaintext = pad_pkcs7(buffer, AES.block_size) ciphertext = bytearray(len(plaintext)) prev_block = iv for i in range(0, len(plaintext), AES.block_size): ciphertext[i: i + AES.block_size] = aes_128_ecb_enc( xor(plaintext[i: i + AES.block_size], prev_block), key, ) prev_block = ciphertext[i: i + AES.block_size] return ciphertext def aes_128_cbc_dec(ciphertext, key, iv): plaintext = bytearray(len(ciphertext)) prev_block = iv for i in range(0, len(ciphertext), AES.block_size): plaintext[i: i + AES.block_size] = xor( aes_128_ecb_dec(bytes(ciphertext[i: i + AES.block_size]), key), prev_block ) prev_block = ciphertext[i: i + AES.block_size] return unpad_pkcs7(plaintext) key = bytes(random_key(AES.block_size)) iv = bytearray(random_key(AES.block_size)) def encryption_oracle(input_data): input_data = input_data.replace(';','%3b').replace('=','%3d') plaintext = bytearray( "comment1=cooking%20MCs;userdata=" + input_data + ";comment2=%20like%20a%20pound%20of%20bacon" ) return aes_128_cbc_enc(plaintext, key, iv) def is_admin(enc_data): plaintext = aes_128_cbc_dec(enc_data, key, iv) return ";admin=true;" in plaintext def crack(): first_block = bytearray('A' * AES.block_size) second_block = bytearray("AadminAtrueA") plaintext = first_block + second_block ciphertext = encryption_oracle(plaintext) # We 'know' the prefix is two blocks long offset = 32 # Change the first byte in first_block 'A' so we change the first byte in # second_block to be ';' ciphertext[offset] = bytes( xor( bytearray(chr(ciphertext[offset])), xor(bytearray("A"), bytearray(";")) ) ) # Change the 7th byte in first_block 'A' so we change the first byte in # second_block to be '=' ciphertext[offset + 6] = bytes( xor( bytearray(chr(ciphertext[offset + 6])), xor(bytearray("A"), bytearray("=")) ) ) # Change the 12th byte in first_block 'A' so we change the first byte in # second_block to be ';' ciphertext[offset + 11] = bytes( xor( bytearray(chr(ciphertext[offset + 11])), xor(bytearray("A"), bytearray(";")) ) ) return is_admin(ciphertext) crack() # True
to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.