# Long-Term Verification & Crypto Agility

Status: **RESEARCH**. This note describes design directions for keeping
receipts verifiable across multi-decade horizons and across a possible
Ed25519 → post-quantum migration. No implementation ships in this pass.

## 1. Historical key model

A production trust bundle
(`OFFLINE_VERIFICATION_SPEC.md` §Trust bundle format) records every
signing key an issuer has used, with:

- `key_id`
- `algorithm`
- `public_key`
- `fingerprint`
- `valid_from`, `valid_to`
- `status`: `active` | `retired` | `revoked`
- `rotation_notes` (human-readable)
- optionally, a `superseded_by: key_id` link

The verifier selects the key whose issuance window covers the receipt's
`timestamp`. Multiple active keys are allowed (e.g., during a
staggered rotation).

### Revocation semantics

A revocation entry in the trust bundle carries:

```jsonc
{
  "key_id": "sig-2026-01",
  "effective_from": "2028-04-14T12:00:00Z",
  "reason": "operator-suspected-compromise",
  "affects_signatures_before_effective_from": "advisory"
                                          | "hard_fail"
                                          | "hard_fail_with_reason_code"
}
```

Rationale for the choice:

- `advisory` (default): a signature produced before the revocation
  effective time is not automatically invalidated. The verifier reports
  "signed with a key later revoked" as a warning, not as a hard failure.
- `hard_fail`: some deployments will want a compromised key to
  invalidate all past signatures. This is a policy choice, not a
  cryptographic one, and it must be explicit.

The verifier respects `--strict-revocation` on the CLI to force
`hard_fail` regardless of the bundle's declared mode.

Retroactive invalidation is a policy statement about trust, not a
statement about the cryptographic soundness of a specific signature. The
codebase must not conflate the two.

### Publication

The reference node exposes (DOCUMENTED):

- `GET /.well-known/signatrust/discovery.json` — current active key
  (already implemented).
- `GET /.well-known/signatrust/trust-bundle.json` — full historical
  bundle in `signatrust-trust-bundle-v1` format (planned; wired in a
  follow-up).

Deployments must persist trust bundles independently of the running
service. Once the service disappears, only previously-fetched bundles
remain authoritative.

## 2. Trusted time — options and trade-offs

The `timestamp` field in a receipt is **issuer-asserted**. No independent
wall-clock proof exists today. Options:

### 2a. RFC 3161 timestamp authority (TSA)

- **How**: after sealing, request a TSA-signed token over `receipt_hash`.
  Store the token alongside the receipt or in a companion attestation
  receipt.
- **Trust assumptions**: trust in the TSA operator; TSA availability at
  seal time.
- **Privacy**: TSA sees the receipt hash only, not content.
- **Cost**: small per-receipt latency + optional TSA fee.
- **Long-term**: relies on the TSA still being verifiable years later,
  which historically has been the case for well-known TSAs.

### 2b. Public transparency log

- **How**: append `receipt_hash` (or a Merkle-tree root of a batch) to
  a public transparency log (Certificate-Transparency-style Merkle log,
  or a domain-specific equivalent). Retain the inclusion proof.
- **Trust assumptions**: the log's operator + auditors follow their own
  protocol; the log's data is retrievable years later.
- **Privacy**: only hashes leak.
- **Long-term**: strongest independent time guarantee if the log's
  ecosystem is well-maintained.

### 2c. Periodic signed checkpoint

- **How**: the issuer signs a checkpoint at fixed intervals (e.g.,
  daily) containing the ledger head and its timestamp. Auditors archive
  checkpoints. A receipt at sequence N is provably not later than the
  first checkpoint that includes sequence N.
- **Trust assumptions**: the checkpoint is distributed to independent
  archivers (email, git, media).
- **Privacy**: excellent — only the head hash leaves.
- **Long-term**: depends on archivers retaining checkpoints.

### 2d. Public ledger anchor

- **How**: periodically anchor the ledger head (only the head hash) to
  a public blockchain or similar public data store. Retain the anchor
  transaction id.
- **Trust assumptions**: the public network remains operational and
  historical data remains retrievable.
- **Privacy**: only the head hash leaves.
- **Cost**: gas / fees + throughput management.

### Recommendation

For a first pilot, **2c (periodic signed checkpoint)** is the lowest
friction and privacy-safe. **2a (RFC 3161)** is the strongest per-receipt
guarantee. **2b/2d** are open research; do not require them.

## 3. Crypto agility

Ed25519 is the current signature primitive. For long-term evidence
(decade-plus retention), plan for algorithm migration.

### Design principles

- **Algorithm identifiers versioned**: the `signature.algorithm` field
  is `"ed25519"` today; future values (`"ml-dsa-65"`,
  `"ed25519+ml-dsa-65"` for hybrid) must be added additively.
- **Multi-key**: an issuer may run multiple active keys concurrently
  (e.g., Ed25519 and an ML-DSA hybrid signature over the same
  `receipt_hash`), each entry recorded in the trust bundle.
- **Hybrid signatures**: for new receipts, sign under two algorithms
  simultaneously and record both signatures. A future verifier can
  drop the older algorithm if it becomes suspect, without invalidating
  the receipt.
- **Re-attestation**: for archival-critical receipts, an issuer may
  produce an Attestation Receipt that re-signs the historical
  `receipt_hash` under a new algorithm. This does not change the
  historical receipt; it adds evidence that a modern trust anchor also
  binds the same hash.

### Migration steps (not shipped, plan only)

1. Add optional `signatures: SignatureEnvelope[]` alongside the current
   singular `signature` field, additive and backward compatible; keep
   `signature` populated with the primary algorithm.
2. Introduce a hybrid signing profile in the SDKs that emits both.
3. Publish an updated trust bundle format
   (`signatrust-trust-bundle-v2`) that permits multi-algorithm keys.
4. Update the offline verifier to accept multi-signature receipts and to
   report per-algorithm results.
5. Retain Ed25519 as a required verification algorithm for at least the
   life of any receipts that were signed with it — never remove the
   check for historical signatures.

### Non-claims

- No claim that current receipts are post-quantum safe.
- No claim that adding a hybrid signature backdates any protection to
  older receipts. Older receipts remain Ed25519-only; the hybrid path
  applies from adoption forward.

## 4. Archival timestamp model

For deployments that expect receipts to be reviewed decades later:

- Store the receipt + its trust bundle + hashing profile in a
  content-addressed archive.
- Periodically **re-timestamp** the archive: request a fresh RFC 3161
  token over `sha256(archive-manifest)` at a chosen cadence.
- On any cryptographic-primitive migration, add a new timestamp under
  the new algorithm alongside the older one, never replacing it.

This is standard archival-signature practice; it does not require any
change to the current wire format.

## 5. Explicit non-claims

- Ed25519 receipts are not post-quantum safe.
- Adding a hybrid signature scheme in the future does not retroactively
  protect old receipts.
- Trusted time is issuer-asserted today. Any external anchoring is
  future work.
- Retroactive revocation is a policy statement, not a cryptographic
  invalidation.
