Python’s hashlib computes cryptographic hash digests. import hashlib. sha256: hashlib.sha256(b"data").hexdigest(). sha512: hashlib.sha512(data).digest(). md5: hashlib.md5(data).hexdigest() — checksums only; not cryptographically secure. blake2b: hashlib.blake2b(data, digest_size=32). sha3_256: hashlib.sha3_256(data).hexdigest(). new: h = hashlib.new("sha256"); h.update(chunk); h.hexdigest(). update: h = hashlib.sha256(); h.update(part1); h.update(part2) — incremental. digest: h.digest() → bytes. hexdigest: h.hexdigest() → hex string. file_digest: hashlib.file_digest(f, "sha256").hexdigest() (Python 3.11+). pbkdf2_hmac: hashlib.pbkdf2_hmac("sha256", password, salt, iterations=600000) — NIST recommended. scrypt: hashlib.scrypt(password, salt=salt, n=2**14, r=8, p=1) — memory-hard. hmac: import hmac; mac = hmac.new(key, msg, hashlib.sha256); mac.hexdigest(). compare_digest: hmac.compare_digest(a, b) — timing-safe comparison. algorithms_available: hashlib.algorithms_available — set of available names. algorithms_guaranteed: hashlib.algorithms_guaranteed. usedforsecurity: hashlib.md5(data, usedforsecurity=False) — FIPS mode hint. secrets: import secrets; secrets.token_hex(32); secrets.token_bytes(32); secrets.compare_digest. Claude Code generates file integrity checkers, API request signers, password hashers, and ETag generators.
CLAUDE.md for hashlib
## hashlib Stack
- Stdlib: import hashlib, hmac, secrets
- Hash: hashlib.sha256(data).hexdigest() | hashlib.file_digest(f, "sha256")
- Password: hashlib.pbkdf2_hmac("sha256", pw.encode(), salt, iterations=600_000)
- HMAC: hmac.new(key, msg, hashlib.sha256).hexdigest()
- Compare: hmac.compare_digest(a, b) — ALWAYS use this, never == for secrets
- Random: secrets.token_hex(32) | secrets.token_bytes(32)
hashlib Security Pipeline
# app/hashing.py — sha256, file_digest, pbkdf2, scrypt, hmac, API signing, ETags
from __future__ import annotations
import base64
import hashlib
import hmac
import os
import secrets
import time
from dataclasses import dataclass
from pathlib import Path
from typing import Any
# ─────────────────────────────────────────────────────────────────────────────
# 1. File integrity
# ─────────────────────────────────────────────────────────────────────────────
def file_sha256(path: str | Path, chunk_size: int = 65536) -> str:
"""
Compute SHA-256 hex digest of a file's contents.
Example:
checksum = file_sha256("dist/app.tar.gz")
assert checksum == expected_sha256
"""
h = hashlib.sha256()
with open(path, "rb") as f:
while chunk := f.read(chunk_size):
h.update(chunk)
return h.hexdigest()
def file_checksums(path: str | Path, algorithms: list[str] = None) -> dict[str, str]:
"""
Compute multiple hash digests of a file in a single pass.
Example:
sums = file_checksums("release.zip", ["sha256", "sha512", "md5"])
# {"sha256": "...", "sha512": "...", "md5": "..."}
"""
if algorithms is None:
algorithms = ["sha256"]
hashers = {alg: hashlib.new(alg) for alg in algorithms}
with open(path, "rb") as f:
while chunk := f.read(65536):
for h in hashers.values():
h.update(chunk)
return {alg: h.hexdigest() for alg, h in hashers.items()}
def hash_bytes(data: bytes, algorithm: str = "sha256") -> str:
"""
Hash raw bytes and return hex digest.
Example:
token_hash = hash_bytes(token.encode(), "sha256")
"""
return hashlib.new(algorithm, data).hexdigest()
def hash_string(s: str, algorithm: str = "sha256", encoding: str = "utf-8") -> str:
"""Hash a string and return hex digest."""
return hash_bytes(s.encode(encoding), algorithm)
def content_hash(obj: Any) -> str:
"""
Deterministic SHA-256 of a JSON-serializable object.
Useful for cache keys and ETags.
Example:
key = content_hash({"user_id": 42, "filters": ["active"]})
"""
import json
canonical = json.dumps(obj, sort_keys=True, separators=(",", ":"))
return hashlib.sha256(canonical.encode()).hexdigest()[:16]
# ─────────────────────────────────────────────────────────────────────────────
# 2. Password hashing (PBKDF2 and scrypt)
# ─────────────────────────────────────────────────────────────────────────────
PBKDF2_ITERATIONS: int = 600_000 # NIST SP 800-132 (2023) recommendation
SALT_SIZE: int = 32 # 256-bit salt
def hash_password(password: str, iterations: int = PBKDF2_ITERATIONS) -> str:
"""
Hash a password using PBKDF2-HMAC-SHA256.
Returns a self-contained string: "pbkdf2$N$salt_hex$hash_hex".
Example:
stored = hash_password("mysecret")
assert verify_password("mysecret", stored)
"""
salt = secrets.token_bytes(SALT_SIZE)
dk = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, iterations)
return f"pbkdf2${iterations}${salt.hex()}${dk.hex()}"
def verify_password(password: str, stored: str) -> bool:
"""
Verify a password against a hash produced by hash_password().
Uses timing-safe comparison to prevent timing attacks.
Example:
if not verify_password(user_input, db_hash):
raise AuthError("Invalid credentials")
"""
try:
scheme, iters_str, salt_hex, hash_hex = stored.split("$", 3)
if scheme != "pbkdf2":
return False
iterations = int(iters_str)
salt = bytes.fromhex(salt_hex)
expected = bytes.fromhex(hash_hex)
except (ValueError, AttributeError):
return False
actual = hashlib.pbkdf2_hmac("sha256", password.encode(), salt, iterations)
return hmac.compare_digest(actual, expected)
def hash_password_scrypt(password: str, n: int = 2**14, r: int = 8, p: int = 1) -> str:
"""
Hash a password using scrypt (memory-hard, stronger than PBKDF2).
Returns "scrypt$N$r$p$salt_hex$hash_hex".
Example:
stored = hash_password_scrypt("mysecret")
"""
salt = secrets.token_bytes(SALT_SIZE)
dk = hashlib.scrypt(password.encode(), salt=salt, n=n, r=r, p=p)
return f"scrypt${n}${r}${p}${salt.hex()}${dk.hex()}"
def verify_password_scrypt(password: str, stored: str) -> bool:
"""Verify scrypt password hash."""
try:
scheme, n_s, r_s, p_s, salt_hex, hash_hex = stored.split("$", 5)
if scheme != "scrypt":
return False
n, r, p = int(n_s), int(r_s), int(p_s)
salt = bytes.fromhex(salt_hex)
expected = bytes.fromhex(hash_hex)
except (ValueError, AttributeError):
return False
actual = hashlib.scrypt(password.encode(), salt=salt, n=n, r=r, p=p)
return hmac.compare_digest(actual, expected)
# ─────────────────────────────────────────────────────────────────────────────
# 3. HMAC request signing
# ─────────────────────────────────────────────────────────────────────────────
def sign_message(key: bytes, message: bytes, algorithm: str = "sha256") -> str:
"""
Compute HMAC of message using key. Returns hex digest.
Example:
sig = sign_message(api_secret, request_body)
"""
mac = hmac.new(key, message, getattr(hashlib, algorithm))
return mac.hexdigest()
def verify_signature(
key: bytes,
message: bytes,
signature: str,
algorithm: str = "sha256",
) -> bool:
"""
Verify an HMAC signature. Uses timing-safe comparison.
Example:
if not verify_signature(secret, body, request.headers["X-Signature"]):
return 401
"""
expected = sign_message(key, message, algorithm)
return hmac.compare_digest(expected, signature)
@dataclass
class APISignature:
"""
Signed API request envelope (similar to AWS Signature V4 / Stripe webhook verification).
Example:
signer = APISignature(key=b"my-secret-key")
payload = b'{"event": "charge.success", "amount": 4999}'
sig = signer.sign(payload)
assert signer.verify(payload, sig)
"""
key: bytes
algorithm: str = "sha256"
timestamp_window: int = 300 # 5 minutes
def sign(self, body: bytes, timestamp: int | None = None) -> str:
"""Sign body with optional timestamp prefix."""
ts = str(timestamp or int(time.time())).encode()
msg = ts + b"." + body
sig = sign_message(self.key, msg, self.algorithm)
return f"t={ts.decode()},v1={sig}"
def verify(self, body: bytes, signature: str, now: int | None = None) -> bool:
"""
Verify signature; reject if timestamp is outside window.
Example:
api.verify(webhook_body, request.headers["Stripe-Signature"])
"""
now = now or int(time.time())
try:
parts = dict(item.split("=", 1) for item in signature.split(","))
ts = int(parts["t"])
sig = parts["v1"]
except (KeyError, ValueError):
return False
if abs(now - ts) > self.timestamp_window:
return False
msg = f"{ts}.".encode() + body
return verify_signature(self.key, msg, sig, self.algorithm)
# ─────────────────────────────────────────────────────────────────────────────
# 4. Secure tokens and IDs
# ─────────────────────────────────────────────────────────────────────────────
def generate_token(length: int = 32) -> str:
"""
Generate a cryptographically secure URL-safe token.
Example:
session_id = generate_token(32) # 64 hex chars
api_key = generate_token(48) # 96 hex chars
"""
return secrets.token_hex(length)
def generate_token_urlsafe(length: int = 32) -> str:
"""Generate a URL-safe base64 token."""
return secrets.token_urlsafe(length)
def derive_key(
password: str | bytes,
salt: bytes | None = None,
length: int = 32,
iterations: int = PBKDF2_ITERATIONS,
) -> tuple[bytes, bytes]:
"""
Derive a symmetric encryption key from a password.
Returns (key_bytes, salt_bytes).
Example:
key, salt = derive_key("my-passphrase")
# Store salt alongside encrypted data
key2, _ = derive_key("my-passphrase", salt=salt)
assert key == key2
"""
if salt is None:
salt = secrets.token_bytes(SALT_SIZE)
key = hashlib.pbkdf2_hmac("sha256", password.encode() if isinstance(password, str) else password, salt, iterations, dklen=length)
return key, salt
def constant_time_equal(a: str | bytes, b: str | bytes) -> bool:
"""
Timing-safe string comparison — prevents timing oracle attacks.
Example:
if not constant_time_equal(provided_token, stored_token):
raise AuthError
"""
if isinstance(a, str):
a = a.encode()
if isinstance(b, str):
b = b.encode()
return hmac.compare_digest(a, b)
# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────
if __name__ == "__main__":
import tempfile
print("=== hashlib demo ===")
print("\n--- file checksums ---")
with tempfile.NamedTemporaryFile(delete=False) as f:
f.write(b"Hello, World!\n" * 1000)
tmp = f.name
sums = file_checksums(tmp, ["sha256", "sha512", "md5"])
for alg, digest in sums.items():
print(f" {alg:8s}: {digest[:24]}...")
Path(tmp).unlink()
print("\n--- content_hash (ETags) ---")
for obj in [{"user": 1, "page": 3}, {"user": 1, "page": 3}, {"user": 2}]:
print(f" {obj} → {content_hash(obj)!r}")
print("\n--- PBKDF2 password hash/verify ---")
stored = hash_password("supersecret")
print(f" stored: {stored[:50]}...")
print(f" verify correct: {verify_password('supersecret', stored)}")
print(f" verify wrong: {verify_password('wrongpassword', stored)}")
print("\n--- scrypt password hash/verify ---")
sc_stored = hash_password_scrypt("supersecret", n=2**12)
print(f" scrypt stored: {sc_stored[:50]}...")
print(f" verify: {verify_password_scrypt('supersecret', sc_stored)}")
print("\n--- HMAC signing ---")
secret = b"my-webhook-secret-key"
body = b'{"event":"charge.success","amount":4999}'
sig = sign_message(secret, body)
print(f" signature: {sig[:24]}...")
print(f" verify ok: {verify_signature(secret, body, sig)}")
print(f" verify tamper:{verify_signature(secret, b'tampered', sig)}")
print("\n--- APISignature (webhook-style) ---")
signer = APISignature(key=b"stripe-style-secret")
payload = b'{"event": "payment.created"}'
envelope_sig = signer.sign(payload, timestamp=int(time.time()))
print(f" sig envelope: {envelope_sig[:40]}...")
print(f" verify: {signer.verify(payload, envelope_sig)}")
print("\n--- tokens ---")
print(f" token_hex(32): {generate_token(32)[:16]}...")
print(f" token_urlsafe(32): {generate_token_urlsafe(32)[:16]}...")
print("\n--- derive_key ---")
key, salt = derive_key("my-passphrase")
key2, _ = derive_key("my-passphrase", salt=salt)
print(f" derived key: {key.hex()[:16]}... match: {key == key2}")
print("\n=== done ===")
For the cryptography alternative — the cryptography package (PyPI) provides authenticated encryption (AES-GCM, ChaCha20-Poly1305), asymmetric key operations (RSA, ECDSA, Ed25519), X.509 certificates, TLS primitives, and Key Derivation Functions (PBKDF2, scrypt, Argon2 via third-party backend); stdlib hashlib + hmac covers hashing, MAC verification, and PBKDF2/scrypt key derivation — use cryptography when you need symmetric encryption, asymmetric signing, or certificate handling, stdlib hashlib+hmac+secrets for file integrity, API request signing, and password hashing where you do not need encryption. For the passlib alternative — passlib (PyPI) provides a multi-algorithm password hashing library with automatic algorithm migration (bcrypt, argon2, sha512_crypt) and a CryptContext for managing hash scheme upgrades over time; stdlib hashlib.pbkdf2_hmac is NIST-approved for password storage but requires manual salt/iteration management — use passlib with bcrypt or argon2 for production user authentication systems needing algorithm agility, stdlib hashlib.pbkdf2_hmac or hashlib.scrypt for new applications where no external deps are acceptable. The Claude Skills 360 bundle includes hashlib skill sets covering file_sha256()/file_checksums()/content_hash() integrity utilities, hash_password()/verify_password() PBKDF2-SHA256 with 600K iterations, hash_password_scrypt()/verify_password_scrypt() memory-hard variant, sign_message()/verify_signature() HMAC, APISignature webhook verifier, generate_token()/derive_key()/constant_time_equal() secure utilities. Start with the free tier to try cryptographic hashing and security pipeline code generation.