Skip to content

core.hashing

Deterministic hashing utilities.

taskclf.core.hashing

Deterministic hashing utilities for schema fingerprinting and PII obfuscation.

stable_hash(payload)

Deterministic SHA-256 of payload, truncated to 12 hex chars.

Used for schema hashing (not for title hashing -- that uses the salted variant :func:salted_hash).

Parameters:

Name Type Description Default
payload str

Arbitrary string to hash.

required

Returns:

Type Description
str

First 12 hexadecimal characters of the SHA-256 digest.

Source code in src/taskclf/core/hashing.py
def stable_hash(payload: str) -> str:
    """Deterministic SHA-256 of *payload*, truncated to 12 hex chars.

    Used for schema hashing (not for title hashing -- that uses the salted
    variant :func:`salted_hash`).

    Args:
        payload: Arbitrary string to hash.

    Returns:
        First 12 hexadecimal characters of the SHA-256 digest.
    """
    digest = hashlib.sha256(payload.encode("utf-8")).hexdigest()
    return digest[:_HASH_TRUNCATION]

salted_hash(payload, salt)

Salted SHA-256 of payload, truncated to 12 hex chars.

Prepends salt to payload before hashing so the same input produces different digests under different salts. Intended for window-title and other PII obfuscation where reversibility must be infeasible even if the hash function is known.

Parameters:

Name Type Description Default
payload str

Arbitrary string to hash (e.g. a window title).

required
salt str

A per-installation or per-session secret.

required

Returns:

Type Description
str

First 12 hexadecimal characters of the SHA-256 digest.

Source code in src/taskclf/core/hashing.py
def salted_hash(payload: str, salt: str) -> str:
    """Salted SHA-256 of *payload*, truncated to 12 hex chars.

    Prepends *salt* to *payload* before hashing so the same input produces
    different digests under different salts.  Intended for window-title and
    other PII obfuscation where reversibility must be infeasible even if the
    hash function is known.

    Args:
        payload: Arbitrary string to hash (e.g. a window title).
        salt: A per-installation or per-session secret.

    Returns:
        First 12 hexadecimal characters of the SHA-256 digest.
    """
    digest = hashlib.sha256((salt + payload).encode("utf-8")).hexdigest()
    return digest[:_HASH_TRUNCATION]

keyed_digest(payload, secret, namespace)

Return an HMAC-SHA256 digest for payload scoped by namespace.

Source code in src/taskclf/core/hashing.py
def keyed_digest(payload: str, secret: str, namespace: str) -> bytes:
    """Return an HMAC-SHA256 digest for *payload* scoped by *namespace*."""
    msg = f"{namespace}:{payload}".encode("utf-8")
    return hmac.new(secret.encode("utf-8"), msg, hashlib.sha256).digest()