Today’s Lesson
Security for Legal SaaS — Episode 42: Hash-Chained Immutable Logs
If Someone Can Edit the Audit Log, You Don't Have an Audit Log
In Episode 41, we designed audit logs that capture who did what, when, and to which resource. This episode adds the critical property that makes those logs trustworthy: tamper evidence. Specifically, we'll implement hash chains — a technique where each log entry is mathematically linked to every entry before it, so that modifying any single entry breaks a chain that is trivially detectable.
A hash chain gives you a guarantee that append-only storage alone cannot: not just that entries should not be modified, but that if they were modified, you would know.
Hash Functions: A Quick Primer
A hash function — which we first covered in Episode 17 in the context of password storage — is a one-way mathematical transformation that takes an input of any size and produces a fixed-length output (the "hash" or "digest"). Two properties matter here:1
- Deterministic: The same input always produces the same hash
- Collision-resistant: It is computationally infeasible to find two different inputs that produce the same hash
SHA-256 (Secure Hash Algorithm, 256-bit) is the standard choice for audit log chains. It produces a 64-character hexadecimal string from any input. Change a single character in the input, and the output changes completely and unpredictably.2
How Hash Chains Work
The principle is straightforward: each log entry's hash includes the hash of the previous entry.
| Entry | Data | Previous Hash | This Entry's Hash |
|---|---|---|---|
| Entry 0 | `"System initialised"` | `(none — genesis entry)` | `SHA-256("System initialised" + "0000...")` = `a3f2...` |
| Entry 1 | `"sarah.chen viewed doc-001"` | `a3f2...` | `SHA-256("sarah.chen viewed doc-001" + "a3f2...")` = `b7c1...` |
| Entry 2 | `"james.wong approved filing"` | `b7c1...` | `SHA-256("james.wong approved filing" + "b7c1...")` = `d4e8...` |
| Entry 3 | `"system.ai classified doc-002"` | `d4e8...` | `SHA-256("system.ai classified doc-002" + "d4e8...")` = `f1a9...` |
If someone modifies Entry 1 — changing "sarah.chen" to "john.doe" to cover tracks — the hash of Entry 1 changes. But Entry 2's hash was computed using Entry 1's original hash. Now Entry 2's stored hash doesn't match what you'd get by recomputing it. The chain is broken. To hide the tampering, the attacker would need to recompute the hash of every subsequent entry — and if anyone has a copy of any later hash (a checkpoint, an external witness), the fraud is detectable.3
You've seen this before. Git — the version control system — uses exactly the same mechanism. Every commit's hash includes the hash of the parent commit. If anyone modifies a historical commit, every subsequent commit hash changes, and the tampering is immediately visible. Certificate transparency logs use the same principle. So do blockchains — though our use case requires none of the decentralisation overhead.
Implementation: Blockchain-Lite Without the Blockchain
Hash-chained audit logs provide the tamper-evidence property of a blockchain without the consensus mechanism, cryptocurrency, or distributed infrastructure. This is sometimes called "blockchain-lite" — you get the mathematical integrity guarantee without the operational complexity.4
A Minimal Implementation
Each audit log entry includes:
{
"sequence": 42,
"timestamp": "2026-05-18T14:23:07.442Z",
"event_type": "document.classify",
"actor": "sarah.chen@firm.com",
"resource": "doc-a3f2c1",
"outcome": "success",
"previous_hash": "b7c1e3d4f5a6b7c8d9e0f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2",
"entry_hash": "d4e8f1a2b3c4d5e6f7a8b9c0d1e2f3a4b5c6d7e8f9a0b1c2d3e4f5a6b7c8d9e0"
}
The `entry_hash` is computed as: `SHA-256(sequence + timestamp + event_type + actor + resource + outcome + previous_hash)`. Every field that matters for the audit record is included in the hash computation. Changing any field changes the hash.5
Verification
To verify log integrity, you recompute the hash chain from the beginning (or from a trusted checkpoint):
- Start at the genesis entry (or the last verified checkpoint)
- For each entry, compute `SHA-256` of its fields plus the previous entry's hash
- Compare the computed hash to the stored `entry_hash`
- If any computed hash doesn't match the stored hash, that entry or a prior entry has been tampered with
This verification can run as a scheduled job — daily, hourly, or continuously — and should trigger an immediate alert if integrity breaks.6
Tamper Evidence: What Can and Cannot Be Detected
| Scenario | Detectable? | How |
|---|---|---|
| Entry modified | Yes | Hash chain breaks at the modified entry |
| Entry deleted | Yes | Sequence gap; or chain breaks if entries are re-numbered |
| Entry inserted | Yes | Subsequent hashes no longer match (the chain moved) |
| Entries appended (normal) | N/A | This is expected behaviour |
| All entries recomputed by an attacker | Only with external witness | If no external checkpoint exists, a full rewrite could go undetected |
The "full rewrite" scenario is the weakness of a single-system hash chain. If the attacker controls the log storage and can recompute the entire chain, they can produce a consistent but fraudulent chain. The defence: external witnesses.
External Witnesses and Checkpoints
To protect against a full chain rewrite, periodically publish a checkpoint — the latest hash — to a location the log administrator cannot control:7
| Witness Method | Description | Strength |
|---|---|---|
| Separate internal system | Write checkpoint hashes to a different server with different access controls | Protects against single-admin compromise |
| Cloud object storage (immutable) | Write checkpoints to S3 with object lock | Provider guarantees immutability |
| Public transparency log | Publish hashes to a Certificate Transparency-style log | Publicly verifiable; strongest guarantee |
| Email to external party | Automated daily email of the chain head hash to compliance officer's personal account | Simple; surprisingly effective |
| Print and sign | Monthly printout of checkpoint hashes, signed by the compliance officer | Physical evidence; useful for court |
For most legal SaaS platforms, writing checkpoint hashes to a separate cloud storage account with object lock provides a practical balance of security and simplicity.
Practical Options
AWS QLDB (Quantum Ledger Database)
AWS QLDB is a purpose-built ledger database that provides an immutable, cryptographically verifiable transaction log. Every change to the database is tracked in an append-only journal, and QLDB uses SHA-256 hash chains internally to provide tamper evidence.8
Key characteristics:
- Append-only journal: Data cannot be modified or deleted after being committed
- Cryptographic verification: Built-in digest computation and verification API
- SQL-like interface: Familiar query language (PartiQL) for reading data
- Serverless: No infrastructure to manage
QLDB is particularly well-suited for audit logs because it handles the hash chain implementation internally — you write events, and QLDB provides the integrity guarantees automatically.
Note: AWS announced QLDB end-of-life for July 2025, directing customers to Amazon Aurora PostgreSQL with ledger tables or Amazon DynamoDB with provenance tracking. The underlying principles — append-only storage with cryptographic verification — remain the same regardless of the specific service.9
Custom Implementation with PostgreSQL
For teams that prefer not to depend on a proprietary service:
- Create an append-only audit table (INSERT-only permissions for the application, no UPDATE/DELETE)
- Compute and store the hash chain in application code
- Store the table in a separate database with restricted administrative access
- Run a verification job that recomputes and checks the chain
- Publish checkpoint hashes to external storage
This approach gives you full control and avoids vendor lock-in, at the cost of implementing and maintaining the hash chain logic yourself.
Append-Only Databases
Several databases support append-only or immutable table modes:
- PostgreSQL with restricted permissions and triggers that prevent UPDATE/DELETE
- CockroachDB with change data capture for audit streams
- ImmuDB — an open-source immutable database specifically designed for tamper-evident data storage10
When Immutability Matters Most
Not every log entry justifies the overhead of hash-chained immutability. Prioritise:
| Event Category | Immutability Priority | Rationale |
|---|---|---|
| Privilege access events | Critical | Who accessed privileged data and when; discoverable in litigation |
| AI-generated legal documents | Critical | Provenance and approval chain for AI outputs (EP37, EP43) |
| Financial transactions | Critical | Billing, trust account movements, fee calculations |
| Authentication events | High | Login history is often subpoenaed in investigations |
| Document production/disclosure | Critical | What was produced to opposing counsel and when; irreversible |
| Configuration changes | High | Who changed security settings, access controls, or system behaviour |
| General document access | Medium | Important for compliance but lower litigation exposure |
Combining With Episode 41 Design
The complete audit logging architecture:
- Structured JSON entries with the six W's (EP41)
- Append-only storage preventing modification or deletion (EP41)
- Hash chain linking each entry to all previous entries (this episode)
- External checkpoint witnesses protecting against full chain rewrites
- Automated verification running continuously or on schedule
- Access controls separating writers, readers, and administrators
- Retention policy aligned with regulatory requirements (7+ years)
This architecture produces an audit trail that is structured, searchable, tamper-evident, and legally admissible — the foundation that every security control in this series depends on.
What's Next
Episode 43 moves to Provenance Chains for AI Outputs — tracking not just who did what, but which AI model generated a specific legal document, what data it relied on, and whether the same output could be reproduced. When a court asks "where did this analysis come from?", you'll have the answer.
Sources & Further Reading
Sources & references
- DEV Community, Building a Tamper-Evident Audit Log with SHA-256 Hash Chains (Zero Dependencies).
- DEV Community, The Architecture Behind Tamper-Proof Audit Logs.
- MDPI Electronics, AuditableLLM: A Hash-Chain-Backed, Compliance-Aware Auditable Framework for Large Language Models.
- Devoteam, Is AWS QLDB Built on Blockchain Technology?.
- DZone, Immutable Data Integrity Using QLDB and Blockchain.
- Mattermost, Compliance by Design: 18 Tips to Implement Tamper-Proof Audit Logs.
- Pangea, Understanding Audit Logs: What It Is & How to Build One.
- Medium (Mihir Popat), The Future of Immutable Data: A Comprehensive Guide to AWS QLDB.
- GeeksforGeeks, What Is Amazon QLDB? Step-By-Step Process to Configure.
- Bits Lovers, The Benefits of Using Amazon QLDB for Your Business.
- SUDO Consultants, AWS Quantum Ledger Database: Quantum-Resistant Distributed Ledger.