The essentials
Quick reference
One focused task per row. Jump to the related section for complete, working examples.
| Use | Syntax | Examples |
|---|---|---|
| Hash bytes with SHA-256 | digest = hashlib.sha256(data).digest() | View examples |
| Render a hexadecimal digest | text = hashlib.sha256(data).hexdigest() | View examples |
| Hash data incrementally | hasher.update(chunk) | View examples |
| Hash an open binary file | with path.open('rb') as file: digest = hashlib.file_digest(file, 'sha256') | View examples |
| Branch a partial hash | branch = hasher.copy() | View examples |
| Construct an algorithm by name | hasher = hashlib.new('sha256', data) | View examples |
| Inspect portable algorithms | portable = hashlib.algorithms_guaranteed | View examples |
| Build an HMAC incrementally | mac = hmac.new(key, message, digestmod=hashlib.sha256) | View examples |
| Calculate an HMAC in one call | tag = hmac.digest(key, message, 'sha256') | View examples |
| Compare authenticators safely | valid = hmac.compare_digest(received_tag, expected_tag) | View examples |
| Generate random secret bytes | key = secrets.token_bytes(32) | View examples |
| Generate a hexadecimal token | token = secrets.token_hex(32) | View examples |
| Generate a URL-safe token | token = secrets.token_urlsafe(32) | View examples |
| Choose securely from a sequence | character = secrets.choice(alphabet) | View examples |
| Generate a bounded integer | index = secrets.randbelow(exclusive_upper_bound) | View examples |
| Derive a PBKDF2 verifier | derived = hashlib.pbkdf2_hmac('sha256', password, salt, iterations, dklen=32) | View examples |
| Derive a scrypt verifier | derived = hashlib.scrypt(password, salt=salt, n=16384, r=8, p=1, dklen=32) | View examples |
| Create a unique password salt | salt = secrets.token_bytes(16) | View examples |
| Authenticate with keyed BLAKE2 | tag = hashlib.blake2b(message, key=key, digest_size=32).digest() | View examples |
| Separate BLAKE2 domains | digest = hashlib.blake2b(data, person=b'cache-v1', digest_size=16).digest() | View examples |
Cryptographic APIs solve different problems: a digest fingerprints bytes, a MAC authenticates bytes with a shared secret, a password KDF deliberately slows guessing, and a cryptographically secure random generator creates unpredictable tokens. Choose the primitive by threat model, encode inputs explicitly, carry algorithm and parameter metadata with stored results, and compare authenticators with compare_digest. Hashes are neither encryption nor proof of authenticity, and the random module is not suitable for secrets.
Step by step
Detailed examples
Hash a precisely encoded byte sequence
Hash functions consume bytes, so define the encoding and serialization before computing a digest. Updating with chunks is equivalent to hashing their concatenation and supports bounded-memory file processing. digest returns raw bytes for protocols and storage; hexdigest returns a display-friendly representation twice as long. hashlib.file_digest was added in Python 3.11 and may bypass normal file-object methods, so treat the file object's position as unknown afterward and close it through a context manager.
import hashlib
payload = 'café'.encode('utf-8')
one_shot = hashlib.sha256(payload)
streamed = hashlib.sha256()
streamed.update(payload[:3])
streamed.update(payload[3:])
print(one_shot.hexdigest())
print(streamed.digest() == one_shot.digest())
print(one_shot.digest_size) 850f7dc43910ff890f8879c0ed26fe697c93a067ad93a7d50f466a7028a9bf4e
True
32Choose algorithms by purpose and interoperability requirements
SHA-256 and SHA-3 are common choices for collision-resistant content digests, while BLAKE2 offers configurable output and keyed modes. MD5 and SHA-1 have known collision weaknesses and must not protect signatures, certificates, or adversarial integrity; a usedforsecurity=False argument can identify an explicitly non-security use on restricted builds, but does not repair an algorithm. algorithms_guaranteed is portable, whereas algorithms_available depends on the linked OpenSSL provider. A plain digest detects accidental changes only when the expected digest arrives through a trusted channel.
import hashlib
prefix = hashlib.sha256(b'event:')
created = prefix.copy()
created.update(b'created')
deleted = prefix.copy()
deleted.update(b'deleted')
print(created.hexdigest()[:16])
print(deleted.hexdigest()[:16])
print(created.digest() != deleted.digest())
print('sha256' in hashlib.algorithms_guaranteed) 77bcff09719f629c
346f09bf9585f92e
True
TrueAuthenticate messages with a secret key
HMAC binds a message to a shared secret and detects tampering by parties without that secret. Select digestmod explicitly and authenticate an unambiguous serialization that includes every security-relevant field, protocol version, and context. Never reuse an ordinary unhashed prefix-secret construction as a substitute. Verify the received tag with hmac.compare_digest rather than ==; inputs must have the same type, and differing lengths or types can still reveal metadata. HMAC provides authenticity, not confidentiality or replay protection.
import hashlib
import hmac
key = b'demonstration-key-not-for-production'
message = b'v1|account=42|amount=1250'
tag = hmac.new(key, message, hashlib.sha256).digest()
def verify(candidate, received):
expected = hmac.digest(key, candidate, 'sha256')
return hmac.compare_digest(received, expected)
print(tag.hex())
print(verify(message, tag))
print(verify(b'v1|account=42|amount=9000', tag)) fc6aa259738cf41ce5349bfa8a1cdf007d6f3046e5640390f097dada8935e3e1
True
FalseGenerate unpredictable tokens with explicit entropy
secrets obtains randomness from the operating system and is intended for credentials, reset links, session identifiers, and cryptographic keys. Pass nbytes explicitly because the default token entropy is intentionally subject to change, even during maintenance releases. token_hex is convenient for case-insensitive text fields; token_urlsafe uses unpadded URL-safe Base64 and is more compact. Store only a digest or MAC of bearer tokens when practical, set an expiry and purpose, and do not log secret values. The random module is designed for simulation, not attackers.
import secrets
raw = secrets.token_bytes(16)
hex_token = secrets.token_hex(16)
url_token = secrets.token_urlsafe(18)
index = secrets.randbelow(10)
print(len(raw), len(hex_token), len(url_token))
print(all(character in '0123456789abcdef' for character in hex_token))
print(0 <= index < 10) 16 32 24
True
TrueUse a password KDF and version every cost parameter
Never store passwords or hash them directly with SHA-256, SHA-3, or BLAKE2. Use a dedicated password-hashing library where possible. hashlib exposes PBKDF2-HMAC and scrypt through compatible OpenSSL builds; since Python 3.12, PBKDF2-HMAC no longer has a slow pure-Python fallback. Generate a unique random salt for each password and store the KDF name, salt, cost parameters, and derived value. Tune cost on production hardware, cap attacker-controlled parameters before verification, compare with compare_digest, and upgrade successful logins when policy changes. Fixed salts and modest costs below are reproducible test vectors, not deployment policy.
import hashlib
import hmac
password = 'correct horse battery staple'.encode('utf-8')
salt = bytes.fromhex('00112233445566778899aabbccddeeff')
iterations = 100_000
stored = hashlib.pbkdf2_hmac('sha256', password, salt, iterations, dklen=32)
candidate = hashlib.pbkdf2_hmac('sha256', password, salt, iterations, dklen=32)
wrong = hashlib.pbkdf2_hmac('sha256', b'wrong', salt, iterations, dklen=32)
print(stored.hex())
print(hmac.compare_digest(stored, candidate))
print(hmac.compare_digest(stored, wrong)) 2a080fdedce213934a91e8142d2eb7165be949c295612ce4b7d87be90ae208b6
True
FalseUse BLAKE2's keyed and personalized modes intentionally
BLAKE2b and BLAKE2s support explicit digest sizes, keys, salts, and personalization. Keyed mode is a native MAC construction, not merely key bytes concatenated with a message. Personalization separates application domains so identical input used for two protocols does not automatically share a digest; it is public context, not a secret. BLAKE2 salt is a fixed constructor parameter with strict maximum length and is not a password-hashing salt. General-purpose BLAKE2 remains unsuitable for password storage because it is intentionally fast.
from hashlib import blake2b
import hmac
payload = b'customer:42'
cache_id = blake2b(payload, digest_size=16, person=b'cache-v1').digest()
audit_id = blake2b(payload, digest_size=16, person=b'audit-v1').digest()
tag = blake2b(payload, key=b'32-byte-demo-key-material-value!', digest_size=16).digest()
expected = blake2b(payload, key=b'32-byte-demo-key-material-value!', digest_size=16).digest()
print(cache_id.hex())
print(audit_id.hex())
print(cache_id != audit_id)
print(hmac.compare_digest(tag, expected)) cf8043a1a37b3d7a7acd583a40b416ed
46e1380c886506a951c5131976b7ba4f
True
TrueLocal code tester
Hash and authenticate a structured message
Compare a public content digest with a keyed authenticator and verify both the original and a modified message.
Press Run to load Python locally.
Sources and further reading
References
Authoritative documentation used to verify and expand this cheat sheet.
- Python Software Foundationhashlib — Secure hashes and message digestsdocs.python.org
- Python Software Foundationhmac — Keyed-Hashing for Message Authenticationdocs.python.org
- Python Software Foundationsecrets — Generate secure random numbers for managing secretsdocs.python.org
- Python Software FoundationSecurity considerationsdocs.python.org
- Python Software FoundationPEP 506 — Adding a Secrets Module to the Standard Librarypeps.python.org
Help us improve
Found a typo or missing example?
Tell us what would make this cheat sheet clearer, more complete, or more useful.



