HMAC is a cryptographic MAC (message authentication code) that uses a cryptographic hash function and a secret key.
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.
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).
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
def md5(buf): return hashlib.md5(buf).digest() hmac_md5 = make_hmac(md5, 64)
hmac_md5(b"key", b"The quick brown fox jumps over the lazy dog").hex()
def sha1(buf): return hashlib.sha1(buf).digest() hmac_sha1 = make_hmac(sha1, 64)
hmac_sha1(b"key", b"The quick brown fox jumps over the lazy dog").hex()
The following values can be used to confirm if an HMAC implementation is behaving correctly.
- Key: key
- Message: The quick brown fox jumps over the lazy dog
- Key: key
- Message: Hello, world!
- Output: 8013adbd3f9eff856800e8d3a7077cef