Chain Seed

The chain seed is a secret value used to compute the genesis hash — the prev_hash of the very first entry in the audit chain. A strong, unpredictable seed ensures that an attacker cannot forge the chain from scratch.

How the Genesis Hash Works

When AuditChain records the first audit log entry, it needs a prev_hash to link against. Since there is no previous entry, it derives one from the chain seed:

genesis_hash = SHA-256(chain_seed)

Every subsequent entry links to the one before it:

Entry #1: prev_hash = SHA-256(chain_seed)     hash = SHA-256(data + prev_hash)
Entry #2: prev_hash = hash of Entry #1        hash = SHA-256(data + prev_hash)
Entry #3: prev_hash = hash of Entry #2        hash = SHA-256(data + prev_hash)

The genesis hash anchors the entire chain. If an attacker knows the seed, they can recompute the genesis hash and forge a replacement chain from the beginning.

Configuration

The seed is configured via the chain_seed key in config/audit-chain.php:

'chain_seed' => env('AUDIT_CHAIN_SEED', 'genesis'),

The default value is 'genesis' — a predictable placeholder that is fine for development but must be replaced in production. AuditChain emits a Log::warning() once if the seed is still set to the default 'genesis' value, reminding you to configure a secret seed before going to production.

Setting a Secure Seed

Add AUDIT_CHAIN_SEED to your .env file with a random, high-entropy value:

AUDIT_CHAIN_SEED=your-random-secret-value-here

Generating a Secure Value

Use Laravel's Tinker to generate a 64-character random string:

php artisan tinker --execute="echo Str::random(64);"

Or use OpenSSL from the command line:

openssl rand -hex 32

Either approach produces a value with sufficient entropy.

Why a Predictable Seed Is Dangerous

If the chain seed is left at the default 'genesis' (or any other guessable value), an attacker who gains write access to the audit table can:

  1. Compute the genesis hash themselves (SHA-256('genesis')).
  2. Delete all existing audit logs.
  3. Insert a forged chain that starts from the same genesis hash.
  4. The forged chain passes audit:verify because the hashes are internally consistent.

With a secret seed, step 1 fails — the attacker cannot compute the correct genesis hash, so any forged chain will break at the first link during verification.

Important Considerations

Set the seed before recording any audit logs. The genesis hash is computed at the time the first entry is recorded. Changing the seed after entries exist will cause audit:verify to fail on the first entry, since verification recomputes the genesis hash from the current seed.

Store the seed securely. Treat AUDIT_CHAIN_SEED like any other application secret. Keep it in your .env file (which should never be committed to version control) or in a secrets manager.

Use a unique seed per environment. Your production, staging, and local environments should each have their own seed value. This prevents audit data copied between environments from appearing valid.

Do not rotate the seed. Unlike encryption keys, the chain seed is not meant to be rotated. Changing it invalidates the chain from the very first entry. If the seed is compromised, you should investigate the extent of the compromise and decide whether to re-baseline the chain.