Link to this headingCBC-MAC

  • Encrypt with [CBC](/Crypto/Symmetric Encryption/Block Ciphers/CBC) and the last block is the MAC.
    • Uses an all zero IV
  • Ensure that the MAC key is different than the encryption key

Link to this headingImplementation

from cryptopals_lib import * from aes_lib import AES def CBC_MAC(enc_obj, message, iv=None): #First Block is the IV cipher_block = iv if iv == None: cipher_block = b"\x00" * enc_obj.block_size blocks = to_blocks(message, enc_obj.block_size) for block in blocks: xor_block = fixedlen_xor(block, cipher_block) cipher_block = enc_obj.aes_block_encryption(xor_block) #Do regular CBC Encryption but the MAC is the last block return cipher_block if __name__ == '__main__': key = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] test = AES(key) out = CBC_MAC(test, add_PKCS7_pad(b"Message Data", test.block_size)) print(out.hex())

Link to this headingIV Control Attack

The first block is controllable if the IV is user controllable

### IV Test real_message = b"Administrator" forged_message = b"administrator" key = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] test = AES(key) real_mac = CBC_MAC(test, add_PKCS7_pad(real_message, test.block_size)) #Manipulate the IV so the input is the same manipulated_iv = fixedlen_xor(b"A", b"a") + b"\x00" * (test.block_size -1) forged_mac = CBC_MAC(test, add_PKCS7_pad(forged_message, test.block_size), iv=manipulated_iv) print(f"real_message: {real_message}, real_mac: {real_mac.hex()}") #real_message: b'Administrator', real_mac: 958b151e5d001a449859077a20c9632d print(f"manipulated_iv: {manipulated_iv.hex()}") #manipulated_iv: 20000000000000000000000000000000 print(f"forged_message: {forged_message}, forged_mac: {forged_mac.hex()}") #forged_message: b'administrator', forged_mac: 958b151e5d001a449859077a20c9632d

Link to this headingMessage Spoofing Attack

### Block Forging real_message = add_PKCS7_pad(b"User=Administrator", test.block_size) forged_message1 = b"User=Administrat" forged_message2 = b"or\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e" key = [0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f] test = AES(key) real_mac = CBC_MAC(test, real_message) #Lets get each block forged_mac_block1 = CBC_MAC(test, forged_message1) forged_mac_block2 = CBC_MAC(test, forged_message2) #XOR the CBC output of forged_message1 with the Second block (forged_message2) forged_input = fixedlen_xor(forged_mac_block1, forged_message2) forged_mac = CBC_MAC(test, forged_input) print(f"real_message: {real_message}, real_mac: {real_mac.hex()}") #real_message: b'User=Administrator\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e', real_mac: 5bd3e29e4485c3c93ad2c54d19c70392 print(f"forged_message1: {forged_message1}, forged_mac: {forged_mac_block1.hex()}") #forged_message1: b'User=Administrat', forged_mac: 80fdcee9dd73a3cdb4642acbb3a6d27b print(f"forged_message2: {forged_message2}, forged_mac: {forged_mac_block2.hex()}") #forged_message2: b'or\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e\x0e', forged_mac: c56302835470a32beeaf0a48adf979de print(f"forged_input: {forged_input}, forged_mac: {forged_mac.hex()}") #forged_input: b'\xef\x8f\xc0\xe7\xd3}\xad\xc3\xbaj$\xc5\xbd\xa8\xdcu', forged_mac: 5bd3e29e4485c3c93ad2c54d19c70392