Skip to content

Documentation

Evidence integrity

HMAC-SHA256 over RFC 8785 canonical JSON, domain-separated HKDF keys, signed leaves, and offline, tamper-evident verification.

The crypto stack#

Every signed artifact uses the same three-part construction, recorded on the canonical run as its leaf MAC:

leaf MAC
HKDF-SHA256 / RFC 8785 (JCS) / HMAC-SHA256
  • HKDF-SHA256 derives two domain-separated keys from one master key, under distinct salt and info constants, so the leaf key and the database key can never collide.
  • RFC 8785 (JCS) canonicalizes the JSON before signing: keys sorted, no insignificant whitespace, deterministic escaping, so a byte-stable form is signed regardless of field order.
  • HMAC-SHA256 signs that canonical form and yields a 64-character lowercase hex MAC.

Signed leaves#

Every leaf is signed, including a withheld one, so the signature covers the withheld state as well. The MAC binds the load-bearing fields: whether evil was confirmed, the tool family, the confidence, the database content hash, the original and tampered timestamps, and the key class. Because key_class is inside the signed payload, a demo-signed leaf cannot be passed off as a production one without invalidating the HMAC. The canonical run leaf MAC is 059d042626b2aa11640526d69c56f05cf39a4bc1b3e7e94e343393819ba5506a.

Offline verification#

Any signed artifact can be re-verified offline, with no network and no stored operational key. Both verifiers re-derive the key from the master key on demand and recompute the MAC over the canonical form.

verify
python -m logflip verify-leaf --key-file key.bin leaf.json
python -m logflip verify-db   --key-file key.bin fingerprints.json

Each exits 0 on pass and 1 on failure. verify-db is variant-independent: it checks the HMAC over every field except the signature itself.

Tamper-evidence#

A single flipped byte in a signed database makes verify-db report a database integrity failure; a tampered leaf fails verify-leaf. All MAC comparisons are constant-time, so a verifier leaks no timing signal about how close a forgery was. The mechanism is simple: the HMAC is computed over the canonical bytes, and any change to the payload changes the recomputed MAC, which fails the constant-time compare.

Key handling#

Keys never touch the command line. Every key is read from a raw 32-byte file passed with --key-file, never as a plain argument that would land in shell history or a process listing. keygen generates a key from the system CSPRNG, writes it mode 0600 on POSIX, and never prints the bytes.

Demo key

The synthetic demo key is refused for verification: it cannot re-verify key custody, and it cannot sign a confirmed leaf. That is the structural reason the canonical run (key class demo) stays provisional.

What integrity does not prove#

The HMAC proves the bytes are unmodified and were sealed by the master-key holder. It is tamper-evident, not tamper-proof: it detects modification, it does not prevent it. And it is not provenance. A holder of the engagement key can seal a database of fabricated patterns and the HMAC will still pass. There is no cryptographic defense against that; the governance layer, a custody standard operating procedure, is the only defense, and that procedure is documented as a draft, not yet enacted.