Search code examples
cmac

What is wrong with this CMAC computation?


I have an example of a CMAC computation, which I want to reproduce in Python, however I am failing. The example looks like this:

key = 3ED0920E5E6A0320D823D5987FEAFBB1
msg = CEE9A53E3E463EF1F459635736738962&cmac=

The expected (truncated) CMAC looks like this (note: truncated means that every second byte is dropped)

ECC1E7F6C6C73BF6

So I tried to reenact this example with the following code:

from Crypto.Hash import CMAC
from Crypto.Cipher import AES
from binascii import hexlify, unhexlify

def generate_cmac(key, msg):
    """generate a truncated cmac message.
    Inputs: 
    key: 1-dimensional bytearray of arbitrary length
    msg: 1-dimensional bytearray of arbitrary length
    Outputs:
    CMAC: The cmac number
    CMAC_t: Trunacted CMAC"""


    # Generate CMAC via the CMAC algorithm
    cobj = CMAC.new(key=key, ciphermod=AES)
    cobj.update(msg)
    mac_raw = cobj.digest()

    # Truncate by initializing an empty array and assigning every second byte
    mac_truncated = bytearray(8 * b'\x00')
    it2 = 0
    for it in range(len(mac_raw)):
        if it % 2:
            mac_truncated[it2:it2+1] = mac_raw[it:it+1]
            it2 += 1
    return mac_raw, mac_truncated

key = unhexlify('3ED0920E5E6A0320D823D5987FEAFBB1') # The key as in the example
msg = 'CEE9A53E3E463EF1F459635736738962&cmac='      # The msg as in the example
msg_utf = msg.encode('utf-8')
msg_input = hexlify(msg_utf)                        # Trying to get the bytearray
mac, mact_calc = generate_cmac(key, msg_input)      # Calculate the CMAC and truncated CMAC
# However the calculated CMAC does not match the cmac of the example

My function generate_cmac() works perfectly for other cases, why not for this example?

(If anybody is curious, the example stems from this document Page 18/Table 6)

Edit: An example for a successful cmac computation is the following:

mact_expected = unhexlify('94EED9EE65337086')       # as stated in the application note
key = unhexlify('3FB5F6E3A807A03D5E3570ACE393776F') # called K_SesSDMFileReadMAC
msg = []                                            # zero length input
mac, mact_calc = generate_cmac(key, msg)            # mact_expected and mact_calc are the same
assert mact_expected == mact_calc, "Example 1 failed" # This assertion passes

Solution

  • TLDR: overhexlification

    Much to my stupefaction, the linked example indeed seems to mean CEE9A53E3E463EF1F459635736738962&cmac=when it writes that, since the box below contains 76 hex characters for the the 38 bytes coding that in ASCII, that is 434545394135334533453436334546314634353936333537333637333839363226636d61633d.

    However I'm positive that this does not need to be further hexlified on the tune of 76 bytes as the code does. In other words, my bets are on

    key = unhexlify('3ED0920E5E6A0320D823D5987FEAFBB1')
    msg = 'CEE9A53E3E463EF1F459635736738962&cmac='.encode()
    mac, mact_calc = generate_cmac(key, msg)