Claude Code for hmac: Python HMAC Message Authentication — Claude Skills 360 Blog
Blog / AI / Claude Code for hmac: Python HMAC Message Authentication
AI

Claude Code for hmac: Python HMAC Message Authentication

Published: November 23, 2028
Read time: 5 min read
By: Claude Skills 360

Python’s hmac module computes and verifies HMAC (Hash-based Message Authentication Codes) — keyed hashes that authenticate both message integrity and sender identity. import hmac. Create: h = hmac.new(key, msg=None, digestmod="sha256")key must be bytes; digestmod is a hash name string or hashlib constructor; key shorter than block size is padded, longer is hashed first. Single-call: hmac.digest(key, msg, digest) → raw bytes — faster than creating an object (uses OpenSSL directly when available). Update: h.update(data) — feed more bytes. Result: h.digest() → raw bytes; h.hexdigest() → hex string. Clone: h.copy() — fork state for multiple MAC computations from the same prefix. Attributes: h.digest_size → output length in bytes; h.block_size → underlying hash block size. Constant-time compare: hmac.compare_digest(a, b) → bool — CRITICAL: always use this instead of == for MAC comparison to prevent timing attacks; works with both bytes and str. Common digestmod values: "sha256", "sha512", "sha3_256", "blake2b". Claude Code generates request signing middlewares, webhook validators, API key verifiers, session cookie signers, and tamper-proof token systems.

CLAUDE.md for hmac

## hmac Stack
- Stdlib: import hmac, hashlib, secrets
- Single: mac = hmac.digest(key, msg, "sha256")         # bytes, fast
- Object: h = hmac.new(key, digestmod="sha256")
-         h.update(data); mac = h.digest()
- Hex:    mac_hex = hmac.new(key, msg, "sha256").hexdigest()
- Verify: hmac.compare_digest(received, expected)       # constant-time!
- Note:   key must be bytes; never use == for MAC comparison

hmac Message Authentication Pipeline

# app/hmacutil.py — sign, verify, webhook, API keys, timed tokens
from __future__ import annotations

import base64
import hmac
import hashlib
import json
import secrets
import struct
import time
from dataclasses import dataclass


# ─────────────────────────────────────────────────────────────────────────────
# 1. Core sign/verify helpers
# ─────────────────────────────────────────────────────────────────────────────

def sign(key: bytes, message: bytes, digestmod: str = "sha256") -> bytes:
    """
    Compute HMAC-{digestmod} of message under key.
    Returns raw MAC bytes.

    Example:
        mac = sign(b"secret", b"hello world")
        print(mac.hex())
    """
    return hmac.digest(key, message, digestmod)


def sign_hex(key: bytes, message: bytes, digestmod: str = "sha256") -> str:
    """
    Sign message and return hex-encoded MAC.

    Example:
        tag = sign_hex(b"secret", b"payload")
    """
    return sign(key, message, digestmod).hex()


def verify(
    key: bytes,
    message: bytes,
    mac: bytes,
    digestmod: str = "sha256",
) -> bool:
    """
    Verify that mac is the correct HMAC of message under key.
    Uses constant-time comparison to prevent timing attacks.

    Example:
        ok = verify(b"secret", b"hello world", received_mac)
    """
    expected = sign(key, message, digestmod)
    return hmac.compare_digest(expected, mac)


def verify_hex(
    key: bytes,
    message: bytes,
    mac_hex: str,
    digestmod: str = "sha256",
) -> bool:
    """
    Verify a hex-encoded HMAC.

    Example:
        ok = verify_hex(b"secret", b"payload", "a1b2c3...")
    """
    try:
        mac = bytes.fromhex(mac_hex)
    except ValueError:
        return False
    return verify(key, message, mac, digestmod)


# ─────────────────────────────────────────────────────────────────────────────
# 2. Webhook signature verification
# ─────────────────────────────────────────────────────────────────────────────

def sign_webhook_payload(
    secret: str,
    payload: bytes,
    timestamp: int | None = None,
    digestmod: str = "sha256",
) -> tuple[int, str]:
    """
    Sign a webhook payload (Stripe/GitHub style).
    Returns (timestamp, signature_hex).

    Example:
        ts, sig = sign_webhook_payload("wh_secret", request_body)
        # headers: {"X-Timestamp": ts, "X-Signature": "sha256=" + sig}
    """
    ts = timestamp if timestamp is not None else int(time.time())
    signed_payload = f"{ts}.".encode() + payload
    sig = sign_hex(secret.encode(), signed_payload, digestmod)
    return ts, sig


def verify_webhook_signature(
    secret: str,
    payload: bytes,
    timestamp: int,
    signature: str,
    tolerance_seconds: int = 300,
    digestmod: str = "sha256",
) -> bool:
    """
    Verify a webhook signature with timestamp replay protection.
    Returns False if timestamp is too old or signature is invalid.

    Example:
        ts = int(request.headers["X-Timestamp"])
        sig = request.headers["X-Signature"].removeprefix("sha256=")
        ok = verify_webhook_signature("wh_secret", body, ts, sig)
    """
    if tolerance_seconds > 0:
        age = abs(time.time() - timestamp)
        if age > tolerance_seconds:
            return False
    signed_payload = f"{timestamp}.".encode() + payload
    expected = sign_hex(secret.encode(), signed_payload, digestmod)
    return hmac.compare_digest(expected, signature)


# ─────────────────────────────────────────────────────────────────────────────
# 3. API request signer
# ─────────────────────────────────────────────────────────────────────────────

@dataclass
class SignedRequest:
    method:     str
    path:       str
    timestamp:  int
    nonce:      str
    body_hash:  str        # hex SHA-256 of body
    signature:  str        # hex HMAC-SHA256 of canonical string

    def canonical_string(self) -> str:
        return f"{self.method}\n{self.path}\n{self.timestamp}\n{self.nonce}\n{self.body_hash}"

    def to_headers(self) -> dict[str, str]:
        return {
            "X-Timestamp":  str(self.timestamp),
            "X-Nonce":      self.nonce,
            "X-Signature":  self.signature,
        }


def sign_request(
    key: bytes,
    method: str,
    path: str,
    body: bytes = b"",
    timestamp: int | None = None,
) -> SignedRequest:
    """
    Sign an HTTP request using HMAC-SHA256 over a canonical string.
    Returns a SignedRequest with headers to attach to the outgoing request.

    Example:
        sr = sign_request(api_key, "POST", "/api/orders", json.dumps(order).encode())
        headers = sr.to_headers()
    """
    ts = timestamp if timestamp is not None else int(time.time())
    nonce = secrets.token_hex(8)
    body_hash = hashlib.sha256(body).hexdigest()
    canonical = f"{method.upper()}\n{path}\n{ts}\n{nonce}\n{body_hash}"
    sig = sign_hex(key, canonical.encode())
    return SignedRequest(
        method=method.upper(),
        path=path,
        timestamp=ts,
        nonce=nonce,
        body_hash=body_hash,
        signature=sig,
    )


def verify_request(
    key: bytes,
    method: str,
    path: str,
    body: bytes,
    timestamp: int,
    nonce: str,
    signature: str,
    tolerance_seconds: int = 60,
) -> bool:
    """
    Verify a signed HTTP request. Returns True if valid.

    Example:
        ok = verify_request(
            api_key, "POST", "/api/orders", body,
            int(headers["X-Timestamp"]), headers["X-Nonce"], headers["X-Signature"]
        )
    """
    age = abs(time.time() - timestamp)
    if age > tolerance_seconds:
        return False
    body_hash = hashlib.sha256(body).hexdigest()
    canonical = f"{method.upper()}\n{path}\n{timestamp}\n{nonce}\n{body_hash}"
    expected = sign_hex(key, canonical.encode())
    return hmac.compare_digest(expected, signature)


# ─────────────────────────────────────────────────────────────────────────────
# 4. Timed token (TOTP-style HMAC-based)
# ─────────────────────────────────────────────────────────────────────────────

def hotp(key: bytes, counter: int, digits: int = 6) -> str:
    """
    Compute an HMAC-SHA1 OTP (HOTP — RFC 4226) for a counter value.

    Example:
        code = hotp(seed_key, counter=42)
        print(code)   # 6-digit string like "123456"
    """
    msg = struct.pack(">Q", counter)
    mac = hmac.new(key, msg, digestmod="sha1").digest()
    offset = mac[-1] & 0x0F
    truncated = struct.unpack(">I", mac[offset:offset + 4])[0] & 0x7FFFFFFF
    return str(truncated % (10 ** digits)).zfill(digits)


def totp(key: bytes, digits: int = 6, step: int = 30, time_: float | None = None) -> str:
    """
    Compute a time-based OTP (TOTP — RFC 6238) for the current time step.

    Example:
        import base64
        seed = base64.b32decode("JBSWY3DPEHPK3PXP")
        code = totp(seed)
        print(code)   # 6-digit code valid for ~30 seconds
    """
    t = time_ if time_ is not None else time.time()
    counter = int(t // step)
    return hotp(key, counter, digits)


def verify_totp(
    key: bytes,
    code: str,
    digits: int = 6,
    step: int = 30,
    window: int = 1,
) -> bool:
    """
    Verify a TOTP code within a tolerance window of ±window steps.

    Example:
        ok = verify_totp(seed, user_entered_code)
    """
    t = time.time()
    for offset in range(-window, window + 1):
        expected = totp(key, digits=digits, step=step,
                        time_=t + offset * step)
        if hmac.compare_digest(expected, code):
            return True
    return False


# ─────────────────────────────────────────────────────────────────────────────
# Demo
# ─────────────────────────────────────────────────────────────────────────────

if __name__ == "__main__":
    import os
    print("=== hmac demo ===")

    key = secrets.token_bytes(32)

    # ── sign / verify ─────────────────────────────────────────────────────────
    print("\n--- sign / verify ---")
    msg = b"Hello, HMAC world!"
    tag = sign_hex(key, msg)
    print(f"  msg:  {msg!r}")
    print(f"  tag:  {tag}")
    print(f"  verify(correct):  {verify_hex(key, msg, tag)}")
    print(f"  verify(tampered): {verify_hex(key, b'Tampered!', tag)}")

    # ── timing-safe compare ───────────────────────────────────────────────────
    print("\n--- hmac.compare_digest ---")
    a = "abc123"
    b = "abc123"
    c = "abc124"
    print(f"  compare_digest({a!r}, {b!r}): {hmac.compare_digest(a, b)}")
    print(f"  compare_digest({a!r}, {c!r}): {hmac.compare_digest(a, c)}")

    # ── webhook signing ───────────────────────────────────────────────────────
    print("\n--- webhook sign/verify ---")
    secret = "wh_test_secret_abc"
    payload = json.dumps({"event": "order.created", "id": 42}).encode()
    ts, sig = sign_webhook_payload(secret, payload)
    print(f"  timestamp={ts}  sig={sig[:24]}...")
    ok = verify_webhook_signature(secret, payload, ts, sig)
    print(f"  verify(correct): {ok}")
    print(f"  verify(old ts):  {verify_webhook_signature(secret, payload, ts - 9999, sig)}")

    # ── request signing ────────────────────────────────────────────────────────
    print("\n--- sign_request / verify_request ---")
    api_key = secrets.token_bytes(32)
    body = json.dumps({"item": "widget", "qty": 10}).encode()
    sr = sign_request(api_key, "POST", "/api/orders", body)
    print(f"  headers: {sr.to_headers()}")
    ok = verify_request(
        api_key, sr.method, sr.path, body,
        sr.timestamp, sr.nonce, sr.signature,
    )
    print(f"  verify: {ok}")

    # ── HOTP / TOTP ───────────────────────────────────────────────────────────
    print("\n--- TOTP ---")
    import base64
    seed = base64.b32decode("JBSWY3DPEHPK3PXP")
    code = totp(seed)
    print(f"  current TOTP code: {code}")
    print(f"  verify_totp:       {verify_totp(seed, code)}")
    print(f"  verify wrong:      {verify_totp(seed, '000000')}")

    print("\n=== done ===")

For the hashlib alternative — hashlib.sha256(data).hexdigest() computes a keyless cryptographic hash — use hashlib for content integrity (checksums, deduplication, fingerprinting) where no shared secret is needed; use hmac whenever you need to authenticate the sender of a message (webhooks, API signatures, session cookies) — a plain hash can be recomputed by anyone, while an HMAC requires knowledge of the secret key, making it unforgeable without the key. For the cryptography (PyPI) alternative — cryptography.hazmat.primitives.hmac.HMAC(key, hashes.SHA256()) with h.update(data) and h.verify(mac) provides the same HMAC functionality with additional algorithm agility and a strict hazmat security model — use cryptography when you need ECDSA, RSA signing, AES-GCM encryption, or other primitives beyond HMAC; use hmac from the stdlib for pure message authentication scenarios where the extra dependency is unnecessary overhead. The Claude Skills 360 bundle includes hmac skill sets covering sign()/sign_hex()/verify()/verify_hex() core helpers, sign_webhook_payload()/verify_webhook_signature() webhook authentication, SignedRequest with sign_request()/verify_request() API request signing, and hotp()/totp()/verify_totp() OTP code generators. Start with the free tier to try message authentication patterns and hmac 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