def mdhash(m: bytes, h: bytes, nopadding: bool = False) -> bytes: state_size = len(h) if not nopadding: m = pkcs7(m) for block in range(len(m) // AES.block_size): cipher = AES.new(pkcs7(h), AES.MODE_ECB) start = block * AES.block_size end = start + AES.block_size h = cipher.encrypt(m[start:end])[:state_size] return h
def _generate_collisions(n: int, start: bytes) -> List[bytes]: h = b'\x00\x00' collisions = [] for _ in range(n): prev_collisions = collisions[:] s1, s2, hashed = _find_collision(start, h) if not collisions: collisions = [s1, s2] else: collisions = [pkcs7(p) + s1 for p in prev_collisions] collisions += [pkcs7(p) + s2 for p in prev_collisions] h = hashed return collisions
def _generate_collisions(n, start): h = '\x00\x00' collisions = [] for level in xrange(n): prev_collisions = collisions[:] s1, s2, hashed = _find_collision(start, h) if not collisions: collisions = [s1, s2] else: collisions = [pkcs7(p) + s1 for p in prev_collisions] collisions += [pkcs7(p) + s2 for p in prev_collisions] h = hashed return collisions
def _generate_suffix(m, funnel): target_states = { h: i for (i, (h, _)) in enumerate(funnel) if i > len(funnel) / 2 } glue = urandom(2) hashed = mdhash(m + glue, '\x00\x00') while hashed not in target_states: glue = urandom(2) hashed = mdhash(m + glue, '\x00\x00') m = pkcs7(m + glue) i = target_states[hashed] while i != 0: h, a = funnel[i] m += pkcs7(a) i = (i - 1) / 2 return m
def aes_ecb_encrypt(ptxt, key): ctxt = '' cipher = AES.new(key, AES.MODE_ECB) padded = pkcs7(ptxt) for block in range(len(padded) / AES.block_size): start = block * AES.block_size end = start + AES.block_size ctxt += cipher.encrypt(padded[start:end]) return ctxt
def p13(): master_key = urandom(16) email = 'hax0r@bar.' + pkcs7('admin') + 'com' profile = _profile_for(email) ctxt = aes_ecb_encrypt(profile, master_key) ctxtmod = _cut_paste_attack(ctxt) ptxtmod = aes_ecb_decrypt(ctxtmod, master_key) profile = validate_pkcs7(ptxtmod) return _parse_encoded_profile(profile)
def _generate_prefix(length, pairs): length *= AES.block_size prefix = '' for long, short in pairs: segment = long if length >= len(long) else short segment = pkcs7(segment) prefix += segment length -= len(segment) if length == 0: return prefix
def _generate_prefix(length: int, pairs: List[Tuple[bytes, bytes]]) -> bytes: length *= AES.block_size prefix = b'' for long, short in pairs: segment = long if length >= len(long) else short segment = pkcs7(segment) prefix += segment length -= len(segment) if length == 0: return prefix
def p49() -> str: our_id = 1 target_id = 2 valid_msg = f'from=#{our_id}&to=#{target_id}&amount=#{1000000}'.encode() good_iv = b'\x00' * AES.block_size client_mac = cbcmac(valid_msg, good_iv) bad_msg = f'from=#{target_id}&to=#{our_id}&amount=#{1000000}'.encode() bad_iv = xor(bad_msg[:AES.block_size], xor(valid_msg[:AES.block_size], good_iv)) assert validate_message(bad_msg, bad_iv, client_mac) valid_msg = f'from=#{target_id}&tx_list=#3:5000;4:7000'.encode() valid_mac = cbcmac(valid_msg) bad_msg = f';{our_id}:1000000'.encode() forged_mac = forge_mac(valid_mac, bad_msg) forged_msg = pkcs7(valid_msg) + pkcs7(bad_msg) assert compare_digest(forged_mac, cbcmac(forged_msg)) return f'Successfully stole 1M spacebucks! Message "{forged_msg.decode()}"' \ f'signed with MAC {hexlify(forged_mac).decode()}'
def p49(): our_id = 1 target_id = 2 valid_msg = 'from=#{}&to=#{}&amount=#{}'.format(our_id, target_id, 1000000) good_iv = '\x00' * AES.block_size client_mac = cbcmac(valid_msg, good_iv) bad_msg = 'from=#{}&to=#{}&amount=#{}'.format(target_id, our_id, 1000000) bad_iv = xor(bad_msg[:AES.block_size], xor(valid_msg[:AES.block_size], good_iv)) assert validate_message(bad_msg, bad_iv, client_mac) valid_msg = 'from=#{}&tx_list=#{}'.format(target_id, '3:5000;4:7000') valid_mac = cbcmac(valid_msg) bad_msg = ';{}:1000000'.format(our_id) forged_mac = forge_mac(valid_mac, bad_msg) forged_msg = pkcs7(valid_msg) + pkcs7(bad_msg) assert compare_digest(forged_mac, cbcmac(forged_msg)) return 'Successfully stole 1M spacebucks! Message "{}" signed with MAC {}'.format( forged_msg, hexlify(forged_mac))
def _block_hash_map(M): block_to_index = {} h = '\x00\x00' M = pkcs7(M) for i in range(len(M) / AES.block_size): start = i * AES.block_size end = start + AES.block_size block = M[start:end] hashed = mdhash(block, h, nopadding=True) block_to_index[hashed] = i h = hashed return block_to_index
def _block_hash_map(M: bytes) -> Dict[bytes, int]: state_to_index = {} h = b'\x00\x00' M = pkcs7(M) for i in range(len(M) // AES.block_size): state_to_index[h] = i start = i * AES.block_size end = start + AES.block_size block = M[start:end] hashed = mdhash(block, h, nopadding=True) h = hashed return state_to_index
def aes_cbc_encrypt(ptxt, key, iv): ctxt = '' cipher = AES.new(key, AES.MODE_ECB) prev_block = iv padded = pkcs7(ptxt) for block in range(len(padded) / AES.block_size): start = block * AES.block_size end = start + AES.block_size cur_block = padded[start:end] tmp = xor(prev_block, cur_block) ctxtblock = cipher.encrypt(tmp) ctxt += ctxtblock prev_block = ctxtblock return ctxt
def forge_mac(valid_mac: bytes, our_msg: bytes) -> bytes: message_block = xor(valid_mac, pkcs7(our_msg)) return cbcmac(message_block)
def forge_mac(valid_mac, our_msg): message_block = xor(valid_mac, pkcs7(our_msg)) return cbcmac(message_block)