Hash chain
A hash chain is a sequence of records in which each record stores a cryptographic hash computed over its own contents and the hash of the record before it. Because a hash function's output changes completely when its input changes at all, altering any record invalidates every hash that follows.
| Property | Guaranteed? | Reasoning |
|---|---|---|
| An entry has not been modified since it was written | Yes | Its hash covers its own content; recomputation exposes the change |
| An entry has not been removed from the middle | Yes | The next entry's hash covers the removed entry's hash, so the link fails |
| The order of entries is fixed | Yes | Order is structural, not a sortable column |
| Entries were truthful when written | No | A chain preserves inputs; it does not evaluate them |
| Nothing was omitted at write time | No | An event never logged leaves no gap to detect |
| Entries were not appended later with a backdated timestamp | Partial | Position is fixed relative to neighbours; the timestamp value itself is only as trustworthy as the writer |
| The whole chain has not been rebuilt from scratch | No | Whoever controls storage can recompute every hash, unless a historical head is anchored externally |
| Verification is possible without trusting the vendor | Yes | Given an export, anyone can recompute the chain independently |
The mechanism, worked through three entries
Take a genesis value of all zeros. Then:
- Entry 1 — content
{actor: A, event: send, target: 118}. Its stored hash isH1 = sha256(0000… ‖ canonical(entry1)). - Entry 2 — content
{actor: B, event: access, target: 204}. Its stored hash isH2 = sha256(H1 ‖ canonical(entry2)). - Entry 3 — content
{actor: A, event: export, target: org}. Its stored hash isH3 = sha256(H2 ‖ canonical(entry3)).
Now suppose someone edits entry 2, changing the actor from B to C. Recomputing gives a different H2'. Entry 3's stored hash was computed over the original H2, so recomputing entry 3 now yields H3' ≠ H3. The verifier walks the chain, finds the first index where recomputation diverges from the stored value, and that index is the tampered entry. The same happens if entry 2 is deleted outright.
The word canonical is doing real work. If the event is serialised as JSON and the key order can vary between writes, two logically identical events hash differently and verification produces false positives. A canonical serialisation — fixed key order, fixed number formatting, fixed encoding — is a precondition, not a detail.
Concurrency, the part that usually breaks
A chain is inherently serial: entry N cannot be computed until entry N−1's hash is final. Under concurrent writers, two transactions can both read the same "latest" hash and both write entries claiming it as their predecessor, producing a fork that will never verify.
The fix is a lock around the read-latest-then-append sequence. Kastr takes a Postgres advisory transaction lock scoped to the organisation, so appends within one organisation serialise while different organisations proceed independently. This is also the reason chains are per-organisation rather than one global sequence: a single global chain would serialise every write in the system behind one lock.
What to pair it with, and why
A hash chain makes tampering detectable. It does not make tampering hard. If the log table is ordinarily writable, an attacker or a careless migration can edit an entry and then simply recompute every subsequent hash, and the chain will verify cleanly.
So the chain belongs on top of an append-only enforcement layer, not instead of one. Kastr revokes UPDATE and DELETE from the application database role and defines no UPDATE or DELETE row-level policy, which means the ordinary path cannot modify history at all; the chain then covers the case where someone reaches the data by a path outside the application.
The rung above — publishing the chain head periodically somewhere outside the vendor's control — is what defeats a wholesale rebuild. We have not built that, and the honest description of our position is rung 4 of the tamper-resistance ladder.
The common misconception
"It's blockchain for audit logs." A hash chain is one component of a blockchain and much the least interesting one. What makes a blockchain resistant to rewriting is not the chaining, it is distributed consensus among parties who do not trust each other: rewriting requires convincing a majority of independent nodes. A single-writer hash chain has no consensus layer, so the party who controls storage can rebuild it. That is not a flaw — for an audit log inside one organisation's database, consensus would be enormous cost for no benefit — but it is why the honest claim is "tamper-evident", not "immutable".
Questions people actually ask
What does a hash chain actually prove?
That no entry has been modified or removed since it was written, and that the ordering is fixed — verifiable by anyone who can recompute the hashes, without trusting the system that stored them. It proves nothing about whether entries were accurate when written, and nothing about events that were never logged.
Is a hash chain the same as a blockchain?
No. A blockchain is a hash chain plus a consensus mechanism across mutually distrusting parties. The consensus is what makes rewriting infeasible. A hash chain on its own can be rebuilt by whoever controls the storage, which is why it is described as tamper-evident rather than immutable.
Can someone rewrite an entire hash chain?
Whoever can write to the underlying storage can, by recomputing every hash from the altered point forward. Two things raise the cost: revoking update and delete privileges so the ordinary application path cannot do it, and anchoring the chain head externally at intervals so a historical value exists outside the system. Kastr does the first and not the second.
Why do you need append-only permissions if you already have a hash chain?
Because the chain detects tampering after the fact rather than preventing it, and detection only helps if someone verifies. Revoked privileges stop the ordinary path entirely; the chain covers the paths that bypass the application. Each covers the other's weakness, which is why using both is standard rather than redundant.
One price. Every feature. Locked for three years.
$3.50 per student per year under 5,000 students. No tiers, no add-on modules, no per-message fees. Published on the site because you should not have to book a call to learn a price.