Kyndex
Security & Trust

Audit Log Integrity

How the platform maintains an encrypted, cryptographically chained, and tamper-evident audit log.

The platform maintains a cryptographic audit log that records security-relevant events across the platform. Every entry in the log is encrypted, chained, and verifiable — providing strong guarantees that the audit trail has not been altered, truncated, or reordered after the fact.

This document explains how the audit log works, what it records, and what trust properties it provides.

What Events Are Logged

The audit log captures events across several categories. Each event records a structured payload that includes a timestamp, the action performed, the outcome, and — where applicable — the identity of the actor.

Authentication Events (Active)

  • Successful logins — recorded after the authentication handshake completes
  • Failed login attempts — recorded with a reason code (invalid_credentials, account_locked)
  • Successful registrations — recorded when a new account is created
  • Session revocations — recorded when a user logs out of a single session (auth.session.revoked) or revokes all active sessions (auth.session.revoked_all)

Administrative Events (Active)

  • Platform key migration — recorded when entity platform master keys are migrated (admin.entity.migrate_pmk)

Planned Event Categories

The following event categories are not yet implemented:

  • Document access — retrievals and decryption events
  • Grant lifecycle — creation, claim, acceptance, denial, and revocation events
  • Membership changes — invitation and removal events
  • Consent and revocation decisions — compliance-relevant approval or denial actions
  • Data export requests — audit data or queue data exports

All events follow a consistent schema: a format version, an ISO-8601 timestamp, a dot-separated action identifier (auth.login.success, admin.entity.migrate_pmk, etc.), an outcome string, and optional metadata. The server never batches events — every action that meets the logging criteria produces exactly one audit entry.

How The Chain Works

The audit log forms an ordered, cryptographically linked chain where each entry depends on every entry that came before it.

Chaining Model

Every audit entry carries an integrity check (IC) value computed from three inputs:

  1. A chain key derived deterministically from a genesis seed
  2. The entry payload (the actual event data)
  3. The IC of the previous entry

The genesis seed is generated inside the secure enclave on first write and its KMS-wrapped form is stored in object storage alongside the genesis entry. Each subsequent IC incorporates the chain state of all prior entries:

k[0]   = first 32 bytes of KMS GenerateDataKey plaintext
k[n]   = SHA-256(k[n-1])
IC[0]  = HMAC-SHA256(k[0], "genesis" || zeros[32])
IC[n]  = HMAC-SHA256(k[n], entry_bytes || IC[n-1])

Modifying, inserting, removing, or reordering any entry produces a different IC at that position — and every subsequent IC diverges. A single tampered entry breaks the entire chain from that point forward.

Chain State And Process Lifetime

Chain state — the current key and previous IC — is held in memory within the secure enclave process. Each enclave restart generates a new genesis seed and starts a new independent chain. Object storage may therefore contain entries from multiple chains, each verifiable independently from its own genesis entry.

Key Evolution

Chain keys evolve forward deterministically: k[n] = SHA-256(k[n-1]). SHA-256 is one-way — knowing k[n] does not reveal k[n-1] or any earlier key. The genesis seed is the root from which the entire chain can be re-derived, and is itself protected by the key management service with enclave attestation as the access condition.

Monotonic Ordering

Every entry carries a monotonic index — a strictly increasing integer starting from zero. The system processes the chain sequentially: only one entry can be written at a time, and the index increments atomically. This prevents concurrent writes from producing ambiguous ordering.

Encryption At Rest

The system never stores audit entries in plaintext. The encryption process:

  1. Generates a unique data key for each entry inside the secure enclave via the key management service
  2. Encrypts the entry payload using AES-256-GCM with the generated key
  3. Stores the KMS ciphertext blob (the wrapped data key) alongside the nonce, ciphertext, IC, and monotonic index in object storage
  4. Zeroizes the plaintext data key immediately after encryption

The data key exists in plaintext only inside the enclave during encryption. Only an attested enclave instance can recover it — the platform operator cannot decrypt audit entries outside the trusted execution environment.

Verification On Read

Audit log reads are gated behind an admin API key (Authorization: Admin <key>). When entries are read, the system verifies the full chain before returning decrypted content:

  1. Recovers the genesis seed inside the enclave via attestation-gated KMS decryption
  2. Re-derives the chain key to the position of the entry being verified by applying SHA-256 entry_index + 1 times
  3. Computes the expected IC from the re-derived key, the decrypted entry payload, and the previous entry's IC
  4. Compares the computed IC to the stored IC using constant-time comparison

If the comparison fails, the read returns an error — the chain has been tampered with. IC mismatch errors are fatal to the entire batch and are not swallowed.

Constant-Time Comparison

The system uses a constant-time algorithm for IC comparison to prevent timing side-channel attacks. An attacker observing response times cannot determine how many bytes of a forged IC matched the expected value.

Trust Properties

The audit log provides the following guarantees:

PropertyGuarantee
Append-onlyEntries are written under unique keys with no delete or overwrite path in the write pipeline. There is no mechanism in the application layer to modify an existing entry.
Tamper-evidentAny modification to an entry's payload, position, or ordering breaks the cryptographic chain. The divergence is detected on the next verified read.
Encrypted at restEvery entry is encrypted with a unique data key that can only be recovered inside an attested enclave. Plaintext is never written to persistent storage.
Verifiable on readEvery admin read operation re-derives the chain from the genesis seed and verifies the IC before returning decrypted content.
Forward key secrecyChain keys evolve forward via one-way SHA-256 derivation. Knowing k[n] does not reveal k[0] through k[n-1]. The genesis seed — the root of trust — is KMS-protected and only recoverable inside an attested enclave.
Hardware isolationAll cryptographic operations — key generation, encryption, decryption, chain computation, and verification — execute inside the secure enclave.

What The Audit Log Does Not Cover

The audit log is scoped to security-relevant platform events. It does not provide:

  • Application-level business logic logging — the audit log records access and authorization events, not domain-specific business outcomes
  • Real-time streaming — entries are written synchronously during request processing but are not streamed to external consumers in real time
  • Selective redaction — once an entry is written and chained, it cannot be redacted without breaking the chain; this is by design
  • Cross-system correlation — the audit log does not automatically correlate with external logging systems; entries include timestamps and action identifiers that can be used for manual correlation

On this page