specify selective disclosure and anchor policy
Some checks failed
CI / fmt, clippy, docs (push) Failing after 5s
CI / test (ubuntu-latest) (push) Failing after 5s
CI / iroh integration smoke tests (push) Failing after 5s
CodeQL / Analyze Rust (push) Failing after 4s
Security / RustSec cargo-audit (push) Failing after 5s
CI / test (macos-latest) (push) Has been cancelled
CI / test (windows-latest) (push) Has been cancelled

This commit is contained in:
Eric Wendland 2026-07-18 22:05:57 +02:00
commit 76eb785ee2
11 changed files with 834 additions and 387 deletions

View file

@ -11,9 +11,9 @@ authorization, and OpenSSH `allowed_signers` projection.
[`sshsigchain.md`](sshsigchain.md) specifies SSHSIGCHAIN, the only portable
signed-chain format in this repository. It is deliberately separate from the
current local keychain operation log: SSHSIGCHAIN starts with an explicit
out-of-band trust tuple, has a strict sequence and hash link, and never uses a
downloaded `allowed_signers` file as a trust root. The previous test-only
static JSONL publication format was removed.
out-of-band trust tuple, uses exact parent hashes without a sequence counter,
and never uses a downloaded `allowed_signers` file as a trust root. The previous
test-only static JSONL publication format was removed.
## Local keychain model
@ -56,28 +56,36 @@ key in the previously accepted local view verifies over the canonical payload.
This is useful for the local Iroh-synchronized operation log, but it is not a
portable SSHSIGCHAIN history and MUST NOT be presented as one.
## SSHSIGCHAIN keychain profile
## SSHSIGCHAIN authority and profiles
Geth's SSHSIGCHAIN profile identifier is `geth.keychain.sshsigchain.v1` and its
SSHSIG namespace is `sshsigchain.v1`. Its canonical binary payload is a
versioned mirror of a keychain operation; it is separate from the
human-facing, internally tagged JSON API type so a decoder can prove one unique
payload encoding.
SSHSIGCHAIN uses the `sshsigchain.v1` SSHSIG namespace. Device/key management is
not a geth-specific profile: the mandatory Authority v1 reducer defines genesis,
device add/revoke, key add/revoke, proof-of-possession, scoped and delegable
permissions, device permission ceilings, anchor-policy changes, and no-op links.
Authority is always public and evaluated from the exact parent state. The root
key seeds authority only at genesis and can later be causally revoked.
The profile requires:
Applications attach profile-ID-scoped commitments. A fresh 32-byte nonce salts
each payload commitment so a withheld small value is not directly vulnerable to
dictionary guessing. A disclosure can be added to or removed from transport
without changing the SSH signature or record hash. Hidden application data can
never alter devices, keys, permissions, or anchor policy. Verification without
all disclosures remains useful for authority, but affected application profile
state is reported as incomplete.
- sequence zero to be `KeychainInit` signed by the operator-pinned root key;
- sequence one to be an `AdminKeyAdd` recording that root key;
- every following signer to be an active admin key in the causally prior
profile state;
- every keychain operation ID to occur only once in the chain;
- each added admin key to have canonical key material matching its declared key
fingerprint; and
- causal add/revoke records rather than validity windows or payload timestamps
as authorization policy.
Keys receive direct permissions such as `DeviceAdd`, `KeyAddSelf`,
`ManagePermissions`, `AnchorAttest`, and `ProfileWrite(<profile>)`. An attached
key cannot exceed its device ceiling, and it cannot grant a permission outside
its delegable set. Newly added keys must sign the exact proposed key/device/
permission binding under `sshsigchain.key-proof.v1`.
The root key seeds authorization at genesis only. A causally valid revocation
removes it like any other admin key.
Head claims are separately signed by an active `AnchorAttest` key. An authority
anchor policy names weighted/required attesting keys plus backend IDs, classes,
locators, weights, required backends/classes, and a separate backend threshold.
Adapters verify backend-specific receipts, while the core
rejects rollback behind a cached head and incomparable histories. Backends do
not decide which history is canonical. The head that changes anchor policy is
witnessed under the previous policy.
To inspect an SSHSIGCHAIN JSONL transport file, pin the chain ID and root public
key locally:
@ -89,11 +97,11 @@ geth keychain verify-sigchain \
--root-key ~/.ssh/geth-root.pub
```
This verifier is experimental while geth adds its own record creation,
publication, import, accepted-head persistence, and independently generated
wire vectors. Those later workflows must preserve the same explicit trust
tuple; they must not introduce a compatibility route for the removed static
format.
This verifier is experimental while geth adds record creation, publication,
import, accepted-head persistence, concrete anchor adapters, and independently
generated wire vectors. Those later workflows must preserve the same explicit
trust tuple and Authority v1 semantics; they must not introduce a compatibility
route for the removed static format.
## Local commands