# CROVIA Trust Root *This file is the public root of trust for the Crovia substrate. Any signed Crovia artifact (collector seal, AXIOM envelope, verdict) must verify against the public key declared here. If this file is absent or tampered with in your local checkout, do not trust the signed artifacts you are reading.* --- ## Substrate signing key (current) | Field | Value | |---|---| | Algorithm | Ed25519 | | Key ID | `430895f101d38164` | | Public key (raw, hex) | `cf742e26f75669dc673cb5c0786a1ae23ae8ca19c347317192ce40c28a7ff25c` | | Created at | `2026-04-27T16:48:48Z` | | Hosted at | `/opt/crovia/keys/substrate/{private.pem,public.pem}` (server) | | Status | active | The same public key in PEM form lives at `/opt/crovia/keys/substrate/public.pem` on the production server. Both encodings yield the same Ed25519 verification key — the hex form is the canonical reference for verifiers who do not want to handle PEM. ## Key ceremony record - The keypair was generated by `collectors/seal.py genkey` on 2026-04-27 at the timestamp recorded above. - Generation source of randomness: the system CSPRNG via the `cryptography` library's `Ed25519PrivateKey.generate()`. - The private key never leaves `/opt/crovia/keys/substrate/private.pem` (mode `0600`, owner `root`). - This file (`TRUST_ROOT.md`) is the public commitment of the public key. Its first canonical commit to the Crovia repository is the ceremony witness: any substrate seal whose `sealed_at` precedes that commit is considered pre-trust-root and labelled as such. ## What the key signs The substrate key signs the **canonical bytes of seal payloads** produced by `collectors/substrate_seal.py`. A seal payload covers a Merkle root computed over an append-only JSONL of collector records. This means a single Ed25519 signature attests: 1. The exact set of records that existed in the JSONL at the sealing moment (via the Merkle root). 2. The first and last `receipt_hash` of that set (forensic anchors). 3. The `sealed_at` UTC timestamp recorded at signing time. 4. The `collector_run_id` of the producing run (when applicable). Subsequent seals on the same JSONL form an append-only seal chain. Any retroactive edit of records breaks the next seal in the chain. ## How to verify any signed Crovia artifact ```bash # 1. Fetch the JSONL and its seal companion (both public). curl -O https://croviatrust.com/substrate/wayback/observations.jsonl curl -O https://croviatrust.com/substrate/wayback/observations.jsonl.seal.jsonl # 2. Use the seal CLI shipped in collectors/substrate_seal.py. python3 -m collectors.substrate_seal verify \ --jsonl observations.jsonl \ --seal observations.jsonl.seal.jsonl ``` The verifier: 1. Reads the JSONL line-by-line, parses each line as JSON, computes `sha256(LEAF_PREFIX || canonical_json(record))` for each. 2. Builds a Merkle tree (RFC-style odd-leaf duplication, sha256, `LEAF_PREFIX=0x00`, `NODE_PREFIX=0x01`). 3. Compares the recomputed root with `seal.merkle_root`. 4. Verifies the Ed25519 signature against the public key declared here, over the canonical bytes of the seal payload (excluding the `signature` and `sig_algorithm` fields). If all four checks pass, the seal is valid and the JSONL has not been modified since sealing. ## Bitcoin timestamp anchor (OpenTimestamps) Since 2026-04-27, every substrate seal Merkle root is anchored into the Bitcoin blockchain via [OpenTimestamps](https://opentimestamps.org) calendar servers. The anchor is free, public, decentralized, and verifiable offline by anyone with Bitcoin block headers. | Field | Value | |---|---| | Anchor type | OpenTimestamps over Bitcoin | | Calendar servers | `btc.calendar.catallaxy.com`, `bob.btc.calendar.opentimestamps.org`, `alice.btc.calendar.opentimestamps.org`, `finney.calendar.eternitywall.com` | | Stamp cadence | Weekly (Sunday 03:00 UTC) on the latest ledger seal | | Upgrade cadence | Daily (04:00 UTC) — pending → Bitcoin block proof once confirmed (~1-6 h after stamp) | | Public manifest | `https://croviatrust.com/registry/data/substrate/ots_anchors.json` | | `.ots` proofs | `https://croviatrust.com/registry/data/substrate/anchors/.ots` | ### How to verify the Bitcoin anchor ```bash # 1. Fetch the public manifest to see all anchored seal roots. curl -sS https://croviatrust.com/registry/data/substrate/ots_anchors.json # 2. Pick a Merkle root and fetch its .ots proof. MR= curl -O https://croviatrust.com/registry/data/substrate/anchors/${MR}.ots # 3. Reconstruct the digest file (the 32 raw bytes of the Merkle root) # and verify it. python3 -c "import sys; open('digest.bin','wb').write(bytes.fromhex('$MR'))" ots verify digest.bin # uses ots-client; reads digest.bin.ots ``` If the `.ots` proof has already been upgraded to a Bitcoin block attestation, `ots verify` confirms the timestamp against your local Bitcoin block headers (or a trusted block explorer). If the proof is still pending calendar attestation, `ots upgrade digest.bin` will poll the calendars until Bitcoin confirms the commitment. The substrate signing key signs the seal payload; OpenTimestamps provides an independent timestamp witness rooted in Bitcoin's proof-of-work consensus. Together they answer two distinct questions: - *Who said it?* — answered by the Ed25519 signature against the key declared above. - *When did they say it, demonstrably?* — answered by the OpenTimestamps proof against Bitcoin. Neither answer relies on Crovia's own infrastructure remaining online. ## Key rotation policy - Active keys are listed in the table above. - A retired key is moved into a "Retired keys" section below with its retirement timestamp and reason. Retired keys remain valid for verifying historical seals; they MUST NOT be used to produce new seals. - Rotation requires (a) generating a new keypair via `collectors/substrate_seal.py genkey`, (b) recording the new key in this file, (c) committing the file, (d) rotating the production symlink to point at the new private key. - The Crovia repository commit history of THIS file is the official public timeline of substrate trust. ## Retired keys *(none)* ## The Crovia seal family The substrate signing key declared above is the trust root for ALL artifacts in the **Crovia seal family**. The family is one cryptographic primitive set (Ed25519 + canonical JSON + Merkle + chained issuance) applied to three complementary subjects: | `seal_kind` | Subject | Producer | Status | |---|---|---|---| | `ai_output` | a single AI output (text, code, image, audio) | `crovia-seal/` v0.5 (open standard, IETF draft target) | spec frozen, pre-deployment | | `release_artifact` | a model release manifest (training data hash, weights hash, license bundle) | `crovia-seal/` v1.0 (planned vendor-side release ceremony) | planned | | `substrate_batch` | an append-only JSONL of collector observations | `collectors/substrate_seal.py` | live since 2026-04-27 | They are siblings, not duplicates. A future unification session (`crovia_seal_core`) will extract the shared crypto core into a single library, but the seal payloads of all three already use compatible canonical JSON, the same Merkle conventions (`LEAF_PREFIX 0x00`, `NODE_PREFIX 0x01`, sha256), and the same Ed25519 verification key listed in this document. When Crovia eventually publishes a Seal product release ceremony or an AI-output proxy, those signatures will verify against the same public key declared above. Trust root is one. Subjects are many. --- *Tamper-evidence is only as strong as the public commitment of the verification key. Treat changes to this file with the seriousness of a constitutional amendment.*