Do You Know The Difference Between HMAC and CMAC?

Prof Bill Buchanan OBE FRSE
4 min readMay 25, 2024

If you’re into cybersecurity or secure software development, do you know the difference between an HMAC and a CMAC?

HMAC

HMAC is a message authentication code (MAC) that can be used to verify the integrity and authentication of a message. It involves hashing a message with a secret key and thus differs from standard hashing, which is purely a one-way function. As with any MAC, it can be used with a standard hash function, such as MD5 or SHA-1, which results in methods such as HMAC-MD5 or HMAC-SHA-1. Also, as with any hashing function, the strength depends on the quality of the hashing function, and the resulting number of hash code bits. Along with this, the number of bits in the secret key is a factor in the strength of the hash.

The figure below outlines the operation, where the message to be sent is converted with a secret key and the hashing function to an HMAC code. This is then sent with the message. On receipt, the receiver recalculates the HMAC code from the same secret key and the message and checks it against the received version. If they match, it validates both the sender and the message.

CMAC

CMACs (Cipher-based message authentication codes) create a message authentication codes (MACs) using a block cipher and a secret key. They differ from HMACs in that they use a symmetric key method for the MACs rather than a hashing method. When the recipient receives the CMAC field, they will also compute the same CMAC with the message and the secret key. If they are the same, the recipient knows that the message has not been changed and signed with the secret key.

Coding

The following is the Golang code using Google Tink [here]:

package main
import (
"fmt"
"github.com/google/tink/go/mac"
"github.com/google/tink/go/keyset"
"github.com/google/tink/go/insecurecleartextkeyset"
"os"

)
func main() {
msg:="This is a test"
htype:="HMACSHA256Tag256Key"
key,_ := keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())

argCount := len(os.Args[1:])
if (argCount>0) { msg= (os.Args[1])}
if (argCount>1) { htype= (os.Args[2])}

if htype=="HMACSHA256Tag256Key" { key,_ = keyset.NewHandle(mac.HMACSHA256Tag256KeyTemplate())
} else if htype=="AESCMACTag128Key" { key,_ = keyset.NewHandle(mac.AESCMACTag128KeyTemplate())
} else if htype=="HMACSHA256Tag128Key" {key,_ = keyset.NewHandle(mac.HMACSHA256Tag128KeyTemplate() )
} else if htype=="HMACSHA512Tag256Key" {key,_ = keyset.NewHandle(mac.HMACSHA512Tag256KeyTemplate() )
} else if htype=="HMACSHA512Tag512Key" {key,_ = keyset.NewHandle(mac.HMACSHA512Tag512KeyTemplate()) }

m, _ := mac.New(key)
mac, _ := m.ComputeMAC([]byte(msg))

res:=m.VerifyMAC(mac, []byte(msg))
if (res!=nil) {
fmt.Printf("MAC failed!")
} else {
fmt.Printf("Message: %s\n\n", msg)
fmt.Printf("MAC type: %s\n",htype)
fmt.Printf("MAC: %x\n", mac)
fmt.Printf("\nMAC success!\n\n")
exportedPriv := &keyset.MemReaderWriter{}
insecurecleartextkeyset.Write(key, exportedPriv)
fmt.Printf("Key: %s\n\n", exportedPriv)
}

}

A sample run for HMAC with SHA-256 and a 256-bit key is [here]:

Message: qwerty123
MAC type: HMACSHA256Tag256Key
MAC: 0122589d948fb8a93f1ab0b0de355d736a328648cefde8c38b2e84e9d447875508581dea20
MAC success!
Key: .{primary_key_id:576232852 key:{key_data:{type_url:"type.googleapis.com.google.crypto.tink.HmacKey" value:".x12.x04.x08.x03.x10 .x1a .xf9h.x96.xc1.xd1c.x06N|.x85.x81Ø–.x7f.xa2.xd1.xf8.x14.xe0].xb12*AW.xba.xcc.xf1 .x1b.x9b.xca" key_material_type:SYMMETRIC} status:ENABLED key_id:576232852 output_prefix_type:TINK} .nil.}

For CMAC we get [here]:

Message: qwerty123
MAC type: AESCMACTag128Key
MAC: 0139bae9f2b77bdc6104d08be0ec8e77484402e275
MAC success!
Key: .{primary_key_id:968550898 key:{key_data:{type_url:"type.googleapis.com.google.crypto.tink.AesCmacKey" value:".x12 ZSƃ .xb1.x01Sx..xd2:p.x1c.xbe.xa0.xc4;}.x9b.xb0 tǁ.x93.x81.xa7e.xb3,.xbc.x1a.x02.x08.x10" key_material_type:SYMMETRIC} status:ENABLED key_id:968550898 output_prefix_type:TINK} .nil.}

The main difference between an HMAC and a CMAC is thus that HMAC uses a hashing method for its MAC, whereas CMAC uses a symmetric key method. In the following, we can use a range of symmetric key methods to create the CMAC code [here]:

Conclusions

And, so, the answer is that HMAC uses a hashing method, and CMAC uses a symmetric key method. Overall, HMAC is simplier and faster than CMAC. It is normally the best choice for varying lengths of messages, and for different key sizes. CMAC, though, is possibly better in complying with standards and its integration into a range of protocols.

Here’s an example of CMAC:

--

--

Prof Bill Buchanan OBE FRSE

Professor of Cryptography. Serial innovator. Believer in fairness, justice & freedom. Based in Edinburgh. Old World Breaker. New World Creator. Building trust.