Concepts · Templates
Evidence bundle
Litigation-grade self-contained ZIP archive that a court can verify using only public artifacts. RFC 3161 trusted timestamps, KMS-signed audit chain, Sigstore Rekor anchor records, per-file Ed25519 signatures, and a bundled verify.sh script.
Last updated
When a Matter-rendered document's executionStatus transitions to
executed, the archive worker writes a frozen render bundle to
AWS S3 with Object Lock + Compliance retention (7 years, non-deletable).
That bundle is the system of record; the live Vercel Blob is a cache.
Callers can extract the bundle as a self-contained, court-verifiable ZIP via:
POST /v1/documents/{id}/export_evidence_bundleReturns 202 Accepted with a bundle_id; the signed download URL
arrives via the evidence_bundle.ready webhook.
Bundle structure
evidence_bundle_<document_id>.zip
├── document.pdf + .sig
├── document.json + .sig
├── template_revision/ (MCTF snapshot with inlined fonts)
├── audit_chain.json + .sig
├── anchors/
│ ├── rekor_records.json
│ └── git_tags.txt
├── signing_keys/ (public-key catalog at bundle time)
├── esra_disclosures.json
├── timestamps/
│ ├── digicert.tsr (RFC 3161)
│ └── freetsa.tsr (RFC 3161, redundancy)
├── chain_signature.bin (KMS Ed25519 over manifest)
├── manifest.json (canonical, signed by chain_signature.bin)
└── verify.sh (court-runnable verifier)Defense-in-depth on tamper detection
Three layers of integrity, any one of which detects tampering:
-
Manifest signature.
chain_signature.binis a KMS-backed Ed25519 signature overcanonical_json(manifest). The manifest maps every file path to its content_sha256. Tampering with the manifest breaks the signature. -
Per-file signatures. Every file in the bundle has a companion
.sigwith its own Ed25519 signature over the file's BYTES (not just its hash). This catches the "tampered ZIP with a forged manifest" attack — a defense round-2 audit flagged as F16. A verifier that only checks the manifest signature passes a fully forged bundle; the per-file.sigmakes that impossible. -
Public anchor records. Every 24h, the audit chain's tip is published to the Sigstore Rekor public transparency log AND tagged in
github.com/matter/audit-anchors. The bundle includes the anchor records covering its audit-chain segment. An insider with KMS access who rewrites the chain still cannot rewrite the external Rekor record — segment substitution is detected by a chain-hash mismatch at the anchor boundary.
RFC 3161 trusted timestamps
A court in 2033 reading a 2026-signed document needs evidence the signature happened on the claimed date — not last week. RFC 3161 timestamps anchor the chain to a third-party trusted timestamping authority at execution time.
Matter fetches tokens from both DigiCert TSA and FreeTSA in
parallel and bundles both. If one TSA becomes untrusted in the future,
the other anchors the chain independently. The bundled verify.sh
script invokes openssl ts -verify against each TSA's public key.
verify.sh
The bundled verifier script does five checks; emits a single
PASS / FAIL line at the end.
#!/usr/bin/env bash
# verify.sh — court-runnable Matter evidence-bundle verifier.
set -e
# 1. Re-hash every file and check against manifest.json's content_sha256 map.
# 2. Verify each <path>.sig with the public key from signing_keys/.
# 3. Verify chain_signature.bin against canonical_json(manifest).
# 4. Walk audit_chain.json's hash chain and compare its tip to
# anchors/rekor_records.json + anchors/git_tags.txt.
# 5. openssl ts -verify timestamps/digicert.tsr (and freetsa.tsr).
echo "PASS — bundle integrity verified"A verifier that doesn't trust Matter can independently confirm the document existed in the claimed state at the claimed time using only public artifacts:
- DigiCert + FreeTSA public TSA roots
- The public Sigstore Rekor log
- The
matter/audit-anchorsgit tag history - The
.well-known/matter-keys.jsonpublished key catalog
GDPR Article 17 + Object Lock
Object Lock Compliance retention forbids deletion of locked objects — even by AWS root credentials within the retention window. Plain implementations make GDPR Article 17 erasure impossible.
Matter's resolution: cryptographic erasure.
- Every restricted-class parameter (SSN, EIN, DOB, bank account, etc.) is wrapped in an AES-256-GCM envelope before persistence.
- The encryption key is per-data-subject and lives in AWS KMS.
- An Article 17 erasure request deletes the KMS key (after a 7-day pending window). The locked S3 object remains — but the restricted parameters inside it become cryptographic noise, irreversible even by AWS.
- The audit-chain hash chain over the bundle bytes is unaffected, because the chain was computed over the encrypted bytes — those haven't changed.
The erasure is logged to the audit chain itself
(cryptographic_erasure_requested → cryptographic_erasure_completed),
so a future court can confirm the erasure happened on the requested
date even though the original parameter is unrecoverable.
See also
- Test-mode safety — distinct key hierarchies for test vs sandbox vs live.
- Render and sign — the flow that produces the bundle.