HMAC is a cryptographic MAC (message authentication code) that uses a cryptographic hash function and a secret key.

Use cases

HMAC was designed as a message authentication code, but over time it has found use for other purposes. HMAC is commonly used as a keyed hash function. The use cases include:

  • One-time passwords using TOTP / HOTP.
  • Key-derivation with HKDF.

Algorithm

Key processing

The hash function is assumed to process its input in N-byte blocks. The first step of the HMAC algorithm turns an arbitrary-length key into a block-sized key.

First; if the key is longer than the block size, it is hashed with the hash function. Afterwards; the key is padded with 0x00 bytes on the right until it is block-sized.

The result is a key that has the same length as a hash block.

Inner and outer padding

Two padding blocks are generated, both of them block-sized. An inner pad (called ipad) and an outer pad (called opad).

Hashing

Python implementation

In [2]:
def make_hmac(fn, block_size):
    def inner(key, buf):
        if len(key) > block_size:
            key = fn(key)
        
        while len(key) < block_size:
            key += b"\x00"
        
        outer_pad = bytes([x ^ 0x5c for x in key])
        inner_pad = bytes([x ^ 0x36 for x in key])
        
        return fn(outer_pad + fn(inner_pad + buf))
    return inner

HMAC-MD5

In [3]:
def md5(buf):
    return hashlib.md5(buf).digest()

hmac_md5 = make_hmac(md5, 64)
In [4]:
hmac_md5(b"key", b"The quick brown fox jumps over the lazy dog").hex()
Out [4]:
'80070713463e7749b90c2dc24911e275'

HMAC-SHA1

In [5]:
def sha1(buf):
    return hashlib.sha1(buf).digest()

hmac_sha1 = make_hmac(sha1, 64)
In [6]:
hmac_sha1(b"key", b"The quick brown fox jumps over the lazy dog").hex()
Out [6]:
'de7c9b85b8b78aa6bc8a7a36f70a90701c9db4d9'

Test vectors

The following values can be used to confirm if an HMAC implementation is behaving correctly.

HMAC-MD5

  • Key: key
  • Message: The quick brown fox jumps over the lazy dog
  • Output: 80070713463e7749b90c2dc24911e275

  • Key: key
  • Message: Hello, world!
  • Output: 8013adbd3f9eff856800e8d3a7077cef

Useful links and references

  • HMAC on Wikipedia
  • RFC2104 - HMAC: Keyed-Hashing for Message Authentication
  • FIPS 198-1 - The Keyed-Hash Message Authentication Code (HMAC)