def AESOracle(msg, test_mode=False): """ An oracle which does the following, given a message: chooses an integer m uniformly from [5, 10] and prepends a random string of m bytes to a message, then chooses an integer n uniformly from [5, 10] and appends a random string of n bytes to the message; generates a random 16-byte key; then flips a fair coin and encrypts the enlarged message with either AES-ECB or AES-CBC (using another random 16-byte string as the IV) depending on the result. The oracle can be used in a simple model of a chosen- plaintext attack on an unknown cipher. To verify the success of such an attack, the function has an optional "test mode" which exposes the mode of AES used for each encryption. Args: msg (string): the message to be affixed-to and encrypted. msg_format (string): the format in which the bytes of 'filename' are encoded. Options are 'ascii' (default), 'hex', and 'base64'. test_mode (bool): if test_mode=True, the function returns a boolean together with each encryption which reveals which mode of AES was used. If test_mode=False, encryption mode is not revealed. Returns: (if test_mode=False) string : the encryption using either AES_ECB or AES_CBC, and a random key (and IV, if applicable), of the concatenation of 'msg' with random pre/suffixes of small random length. (if test_mode=True) tuple (bool, string): string arg is as described in the case test_mode=False. bool arg is True if AES-ECB was used, False if AES-CBC was used. """ prefix = randMsg(5, 10) postfix = randMsg(5, 10) oracle = Oracle(None, prefix, postfix) coin = randint(0, 1) if coin: ciphertext = oracle.encryptECB(msg) else: ciphertext = oracle.encryptCBC(msg) if test_mode: return (coin, ciphertext) else: return ciphertext
def __init__(self, key=None, prefix=None, postfix=None): if key is None: key = randMsg(16) if prefix is None: prefix = Message(b'') if postfix is None: postfix = Message(b'') self.key = key self.prefix = prefix self.postfix = postfix
def __init__(self, time_seed=False): self.prefix = randMsg(0, 20) self.postfix = Message(b'') if time_seed == 'coin_flip': time_seed = True if randint(0, 1) else False if time_seed is True: self.key = int(time()) else: self.key = randint(0, 2**16 - 1) self.time_seed = time_seed
def collectTimingData(url, filename): """ collect data about the timing needed to get the first byte """ # if partial_sig is None: # partial_sig = '' # get the file we're requesting into the server's cache before we start timing query = {'file': filename, 'signature': '00'} get(url, params=query) # 1765 is the number of trials such that for a given byte, we see it at least once with probability > .999 trials = 1765 raw_times = [None] * trials for trial in range(trials): test_byte = randMsg(1).hex() query = {'file': filename, 'signature': test_byte} time_before = time() r = get(url, params=query) time_after = time() raw_times[trial] = time_after - time_before times = Series(raw_times) return (times.mean(), times.max(), times.std())
msg.pad(block_size=20) print("Message padded to a multiple of 20 bytes:", repr(msg.ascii())) msg.stripPad() print("De-padded message:", repr(msg.ascii())) # more tests and examples trials = 5 len_lower_bound = 0 len_upper_bound = 20 print("\nRunning %d trials with messages of lengths in [%d, %d]:" % (trials, len_lower_bound, len_upper_bound)) for trial in range(trials): msg = randMsg(len_lower_bound, len_upper_bound) print("\nOriginal message of length %d:\n" % len(msg), msg) msg.pad(16) print("Padded to a multiple of 16 bytes, length %d:\n" % len(msg), msg) msg.stripPad(16) print("Padding stripped, length %d:\n" % len(msg), msg) print("\nNote behavior when message length is a multiple of the block size:") msg = randMsg(16) print("\nOriginal message of length %d:\n" % len(msg), msg) msg.pad(16, extra=False) print( "Padded to a multiple of 16 bytes with flag 'extra=False', length %d:\n" % len(msg), msg) msg.stripPad(16, strict=False) print("Padding stripped with flag 'strict=False', length %d:\n" % len(msg),
from tools.message import Message from tools.oracle import Oracle from tools.aesattacks import decryptPostfixECB from tools.randomdata import randMsg prefix = randMsg(0, 20) postfix_str = 'Um9sbGluJyBpbiBteSA1LjAKV2l0aCBteSByYWctdG9wIGRvd24gc28gbXkgaGFpciBjYW4gYmxvdwpUaGUgZ2lybGllcyBvbiBzdGFuZGJ5IHdhdmluZyBqdXN0IHRvIHNheSBoaQpEaWQgeW91IHN0b3A/IE5vLCBJIGp1c3QgZHJvdmUgYnkK' postfix = Message(postfix_str, 'base64') oracle = Oracle(None, prefix, postfix) decryption = decryptPostfixECB(oracle.encryptECB) print(decryption.ascii())
# note: this is the same solution as challenge 20. from tools.message import Message from tools.aes import AES_CTR from tools.aesattacks import breakRepNonceCTR from tools.bitops import XOR from tools.randomdata import randMsg rand_key = randMsg(16) with open('data/set3ch19.txt', 'r') as infile: lines = [ Message(line.rstrip('\n'), 'base64') for line in infile.readlines() ] ciphertexts = [AES_CTR(line, rand_key) for line in lines] partial_key = breakRepNonceCTR(ciphertexts) for line in ciphertexts: key = partial_key + Message(b'\x00' * (len(line) - len(partial_key))) decryption = XOR(line, key) print(decryption)
from tools.authentication import macMD4, BadMAC from tools.authattacks import extendMACMD4 from tools.message import Message from tools.md4 import MD4 from tools.randomdata import randMsg from tools.oracle import Oracle from tools.token import Token, InvalidToken from Crypto.Hash import MD4 as true_MD4 # test md4 implementation against pycrypto's md4 trials = 10 for trial in range(trials): m = randMsg(0, 1000) print("\nTrial %d of %d:" % (trial + 1, trials)) print("\nTesting md4 hash of", m) test_digest = MD4().hash(m) print("Test digest:", test_digest) s = true_MD4.new() s.update(m.bytes) true_digest = s.hexdigest() print("True digest:", true_digest) assert(test_digest == true_digest) # demonstrate implementation of md4 keyed mac key = randMsg(16) msg = randMsg(20)
def __init__(self): self.prefix = Message(b'') self.postfix = Message(b'') self.key = randMsg(16)
def test_repeatXOR_selfInverse(msg_len, key_len): msg = randMsg(msg_len) key = randMsg(key_len) assert repeatXOR(repeatXOR(msg, key), key) == msg
def test_XOR_selfInverse(length): msg1 = randMsg(length) msg2 = randMsg(length) assert XOR(msg1, XOR(msg1, msg2)) == msg2
def test_XOR_isCommutative(length): msg1 = randMsg(length) msg2 = randMsg(length) assert XOR(msg1, msg2) == XOR(msg2, msg1)
def encryptCBC(self, msg): return AES_CBC(self.formMsg(msg), self.key, iv=randMsg(16))