
How AuditTrail’s tamper-evidence works
Without you having to take our word for it.
The promise
Tamper-evidence means that any modification to any captured AI conversation — changing a word, deleting a record, reordering entries — breaks a cryptographic chain at exactly the point of modification.
The broken position is detectable by anyone: a regulator, a client, opposing counsel, or a curious technologist. No account is required. No special software is required beyond a browser that supports Web Crypto (every modern browser since 2014).
AuditTrail does not rely on a trusted central server for verification. The chain is self-contained: the math is public, the algorithm is frozen at v1, and the full specification is published on GitHub.
The algorithm, in five steps
1. Capture
Each AI conversation turn is captured as a structured record containing the timestamp, the provider (e.g. claude.ai), the user's prompt, the model's response, and a unique event ID.
// CaptureRecord shape (abbreviated)
{
event_id: "<UUID>",
captured_at: "<ISO-8601 timestamp>",
provider: "claude.ai",
prompt: "<user's question>",
response: "<AI's answer>",
hash_version: 1,
previous_hash: "<hash of preceding record, or null>",
hash: "<SHA-256 of this record's canonical JSON>"
}2. Canonicalize
Before hashing, the record's fields are serialized in a deterministic order. Keys are sorted lexicographically, no whitespace is added, and the result is encoded as UTF-8. This ensures the hash is identical regardless of field insertion order.
// Canonical key order for v1:
// captured_at, event_id, hash_version, model, previous_hash,
// prompt, provider, response, url, user_id
//
// Example output (no whitespace):
canonical = JSON.stringify(sortedFields)
// → '{"captured_at":"2026-05-21T14:00:00.000Z","event_id":"c0ff...","hash_version":1,...}'3. Link
The SHA-256 hash is computed over the canonical JSON of the record, with the previous record’s hash injected as the “previous_hash” field. This cryptographically links each record to the one before it.
hash = hex(SHA-256(UTF-8(canonicalJson({
...fields,
previous_hash: previousRecord.hash // null for first record
}))))
// → 64 lowercase hex characters4. Store
The computed hash is stored alongside the record. The chain tip — the hash of the most recent record — is updated atomically so the next capture can link to it.
// Stored in the database: record.hash = computedHash record.previous_hash = previousRecord.hash // Chain tip updated: user.chain_tip_hash = computedHash
5. Verify
Anyone with the exported chain JSON can re-walk the chain: recompute each record's hash and check that (a) the result matches the stored hash, and (b) the previous_hash field matches the prior record's hash. Any mismatch identifies the exact tampered record by position.
for i, record in enumerate(chain):
# Check chain link
assert record.previous_hash == chain[i-1].hash # null for i=0
# Check content integrity
computed = sha256(canonical(record, record.previous_hash))
assert computed == record.hash
# If all pass → valid. Any failure → tampered at position i.Interactive demo
The records below are from the same sample chain used on the /verify page — a hypothetical Claude conversation about Ontario Rule 4.06.1(2.1). Edit any AI response textarea to simulate tampering. The hash chain breaks at that record and propagates downstream. Click Reset to original sample to restore the valid chain.
What this does not prove
The hash chain proves three things: (a) records have not been altered after capture, (b) the ordering has not been changed, and (c) records have not been silently removed from the middle of the chain.
It does not prove that the AI’s output was correct, that the lawyer reviewed it competently, or that the capture happened when claimed. The timestamp in each record is set by the capture device at the moment of capture; third-party time anchoring (public blockchain timestamping) is a planned future feature and is not part of v1.
AuditTrail is an evidence-preservation tool, not a certification service. It creates a verifiable record of what was asked and what was answered — nothing more, nothing less.
Verify any chain yourself
You don’t need an AuditTrail account to verify a chain. The two resources below are all you need: