make sshsigchain the only portable sigchain format

This commit is contained in:
Eric Wendland 2026-07-18 21:00:06 +02:00
commit 73500e1944
15 changed files with 812 additions and 1603 deletions

View file

@ -634,41 +634,33 @@ geth keychain sign-file \
geth keychain verify-file \
--in /tmp/authorized_keys \
--signature /tmp/authorized_keys.sig
geth keychain sigchain --out /tmp/geth.sigchain.jsonl
geth keychain publish-bundle \
--out ./public/.well-known/sshsigchain \
--signing-key ~/.ssh/id_ed25519_sk \
--snapshot authorized_keys=/tmp/authorized_keys
geth keychain verify-checkpoint \
--checkpoint /tmp/geth.sigchain.checkpoint.json \
--signature /tmp/geth.sigchain.checkpoint.json.sig \
--sigchain /tmp/geth.sigchain.jsonl \
--allowed-signers /tmp/geth.allowed_signers
geth keychain fetch --url https://example.com/.well-known/sshsigchain/ --import
geth keychain verify-sigchain --in /tmp/geth.sigchain.jsonl
geth keychain import-sigchain --in /tmp/geth.sigchain.jsonl
geth keychain explain <op-id>
geth keychain explain-signer <key-id>
geth keychain verify
```
The keychain follows a sigchain model documented in
`docs/sigchain-keychain.md`: each keychain operation is accepted only if it is
signed by an admin key from the previously accepted reduced view. This is the
geth analogue of verifying `git-skm` allowed-signers changes from a prior
trusted state. The reusable mechanics live in the `geth-keychain` crate,
including application-specific signature profiles, allowed-signers projection,
replay verification through a caller-provided verifier trait, and an appendable
JSONL sigchain file format suitable for static hosting with HTTP caching/range
requests. The default discovery/publication base is
`https://example.com/.well-known/sshsigchain/`; publish bundles contain
`allowed_signers`, `geth.sigchain.jsonl`, `geth.sigchain.checkpoint.json`, and
`geth.sigchain.checkpoint.json.sig`. Clients can verify checkpoints, fetch
bundles, import verified sigchains, and remember the last accepted checkpoint to
reject older static bundles from the same source. `keychain fetch --url` is the
retrieval location, so local `file://` mirrors work for testing; the signed
checkpoint still records the advertised publication base URL, and
`verify-checkpoint --base-url` can pin that value when needed.
The previous test-only static sigchain commands (`sigchain`, `publish-bundle`,
`import-sigchain`, `verify-checkpoint`, and `fetch`) were removed. Their
downloaded `allowed_signers` projection could establish the trust that
validated its own chain. There is no compatibility mode for that workflow.
The replacement is the small, transport-neutral
[`SSHSIGCHAIN v1`](docs/sshsigchain.md) specification. It starts from an
operator-pinned chain ID, OpenSSH root public key, profile, and namespace;
records are fixed-byte SSHSIG payloads linked by sequence and digest. Geth
already provides a verifier for independently produced JSONL transport files:
```sh
geth keychain verify-sigchain \
--in ./geth.sshsigchain.v1.jsonl \
--chain-id <64-hex-character-chain-id> \
--root-key ~/.ssh/geth-root.pub
```
SSHSIGCHAIN local record storage, signing, publication, import, and accepted-head
persistence remain follow-up work. Until they exist, do not substitute an
unpinned checkpoint or a local operation-log view for the SSHSIGCHAIN trust
tuple.
Signing is mediated by OpenSSH. `--signing-key` may point at a private key file,
a FIDO/YubiKey OpenSSH security-key stub, or a public key whose private half is