Skip to content

bin for centralized custodian with security-council epoch-key delivery - #234

Open
daltoncoder wants to merge 12 commits into
seismicfrom
d/centralized-custodian
Open

bin for centralized custodian with security-council epoch-key delivery#234
daltoncoder wants to merge 12 commits into
seismicfrom
d/centralized-custodian

Conversation

@daltoncoder

Copy link
Copy Markdown
Contributor

Adds seismic-centralized-custodian-service, a custodian variant for
centrally operated networks where purpose keys at epochs >= 1 are delivered
by a security council
instead of derived from the root key. A TCP port
(default :7879) accepts delivery envelopes that are ECDSA-signed by a
configured council key and ECIES-encrypted (ECDH + AES-256-GCM) to an inbox
keypair derived from the root key; the existing Unix socket then serves
exactly what has been delivered. Asking for an epoch the council has not
published answers a new typed EpochKeyUnavailable response instead of
deriving on demand — making the council the network's actual rotation
authority (previously any authorized caller could derive any epoch).

How

  • crates/council-delivery (new): wire types, domain-separated binding
    digests (golden-vectored; the signed digest covers the ciphertext so a
    signature can't be re-attached to a re-encryption), and seal_delivery /
    open_delivery. A leaf crate shared with off-node council signer tooling.
  • bin/centralized-custodian-service (new): reuses
    seismic-custodian-service's state/dispatch/acl as a library, so epoch-0
    derivations, the bootstrap trio, LUKS handoff, and --allow grants are
    byte-identical. Adds a sync TCP accept loop (no tokio — the key holder
    stays async-free, verified via cargo tree), a sequential-per-purpose
    EpochKeyStore, and envelope persistence: durable on disk (tmp + fsync +
    rename) before a key becomes observable, re-verified and re-decrypted
    on every boot. Byte-identical redelivery is idempotent; anything else at an
    existing epoch is a conflict. Because /persistent is unlocked by this
    process's own LUKS handoff, the store loads lazily and deliveries are
    refused with retriable codes until it's reachable.
  • Existing crates (small, additive): Key conversion methods +
    KeyPurpose::CouncilInbox in seismic-custodian;
    AesKeyDomain::CouncilKeyDelivery in seismic-crypto;
    Response::EpochKeyUnavailable + client/error mapping in
    seismic-custodian-ipc. bin/custodian-service is untouched.

Testing

60 tests across the touched crates: binding golden vectors, seal/open
rejection matrix (wrong network / recipient / signer, tampered fields,
ciphertext swap), sequencing/idempotency/conflict rules, persist-before-
install, restart-reload, corrupt-file heal-by-redelivery, and a real-socket
end-to-end (deliver over TCP → fetch via CustodianClient on the Unix
socket). cargo fmt --check and RUSTFLAGS="-D warnings" builds are clean.

Follow-ups

  • Optional council-signer CLI in council-delivery (the seal_delivery
    API it wraps is done).
  • seismic-images: systemd unit/user, firewall rule for :7879; optionally a
    tdx-init env writer for SEISMIC_COUNCIL_PUBKEY.

@daltoncoder
daltoncoder requested a review from cdrappi as a code owner August 6, 2026 17:34
@HenryMBaldwin

HenryMBaldwin commented Aug 6, 2026

Copy link
Copy Markdown

can you make a linear issue for this?

@linear-code

linear-code Bot commented Aug 10, 2026

Copy link
Copy Markdown

SEI-155

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants