Claude Code for hashlib: Hashing and HMAC in Python — Claude Skills 360 Blog
Blog / AI / Claude Code for hashlib: Hashing and HMAC in Python
AI

Claude Code for hashlib: Hashing and HMAC in Python

Published: July 11, 2028
Read time: 5 min read
By: Claude Skills 360

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.

Keep Reading

AI

Claude Code for email.contentmanager: Python Email Content Accessors

Read and write EmailMessage body content with Python's email.contentmanager module and Claude Code — email contentmanager ContentManager for the class that maps content types to get and set handler functions allowing EmailMessage to support get_content and set_content with type-specific behaviour, email contentmanager raw_data_manager for the ContentManager instance that handles raw bytes and str payloads without any conversion, email contentmanager content_manager for the standard ContentManager instance used by email.policy.default that intelligently handles text plain text html multipart and binary content types, email contentmanager get_content_text for the handler that returns the decoded text payload of a text-star message part as a str, email contentmanager get_content_binary for the handler that returns the raw decoded bytes payload of a non-text message part, email contentmanager get_data_manager for the get-handler lookup used by EmailMessage get_content to find the right reader function for the content type, email contentmanager set_content text for the handler that creates and sets a text part correctly choosing charset and transfer encoding, email contentmanager set_content bytes for the handler that creates and sets a binary part with base64 encoding and optional filename Content-Disposition, email contentmanager EmailMessage get_content for the method that reads the message body using the registered content manager handlers, email contentmanager EmailMessage set_content for the method that sets the message body and MIME headers in one call, email contentmanager EmailMessage make_alternative make_mixed make_related for the methods that convert a simple message into a multipart container, email contentmanager EmailMessage add_attachment for the method that attaches a file or bytes to a multipart message, and email contentmanager integration with email.message and email.policy and email.mime and io for building high-level email readers attachment extractors text body accessors HTML readers and policy-aware MIME construction pipelines.

5 min read Feb 12, 2029
AI

Claude Code for email.charset: Python Email Charset Encoding

Control header and body encoding for international email with Python's email.charset module and Claude Code — email charset Charset for the class that wraps a character set name with the encoding rules for header encoding and body encoding describing how to encode text for that charset in email messages, email charset Charset header_encoding for the attribute specifying whether headers using this charset should use QP quoted-printable encoding BASE64 encoding or no encoding, email charset Charset body_encoding for the attribute specifying the Content-Transfer-Encoding to use for message bodies in this charset such as QP or BASE64, email charset Charset output_codec for the attribute giving the Python codec name used to encode the string to bytes for the wire format, email charset Charset input_codec for the attribute giving the Python codec name used to decode incoming bytes to str, email charset Charset get_output_charset for returning the output charset name, email charset Charset header_encode for encoding a header string using the charset's header_encoding method, email charset Charset body_encode for encoding body content using the charset's body_encoding, email charset Charset convert for converting a string from the input_codec to the output_codec, email charset add_charset for registering a new charset with custom encoding rules in the global charset registry, email charset add_alias for adding an alias name that maps to an existing registered charset, email charset add_codec for registering a codec name mapping for use by the charset machinery, and email charset integration with email.message and email.mime and email.policy and email.encoders for building international email senders non-ASCII header encoders Content-Transfer-Encoding selectors charset-aware message constructors and MIME encoding pipelines.

5 min read Feb 11, 2029
AI

Claude Code for email.utils: Python Email Address and Header Utilities

Parse and format RFC 2822 email addresses and dates with Python's email.utils module and Claude Code — email utils parseaddr for splitting a display-name plus angle-bracket address string into a realname and email address tuple, email utils formataddr for combining a realname and address string into a properly quoted RFC 2822 address with angle brackets, email utils getaddresses for parsing a list of raw address header strings each potentially containing multiple comma-separated addresses into a list of realname address tuples, email utils parsedate for parsing an RFC 2822 date string into a nine-tuple compatible with time.mktime, email utils parsedate_tz for parsing an RFC 2822 date string into a ten-tuple that includes the UTC offset timezone in seconds, email utils parsedate_to_datetime for parsing an RFC 2822 date string into an aware datetime object with timezone, email utils formatdate for formatting a POSIX timestamp or the current time as an RFC 2822 date string with optional usegmt and localtime flags, email utils format_datetime for formatting a datetime object as an RFC 2822 date string, email utils make_msgid for generating a globally unique Message-ID string with optional idstring and domain components, email utils decode_rfc2231 for decoding an RFC 2231 encoded parameter value into a tuple of charset language and value, email utils encode_rfc2231 for encoding a string as an RFC 2231 encoded parameter value, email utils collapse_rfc2231_value for collapsing a decoded RFC 2231 tuple to a Unicode string, and email utils integration with email.message and email.headerregistry and datetime and time for building address parsers date formatters message-id generators header extractors and RFC-compliant email construction utilities.

5 min read Feb 10, 2029

Put these ideas into practice

Claude Skills 360 gives you production-ready skills for everything in this article — and 2,350+ more. Start free or go all-in.

Back to Blog

Get 360 skills free