The problem

An activity log the administrator can edit proves nothing.

Examiners need a history that someone with database access cannot change without it showing.

What you see

Merkle tree, signed checkpoint and the inclusion proof for entry #5Entry #5 is proved to be in the log with 3 hashes: h4, h67, h0–3. The root they produce matches the signed checkpoint.h0h1h2h3h4h4h5h5h6h7h01h23h45h45h67h67h0–3h0–3h4–7h4–7rootroot#0poll_run#1auth#2alert_raised#3poll_rollup#4poll_run#5decision#6alert_raised#7poll_runAudit log · tree size 8leaf = SHA-256(0x00 || entry)node = SHA-256(0x01 || left || right)signed intoCheckpointC2SP signed note, Ed25519gigidlabs.com/appliance/EX-00418Kx3Qe9…7vR0=the root, base64— gigidlabs.com/appliance/EX-0041 Az3f…Hq8=gigidlabs.com/appliance/ is the log’s name, not an address it contacts.Prove entry #51Hash entry #5 to get itsleaf, h5.2Combine it with h4, h67,h0–3, one per level.3The result must equal theroot.4The root must match thesigned checkpoint, and thesignature the registeredkey.IncludedMerkle tree, signed checkpoint and the inclusion proof for entry #5Entry #5 is proved to be in the log with 3 hashes: h4, h67, h0–3. The root they produce matches the signed checkpoint.Checkpointsigned note, Ed25519gigidlabs.com/appliance/EX-00418Kx3Qe9…7vR0=the root, base64— EX-0041 Az3f…Hq8=gigidlabs.com/appliance/ is a name, not an address it contacts.h0h1h2h3h4h4h5h5h6h7h01h23h45h45h67h67h0–3h0–3h4–7h4–7rootroot#0#1#2#3#4#5#6#7Entry #5: decision. Tree size 8.leaf = SHA-256(0x00 || entry)node = SHA-256(0x01 || left || right)Prove entry #51Hash entry #5 to get its leaf, h5.2Combine it with h4, h67, h0–3, one perlevel.3The result must equal the root.4The root must match the signed checkpoint,and the signature the registered key.Included
Inclusion proof. To prove one entry is in the signed log, the verifier needs one hash per level of the tree: 3 for 8 entries, 20 for a million.
What this shows

A Merkle tree over a log of 8 entries, numbered 0 to 7 (#0 poll_run, #1 auth, #2 alert_raised, #3 poll_rollup, #4 poll_run, #5 decision, #6 alert_raised, #7 poll_run). Each entry is hashed into a leaf (h0 to h7); pairs of hashes are hashed into the level above (h01, h23, h45, h67, then h0–3 and h4–7) up to one root. The root and the tree size, 8, are signed into a checkpoint: a C2SP signed note with the origin gigidlabs.com/appliance/EX-0041 (the log's name, not an address the appliance contacts), the size, the root in base64 and an Ed25519 signature. To prove entry #5 is in the log, the verifier hashes the entry, combines it with 3 proof hashes (h4, h67, h0–3), and checks that the result equals the root in the signed checkpoint. Changing any entry would change its leaf, every hash above it and the root, so the signed checkpoint would no longer match.

The audit log: the last signed checkpoint with its size and root, and entries with number, time, actor and sign-in method, action, target, checkpoint and entry hash.(opens the full-size image)The audit log: the last signed checkpoint with its size and root, and entries with number, time, actor and sign-in method, action, target, checkpoint and entry hash.(opens the full-size image)
Every human and system action in an append-only log, checkpointed and signed.

The Audit log shows every entry, newest first: who did it, how they signed in, the action, the target, and whether it is already inside a signed checkpoint.

The last signed checkpoint, with its size and root hash, sits at the top. Any entry can be checked from the command line, while the appliance runs.

Shown in the new interface, which is in development.

appliance audit -data-dir /var/lib/applianceEntries audited:   266 (all, from entry 0)Root from entries: S0LE4pmi7H35HBI1l+Y9ZhCx5alAdP2numxaCzQgME0=Stored root:       S0LE4pmi7H35HBI1l+Y9ZhCx5alAdP2numxaCzQgME0=Latest checkpoint: size 264, root qUGW5l91GHGFMUo6h0GzK7S62Iq7wlw1l5j9rnCLctw=Result:            CLEAN: every entry and tree hash matches, and the latest checkpoint covers them[exit 0]
Real output: every entry re-hashed and checked against the stored tree and the latest checkpoint.

How it works

  • Each entry is canonical JSON (RFC 8785) carrying the hash of the entry before it. The entries form a Merkle tree (RFC 6962 and RFC 9162).
  • A checkpoint, the tree size and root hash, is signed with the appliance’s Ed25519 key every 15 minutes when the log has grown, and at every sign-off.
  • The log tables are append-only in the database, and every change is written in the same transaction as its log entry.
  • The log is checked four ways: at every start, by a full audit every day, at every pack export, and by the examiner’s offline verifier.
  • A restored, rolled-back or rewritten log produces a permanent discontinuity entry, printed in every later pack.
  • Stream the log to your SIEM, and the checkpoint copies held there let the verifier prove history was not rewritten.

What it proves

This is the base of every other claim. Every pack, Rewind answer and board report is proved against a signed checkpoint, and each later pack proves the log still extends the earlier ones.

What it records

Entries this feature writes to the tamper-evident audit log. Each one is in the evidence packs that cover its date.

  • checkpoint_signedThe tree size and root hash, signed.
  • discontinuityThe log was found restored, rolled back, forked or rewritten. It can never be removed.
  • key_rotatedA key handoff, signed by both the old and the new key.
  • authEvery sign-in. Failed attempts: the first of each burst at once, the rest as counts in a summary entry every 15 minutes.
  • config_changeEvery change to sources, users, integrations and policy. Never the secrets.

Limits

What it does not do yet, stated plainly. The technical page lists every known gap.

  • The signing key is software-protected today, by file permissions. Sealing it in a TPM is planned.
  • Key rotation is supported by the format and the verifier. There is no rotation button yet.
  • If someone edits only an entry’s type column directly in the database, filtered views can miss it until the daily full audit catches it: a window of at most a day.

Technical detail

Early access: now taking pilot customers.

See it on your own network.

A live demo with the engineers who built it. We bring a simulated network; you bring your questions.