CI / cargo fmt (push) Canceled after 0s
CI / cargo clippy (macos-latest) (push) Canceled after 0s
CI / cargo clippy (ubuntu-latest) (push) Canceled after 0s
CI / cargo clippy (windows-latest) (push) Canceled after 0s
CI / cargo test (macos-latest) (push) Canceled after 0s
CI / cargo test (ubuntu-latest) (push) Canceled after 0s
CI / cargo test (windows-latest) (push) Canceled after 0s
CI / cargo build (macos-latest) (push) Canceled after 0s
CI / cargo build (ubuntu-latest) (push) Canceled after 0s
CI / cargo build (windows-latest) (push) Canceled after 0s
CI / cargo build --release (macos-latest) (push) Canceled after 0s
CI / cargo build --release (ubuntu-latest) (push) Canceled after 0s
CI / cargo build --release (windows-latest) (push) Canceled after 0s
CI / CLI smoke (macos-latest) (push) Canceled after 0s
CI / CLI smoke (ubuntu-latest) (push) Canceled after 0s
CI / CLI smoke (windows-latest) (push) Canceled after 0s
CI / Minimal E2E (macos-latest) (push) Canceled after 0s
CI / Minimal E2E (ubuntu-latest) (push) Canceled after 0s
CI / Minimal E2E (windows-latest) (push) Canceled after 0s
Connection keys are now a ~49-char seed (rtun3.) instead of a bundled ~1740-char certificate blob. Both endpoints deterministically derive an identical Ed25519 CA from the seed and mint ephemeral server/client leaves at startup (keyderive.rs); the app-layer auth token is derived from the seed. Target is passed separately on connect (resocks-style). - connkey.rs: rtun3 seed parse/format - keyderive.rs: CA/server/client/token derivation - keygen takes no args; connect requires --target - remove miniz_oxide; TLS layer unchanged - add determinism + key-based e2e + wrong-seed-rejected tests - update wiki, README, design spec, CI smoke
77 lines
3.2 KiB
Markdown
77 lines
3.2 KiB
Markdown
# Connection Keys as Seeds (rtun3) — Design
|
|
|
|
## Goal
|
|
|
|
Replace the bundled-certificate connection key (rtun1/rtun2, ~1740 chars) with a
|
|
**~49-char seed key**. No certificates are ever shipped; both endpoints derive an
|
|
identical CA from the seed and mint ephemeral leaf certs locally. Target is passed
|
|
separately on `connect` (resocks-style). App-layer auth token is derived from the
|
|
seed. Supersedes the rtun2 compression work entirely.
|
|
|
|
Motivation: the connection key should be trivial to copy/paste. Compression could
|
|
only halve the size; seed-derivation (as in resocks/kbtls) makes it ~35x smaller.
|
|
|
|
## Format
|
|
|
|
```
|
|
rtun3.<base64url(32-byte seed)>
|
|
```
|
|
|
|
- Parse accepts only the `rtun3.` prefix; `rtun1.`/`rtun2.` are rejected.
|
|
- Payload must decode to exactly 32 bytes; all-zero seed is rejected.
|
|
- `keygen` now takes no arguments — it just prints a fresh seed key.
|
|
|
|
## Derivation (keyderive.rs)
|
|
|
|
Deterministic and identical on both endpoints (same seed → same result):
|
|
|
|
- **CA**: Ed25519 keypair from the seed (`Seed PKCS#8` → rcgen `KeyPair`), self-signed
|
|
with fixed serial/CN/validity. Ed25519 signatures are deterministic, so both sides
|
|
produce the **byte-identical CA**.
|
|
- **Server leaf** (at `listen`): fresh random Ed25519 key signed by the derived CA,
|
|
SANs = localhost/rustunnel/127.0.0.1 + bind IP + optional `--advertise` host.
|
|
- **Client leaf** (at `connect`): fresh random Ed25519 key signed by the derived CA.
|
|
- **Auth token**: `sha256(seed || "rustunnel-auth-token")` → first 16 bytes hex.
|
|
|
|
Derived PEM strings feed the existing `build_server_config_from_pem` /
|
|
`build_client_config_from_pem` builders — the TLS layer is unchanged.
|
|
|
|
## Command changes
|
|
|
|
- `keygen`: `rustunnel keygen` → prints `rtun3.<seed>`. Removed `--target` and the CN
|
|
flags (they only shaped bundled certs).
|
|
- `connect`: `--target` is now required (there is no target in the key).
|
|
- `listen --connection-key $KEY`: decode seed → derive server material + token.
|
|
- Auto path (no certs/no key): generate fresh seed, print key + connect hint.
|
|
- File-based mTLS (`generate --out`, `--cert/--key/--ca-cert`, `--auth-token`) unchanged.
|
|
|
|
## Files
|
|
|
|
| File | Change |
|
|
| ---- | ------ |
|
|
| `Cargo.toml` | Remove `miniz_oxide` (no direct `ring` dep needed; rcgen provides crypto) |
|
|
| `src/connkey.rs` | Rewrite: seed key parse/format (rtun3) |
|
|
| `src/keyderive.rs` | New: CA/server/client/token derivation |
|
|
| `src/redact.rs` | `is_connection_key` detects `rtun3.` |
|
|
| `src/main.rs` | Rework listen/connect/keygen seed flow |
|
|
| `src/tunnel.rs` | Add key-based e2e tests |
|
|
|
|
## Testing
|
|
|
|
- Seed round-trip, format, reject bad/length/zero/rtun1/rtun2.
|
|
- Determinism: same seed → identical CA + token; different seed → different.
|
|
- Server/client material share the same CA.
|
|
- Key-based e2e: derived material establishes an mTLS tunnel with no files.
|
|
- Wrong-seed connector is rejected even with the correct token.
|
|
- Redaction prefix tests.
|
|
|
|
## Docs
|
|
|
|
Update wiki (`connection-keys.md`, `data-models.md`, `glossary.md`,
|
|
`rustunnel-cli.md`, `getting-started.md`, `security.md`,
|
|
`patterns-and-conventions.md`, `dependencies.md`, `overview/index.md`) and README.
|
|
|
|
## Out of scope
|
|
|
|
- File-based mTLS, `insecure_skip_tls_verify`, performance tuning, key registry.
|