From ff2d69c67be51b8b019d248eadc944736f1ed624 Mon Sep 17 00:00:00 2001 From: "glm-5.3-flash" Date: Tue, 27 Oct 2026 11:11:42 +0000 Subject: [PATCH] =?UTF-8?q?docs(architecture):=20ADR-002=20amendment=20?= =?UTF-8?q?=E2=80=94=20the=20key-algorithm=20position=20is=20ed25519-only?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - ADR-002 decision 4 retitled and strengthened per review input: not 'rsa off, ed25519-first' but ed25519-only. Rationale recorded: one key algorithm carries the family's identity — same ed25519 keys behind alktls self-signed certs, iroh, and the downstream alknet rewrite (ssh + ed25519, tcp + tls, quic + tls, iroh); legacy schemes (rsa/dsa/ecdsa/sk) are issued, stored, or derived nowhere in the family - operational consequence: auth_publickey declines non-ed25519 keys explicitly (ADR-004's explicit-over-inherited pattern), so the posture survives pin bumps; registration is ed25519-only by family posture, not assembler choice - ADR-004: carries the matching dated amendment note; other dispositions unchanged - auth.md: disposition summary matches (ed25519-only) - research/russh.md: pin-question list marked resolved by ADR-002 Verification: cargo test, cargo clippy --all-targets -- -D warnings, cargo fmt --check — all pass --- docs/architecture/auth.md | 7 +- docs/architecture/decisions/002-russh-pin.md | 76 ++++++++++--------- .../decisions/004-auth-dispositions.md | 6 +- docs/research/russh.md | 3 + 4 files changed, 55 insertions(+), 37 deletions(-) diff --git a/docs/architecture/auth.md b/docs/architecture/auth.md index 13b006b..60cf399 100644 --- a/docs/architecture/auth.md +++ b/docs/architecture/auth.md @@ -39,7 +39,12 @@ verifies a signature; its auth surface is *dispositional* (ADR-004). ### Dispositions (ADR-004 — summarized) -`publickey` is the only implemented method; `auth_publickey_offered` +`publickey` is the only implemented method, and the only accepted key +algorithm is **ed25519** — `auth_publickey` declines non-ed25519 +public keys explicitly (the family's ed25519-only posture, ADR-002 +decision 4; one key algorithm carries the family's identity — the +same ed25519 keys behind alktls's self-signed certs, iroh, and the +alknet rewrite). `auth_publickey_offered` accepts-and-delegates (keeping `max_auth_attempts` honest — the hook does not consume an attempt, POC-1 verified); `auth_none` / `auth_password` / `auth_keyboard_interactive` / `auth_openssh_certificate` diff --git a/docs/architecture/decisions/002-russh-pin.md b/docs/architecture/decisions/002-russh-pin.md index 08cb459..c8ef778 100644 --- a/docs/architecture/decisions/002-russh-pin.md +++ b/docs/architecture/decisions/002-russh-pin.md @@ -1,6 +1,6 @@ --- status: draft -last_updated: 2026-10-26 +last_updated: 2026-10-27 --- # ADR-002: The russh pin — 0.65.0, aws-lc-rs, no compression, ed25519-only @@ -10,9 +10,10 @@ last_updated: 2026-10-26 **Accepted** — 2026-10-26. A one-way door in practice (SSH negotiation behavior crosses crate boundaries; bumps are deliberate, tested, and recorded per the repo's wire-stability convention). Amended same day -after review: the earlier enabling of the `rsa` feature is reverted — -**`rsa` off, ed25519-first** — the family's key-algorithm posture is -the binding constraint, not fleet compatibility. +after review: the earlier enabling of the `rsa` feature is reverted +(`rsa` off). Amended 2026-10-27 (review pass): the key-algorithm +position is **ed25519-only** — the family's posture is the binding +constraint, not fleet compatibility (decision 4). ## Context @@ -57,27 +58,30 @@ goal — and has nothing to do with TLS on the SSH wire. compression is largely pointless at modern link layers and is the CRIME-adjacent attack surface OpenSSH itself defaults off. Bounded-resources and surface-reduction posture agree. -4. **`rsa` off — the family posture is ed25519-first.** Enabling - `rsa` would have bought compatibility for the vanilla-SSH front - door (users bring their own keys, RSA keys exist in the wild) at - the cost of two RC-pinned deps and making alkssh the family's only - RSA-holding crate. Review reverted it: no other family location - uses RSA; the suggested path everywhere else is ed25519; an - algorithm the family doesn't issue, store, or derive anywhere has - no custody story here. Concretely: **the tree drops `rsa - =0.10.0-rc.18` and `pkcs1 =0.8.0-rc.4` entirely** (verified: the - `["aws-lc-rs"]`-only build is clean and RC-free except `ssh-key - =0.7.0-rc.11`, which russh exact-pins on the `russh::keys` path). - Wire behavior of the decline is honest and fail-closed: russh - fails RSA signing explicitly when the feature is absent (0.63.2's - recorded fix), and a client presenting an RSA key gets a clean - `USERAUTH_FAILURE` — never a half-open session. If RSA ever - matters, the amendment is one feature flag plus this ADR. - Assembly-layer note: which key algorithms an assembly accepts at - registration is the assembler's policy (alkforge registers - ed25519; a non-ed25519 registered key would be unauthenticatable - and should be refused at registration, which is also assembly - territory). +4. **ed25519-only — `rsa` off, and no other scheme is supported.** + Amended 2026-10-27 from the earlier "ed25519-first" wording after + review: the position is ed25519-only. One key algorithm carries + the family's identity: the same ed25519 keys serve alktls's + self-signed TLS certificates and iroh, and the downstream alknet + rewrite rides ssh + ed25519, tcp + tls, quic + tls, and iroh — the + same ed25519 identity. The legacy/alternative SSH key schemes + (rsa, dsa; ecdsa variants and hardware-token sk variants share the + defect) are issued, stored, or derived nowhere in the family — + supporting them here would be a wart backed by nothing else. + Enabling `rsa` would additionally have pulled two RC-pinned deps + and made alkssh the family's only RSA-holding crate. Concretely: + **the tree drops `rsa =0.10.0-rc.18` and `pkcs1 =0.8.0-rc.4` + entirely** (verified: the `["aws-lc-rs"]`-only build is clean and + RC-free except `ssh-key =0.7.0-rc.11`, which russh exact-pins on + the `russh::keys` path). Wire behavior is honest and fail-closed: + a client presenting a non-ed25519 key gets a clean + `USERAUTH_FAILURE` — never a half-open session. Operational + shape: alkssh implements no other scheme; an assembly registers + ed25519 fingerprints only; and `auth_publickey` **declines + non-ed25519 keys explicitly** (ADR-004's explicit-over-inherited + pattern applied to the algorithm position, so the posture survives + a pin bump that might otherwise accept more schemes). If a scheme + ever matters, the amendment is one feature flag plus this ADR. 5. **`des` / `dsa` never.** russh's own "Danger: insecure" features — no alkssh configuration may enable them. 6. **Manifest lands with the dependency**: `rust-version = "1.89"` @@ -91,16 +95,18 @@ goal — and has nothing to do with TLS on the SSH wire. with `rsa` off it is **RC-free except `ssh-key =0.7.0-rc.11`** (unavoidable: russh exact-pins it on the `russh::keys` path); MSRV/licensing are explicit. -- **Negative**: vanilla clients holding only RSA keys decline outright - (clean `USERAUTH_FAILURE`) — recorded as intentional; `ssh-key`'s RC - pin rides the russh keys path until russh moves off it; aws-lc-rs is - the heavier build (proven acceptable here, with `ring` as the - recorded fallback). -- **Neutral**: ADR-004's dispositions are signature-agnostic — at - 0.65.0 the key arrives as `VerifiedPublicKey.public_key` and the - new `algorithm` field is available for future hardening (server-side - reaction to client-signature-algorithm choice); no disposition - changes. +- **Negative**: clients presenting non-ed25519 keys (RSA among them) + decline outright (clean `USERAUTH_FAILURE`) — recorded as + intentional; `ssh-key`'s RC pin rides the russh keys path until + russh moves off it; aws-lc-rs is the heavier build (proven + acceptable here, with `ring` as the recorded fallback). +- **Neutral**: at 0.65.0 the key arrives as + `VerifiedPublicKey.public_key` with the client's signature + `.algorithm` exposed; the ed25519-only posture (decision 4) acts on + the key-algorithm fact at `auth_publickey`, and the `.algorithm` + field remains available for further hardening if ever wanted. + ADR-004 carries the matching amendment note; its other + dispositions are unchanged. ## References diff --git a/docs/architecture/decisions/004-auth-dispositions.md b/docs/architecture/decisions/004-auth-dispositions.md index 700bd68..cc87c7e 100644 --- a/docs/architecture/decisions/004-auth-dispositions.md +++ b/docs/architecture/decisions/004-auth-dispositions.md @@ -9,7 +9,11 @@ last_updated: 2026-10-27 **Accepted** — 2026-10-26. Evidence-backed (POC-1 end to end, POC-2's signature-pipeline facts); open to amendment only via a new -ADR. Not a ledger item (no wire format changes), but the decline +ADR. Amended 2026-10-27 (review pass, per ADR-002 decision 4's +ed25519-only amendment): `auth_publickey` additionally declines +non-ed25519 keys explicitly — the key-algorithm posture, not the +fingerprint disposition, changes; all other dispositions stand. Not a +ledger item (no wire format changes), but the decline matrix is contract territory: every decline is tested on both sides of every feature. diff --git a/docs/research/russh.md b/docs/research/russh.md index 9a6692f..1bc08db 100644 --- a/docs/research/russh.md +++ b/docs/research/russh.md @@ -234,6 +234,9 @@ exists but is out of family scope (agent forwarding declines; see ## Open pin questions for the ADR +All resolved by ADR-002 (2026-10-26, amended 2026-10-27); +items below are the questions as phase 0 posed them: + 1. Which family/russh line (current stable 0.64.1 is the default candidate) and whether the RC-pinned `ssh-key`/`rsa`/`pkcs1` tree is acceptable or gates the pin.