Modern Cryptography · 6.2
🔖 HMAC & Message Authentication Codes
Proving data came from someone with the right key — and wasn't changed⏱ ~2 min
A hash function verifies integrity (data wasn't changed) but not authenticity (who sent it). Anyone can compute SHA-256. A Message Authentication Code (MAC) adds a secret key — only someone with the key can produce or verify the MAC.
HMAC — Hash-based Message Authentication Code
math
HMAC(K, M) = H((K ⊕ opad) || H((K ⊕ ipad) || M)) Where: K = secret key M = message H = hash function (e.g., SHA-256) opad = outer padding constant (0x5c repeated) ipad = inner padding constant (0x36 repeated) || = concatenation Result: HMAC-SHA256 produces a 256-bit authentication tagAnyone with key K can verify; without K, the tag cannot be forgedHMAC vs Digital Signatures — When to Use Each
HMAC (Symmetric MAC)
- •Both sender and receiver share the same secret key
- •Very fast — just two hash computations
- •Provides authentication and integrity
- •Does NOT provide non-repudiation — either party could have created it
- •Use for: API authentication, JWT signing (HS256), internal microservice auth
Digital Signature (Asymmetric)
- •Sender signs with private key; anyone can verify with public key
- •Slower — requires asymmetric math
- •Provides authentication, integrity, AND non-repudiation
- •Third parties can verify without a shared secret
- •Use for: public documents, software signing, TLS certificates, email signing
HMAC in Practice
python
import hmacimport hashlib key = b'super-secret-key-at-least-32-bytes-long'message = b'Transfer $100 to account 12345' # Compute HMAC-SHA256mac = hmac.new(key, message, hashlib.sha256).hexdigest()print(mac) # 64-character hex string # Verify (use hmac.compare_digest — NEVER use ==)def verify_mac(key, message, received_mac): expected = hmac.new(key, message, hashlib.sha256).hexdigest() return hmac.compare_digest(expected, received_mac) # hmac.compare_digest prevents timing attacks:# a == b short-circuits on first mismatch, leaking mac length info# compare_digest always takes the same time regardless of where mismatch occurs🔒 SecurityAlways use a constant-time comparison function (hmac.compare_digest in Python, crypto.timingSafeEqual in Node.js) when comparing MACs or tokens. String equality operators short-circuit at the first mismatched byte, leaking timing information that lets attackers forge MACs one byte at a time (timing oracle attack).
🧠Quick Checkfirst try = +5 XP
What does HMAC add that a plain hash doesn't?
🎮 Practice what you learned
⭐ 0 XP🔥 0 days