hmac
The Python hmac module implements the Hash-based Message Authentication Code (HMAC) algorithm described in RFC 2104. It combines a secret key with a message and a cryptographic hash function to produce an authentication tag that verifies both the integrity and the authenticity of the data.
Here’s a quick example:
>>> import hmac
>>> import hashlib
>>> secret = b"shared-secret"
>>> message = b"transfer 100 USD to alice"
>>> hmac.new(secret, message, hashlib.sha256).hexdigest()
'a8799a4ac7f268038fe298c315ea9c9ff77391c2db1fa021c51bdf1e763873ba'
Any receiver that knows the same secret key can recompute the tag and confirm that the message has not been altered in transit.
Key Features
- Implements HMAC on top of any fixed-size hash function provided by
hashlib - Accepts keys and messages as
bytesorbytearrayobjects - Supports one-shot
hmac.digest()and incremental hashing throughHMAC.update() - Provides
hmac.compare_digest()for constant-time comparison that resists timing attacks - Exposes
.digest_size,.block_size, and.nameattributes on HMAC objects - Allows cloning an HMAC object with
.copy()to reuse a common prefix across many computations
Frequently Used Classes and Functions
| Object | Type | Description |
|---|---|---|
hmac.new() |
Function | Creates a new HMAC object from a key, an optional initial message, and a digest algorithm |
hmac.digest() |
Function | Computes the HMAC of a key and message in a single optimized call |
hmac.compare_digest() |
Function | Compares two digests in constant time to prevent timing attacks |
hmac.HMAC |
Class | Represents an HMAC object built incrementally from chunks of data |
HMAC.update() |
Method | Feeds additional bytes into the HMAC object |
HMAC.digest() |
Method | Returns the current authentication tag as raw bytes |
HMAC.hexdigest() |
Method | Returns the current authentication tag as a hexadecimal string |
HMAC.copy() |
Method | Returns a clone of the HMAC object, useful for shared prefixes |
Examples
Computing a tag in a single call with the hmac.digest() method:
>>> import hmac
>>> secret = b"shared-secret"
>>> message = b"transfer 100 USD to alice"
>>> hmac.digest(secret, message, "sha256").hex()
'a8799a4ac7f268038fe298c315ea9c9ff77391c2db1fa021c51bdf1e763873ba'
Building the tag incrementally when the message arrives in chunks:
>>> import hmac
>>> tag = hmac.new(b"shared-secret", digestmod="sha256")
>>> tag.update(b"transfer 100 USD ")
>>> tag.update(b"to alice")
>>> tag.hexdigest()
'a8799a4ac7f268038fe298c315ea9c9ff77391c2db1fa021c51bdf1e763873ba'
Verifying a tag safely with compare_digest() instead of the equality operator:
>>> import hmac
>>> secret = b"shared-secret"
>>> message = b"transfer 100 USD to alice"
>>> expected = hmac.new(secret, message, "sha256").hexdigest()
>>> hmac.compare_digest(expected, expected)
True
>>> hmac.compare_digest(expected, "0" * len(expected))
False
Inspecting the algorithm metadata on an HMAC object:
>>> import hmac
>>> tag = hmac.new(b"shared-secret", b"hello", "sha256")
>>> tag.name
'hmac-sha256'
>>> tag.digest_size
32
>>> tag.block_size
64
Common Use Cases
The most common tasks for hmac include:
- Signing and verifying webhook payloads sent between services
- Protecting session cookies and signed tokens from tampering
- Authenticating API requests using a shared secret
- Deriving keys and verifying file integrity in custom protocols
- Detecting corruption or modification in messages exchanged over untrusted channels
Real-World Example
Consider a service that receives webhook callbacks from a payment provider. Each request includes a signature header computed with a shared secret, and the receiver must confirm that the payload is genuine before acting on it:
>>> import hashlib
>>> import hmac
>>> import json
>>> webhook_secret = b"shhh-this-is-secret"
>>> payload = json.dumps(
... {"event": "payment.completed", "amount": 4200},
... separators=(",", ":"),
... ).encode()
>>> signature = hmac.new(webhook_secret, payload, hashlib.sha256).hexdigest()
>>> def verify(payload, signature, secret):
... expected = hmac.new(secret, payload, hashlib.sha256).hexdigest()
... return hmac.compare_digest(expected, signature)
...
>>> verify(payload, signature, webhook_secret)
True
>>> verify(payload + b"tampered", signature, webhook_secret)
False
The verification function recomputes the expected tag from the raw bytes of the payload and the shared secret, then compares it against the signature supplied by the sender using compare_digest(). Any modification to the payload, even a single byte, produces a completely different tag and causes verification to fail.
Related Resources
Tutorial
Bytes Objects: Handling Binary Data in Python
In this tutorial, you'll learn about Python's bytes objects, which help you process low-level binary data. You'll explore how to create and manipulate byte sequences in Python and how to convert between bytes and strings. Additionally, you'll practice this knowledge by coding a few fun examples.
For additional information on related topics, take a look at the following resources:
- Unicode & Character Encodings in Python: A Painless Guide (Tutorial)
- Build a Hash Table in Python With TDD (Tutorial)
- Working With JSON Data in Python (Tutorial)
- Python Bytes (Quiz)
- Unicode in Python: Working With Character Encodings (Course)
- Build a Hash Table in Python With TDD (Quiz)
- Working With JSON in Python (Course)
- Working With JSON Data in Python (Quiz)
By Leodanis Pozo Ramos • Updated April 23, 2026