def find_data_injection_block(oracle): # Figure out what block the beginning byte is in. nul = list(grouper(BLOCKSIZE, oracle(b''))) single = list(grouper(BLOCKSIZE, oracle(b'x'))) # The first block that differs between the two contains the first # byte. for i in range(min(len(single), len(nul))): if nul[i] != single[i]: return i return None
def run_p12(): print('Problem 12') oracle = p12_oracle blocksize = find_block_size(oracle) print('Block size is', blocksize, 'bytes.') ecb_check_data = list(grouper(blocksize, oracle(bytes(1000)))) if len(set(ecb_check_data)) == len(ecb_check_data): print('...not ECB, apparently. Huh?') return else: print('ECB detected, as expected.') secret_suffix = find_secret_suffix(oracle, blocksize) if not secret_suffix == SECRET_SUFFIX_12: print("WE'RE WRONNNNNNGGG!") return print('We got it!') test_data = b'Hi there!' assert(secret_suffix_oracle(secret_suffix, test_data) == oracle(test_data)) print('The secret suffix was:') print(secret_suffix.decode()) print()
def is_ecb(ciphertext): # It is overwhelmingly likely that CBC will scramble things enough # that there will be no identical blocks. Meanwhile, ECB will have # many duplicate blocks because I'm passing in all zeros (see # below). blocks = list(grouper(BLOCKSIZE, ciphertext)) return (len(set(blocks)) != len(blocks))
def AES128_CBC_decrypt(ciphertext, key): blocks = list(grouper(BLOCKSIZE, ciphertext)) # Initialization vector last_cipherblock = blocks[0] plaintext = bytearray() for block in blocks[1:]: block = bytes(block) decrypt = AES128_decrypt(block, key) decrypt = xorvec(last_cipherblock, decrypt) plaintext.extend(decrypt) last_cipherblock = block return plaintext
def AES128_CBC_encrypt(plaintext, key, iv=None): if iv is None: iv = os.urandom(BLOCKSIZE) last_cipherblock = iv ciphertext = bytearray(iv) for block in grouper(BLOCKSIZE, plaintext): block = bytes(block) encrypt = AES128_encrypt( xorvec(last_cipherblock, block), key) ciphertext.extend(encrypt) last_cipherblock = encrypt return ciphertext
def test_ct(i): # Generate a candidate injection block. Used later. data = b'x' * i blocks = list(grouper(BLOCKSIZE, oracle(data))) return blocks[injection_block]