def test_cbc_flip_fix(self): k = b'\x81\x0ff\t\x04\xb6\xcf\x1f.\x10\x8frd\xb4E\x19' iv = b'e|\x92\xd0\x8b\xd9\x00\xc8X\xf2Noi\xa1\x155' plain_text = b'2222222222222222hhhhhhhhhhhhhhhhZZZZZZZZZZZZZZZZrrrrrrrrrrrrrrrr' cipher = AES.new(k, AES.MODE_CBC, iv=iv) cipher_text = cipher.encrypt(plain_text) t = cipher_text[31] assert cbc_flip_fix( k, 4, iv + cipher_text[:31] + flip(3, bytes([cipher_text[31]])) + cipher_text[32:]) == b'hhhhhhhhhhhhhhhh' assert cbc_flip_fix( k, 4, iv + cipher_text[:32] + flip(6, bytes([cipher_text[32]])) + cipher_text[33:]) == b'ZZZZZZZZZZZZZZZZ'
def testing_flip(testsing_dict_flipped): errors = 1 test_num = 1 for test in testsing_dict_flipped: key, iv = test["key"], test["iv"] answers, ciphers, test_descriptions = test["block_to_return"], test[ "corrupted_cipher"], test["description"] for answer, corrupted_cipher, test_description in zip( answers, ciphers, test_descriptions): print("{}:".format(test_description)) num_of_blocks = len(corrupted_cipher) // 16 my_output = cbc_flip_fix(key, num_of_blocks, iv + corrupted_cipher) if my_output != answer: print("Error #{} in Test #{}".format(errors, test_num)) print("my output: {}\n\toriginal block is: {}\n".format( errors, my_output, answer)) errors += 1 else: print("Passed Test #{}".format(test_num)) test_num += 1 print("") if errors == 1: print("Passed The Test: testing_flip") else: print("Didn't Pass The Test: testing_flip")
def test_cbc_flip_fix(num_tests=100, message_length=8): from Crypto.Random import get_random_bytes import random from functools import reduce def repeat_byte(): return get_random_bytes(1) * block_size for _ in range(num_tests): # we'll use AES CBC key = get_random_bytes(block_size) aes = AES.new(key, AES.MODE_CBC, iv=get_random_bytes(block_size)) # create message and encryption message = reduce(lambda x, y: x + y, [repeat_byte() for _ in range(message_length)]) cipher = aes.iv + aes.encrypt(message) # choose flip bit index and flip that bit # (from the first n blocks, we cannot flip a bit at the last block) flip_message_block = random.randrange(message_length - 1) * block_size flip_cipher_block_byte = flip_message_block + block_size flip_byte = flip_cipher_block_byte + random.randrange(block_size) flipped_cipher = list(cipher) flipped_cipher[flip_byte] = flipped_cipher[flip_byte] ^ (1 << random.randrange(8)) flipped_cipher = bytes(flipped_cipher) # save on the side the original message original_message = message[flip_message_block:flip_message_block + block_size] result = cbc_flip_fix(key, message_length, flipped_cipher) if result != original_message: print("-----Failed a test") print(f"Expected Result: {list(original_message)}") print(f"Got: {list(result)}") break else: print("Passed all cbc_flip_fix tests successfully" f"({num_tests} random tests with message of length {message_length})")