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:
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.
python -m logflip verify-leaf --key-file key.bin leaf.json
python -m logflip verify-db --key-file key.bin fingerprints.jsonEach 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
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.