Add a Python port of the KEZ CLI under python/, mirroring the Rust and Node implementations command-for-command and byte-for-byte: - Pure-Python JCS (RFC 8785), BIP-340 Schnorr, and Bech32; cryptography for Ed25519 and zstandard for the compact zstd framing. - Full CLI: identity new, claim create/dns, verify file, and sigchain add/revoke/show/export. Wire Python into crosstest.sh with 35 new scenarios covering Python against both Rust and Node, in every direction, across all wire formats, both key types, DNS proofs, and sigchains (incl. JSONL byte parity). All 55 scenarios pass. Update root README and .gitignore for the new implementation.
143 lines
5.4 KiB
Markdown
143 lines
5.4 KiB
Markdown
# KEZ
|
||
|
||
KEZ is a portable, decentralized identity graph. It lets a person say:
|
||
|
||
> "These accounts, keys, domains, and identities are all me."
|
||
|
||
…without depending on any central authority. Every connection is proven by a
|
||
cryptographic signature against a key the user already controls (a nostr key,
|
||
an Ed25519 key, etc.), and the proofs are published in places only the
|
||
claimed account itself can publish to (their gist, their DNS, their nostr
|
||
relay event). Anyone can verify the graph without trusting a server.
|
||
|
||
## Repository layout
|
||
|
||
```
|
||
.
|
||
├── SPEC.md ← The protocol. Language-agnostic, normative.
|
||
├── rust/ ← Rust implementation (kez-core, kez-channels, kez-cli)
|
||
├── nodejs/ ← TypeScript/Node implementation (same shape, same CLI)
|
||
├── python/ ← Python implementation (same shape, same CLI)
|
||
├── rust-sig-server/ ← Optional HTTP store for sigchains (axum + SQLite)
|
||
├── crosstest.sh ← Interop test: artifacts move between implementations
|
||
└── README.md ← (this file)
|
||
```
|
||
|
||
Three parallel implementations. **Wire-compatible**: a claim signed in Rust
|
||
verifies in Node and Python and vice versa, in every direction. The cross-test
|
||
harness proves it.
|
||
|
||
A separate [`rust-sig-server/`](rust-sig-server/) crate provides an optional
|
||
HTTP storage tier for sigchains — useful when a user doesn't want to set up
|
||
DNS/hosting/nostr, but **never required**; the protocol stays decentralized.
|
||
|
||
## Documentation
|
||
|
||
Start here:
|
||
|
||
- [**`SPEC.md`**](SPEC.md) — the language-agnostic protocol spec (v0.2).
|
||
Normative for every implementation.
|
||
- [**`rust/README.md`**](rust/README.md) — Rust implementation guide:
|
||
crate layout (`kez-core` / `kez-channels` / `kez-cli`), full CLI
|
||
reference, channel plugin model, library examples, and the gap list.
|
||
- [**`nodejs/README.md`**](nodejs/README.md) — Node/TypeScript port:
|
||
same shape as Rust, npm workspaces layout, crypto stack rationale,
|
||
CLI reference.
|
||
- [**`python/README.md`**](python/README.md) — Python port: single
|
||
`kez` package, virtualenv setup, crypto stack rationale (pure-Python
|
||
BIP-340 Schnorr + `cryptography` for Ed25519), CLI reference.
|
||
- [**`rust-sig-server/README.md`**](rust-sig-server/README.md) — the
|
||
optional storage server: API reference, no-auth design + threat
|
||
model, deployment recipes (bare-metal, Docker, PaaS), and how
|
||
channel-based publishing remains the fallback if the server is down.
|
||
|
||
## Quick start
|
||
|
||
### Rust
|
||
```sh
|
||
cd rust
|
||
cargo build
|
||
cargo test # 99 tests
|
||
cargo install --path crates/kez-cli # → `kez` on PATH
|
||
kez verify id github:jason
|
||
```
|
||
Full guide: [`rust/README.md`](rust/README.md).
|
||
|
||
### Node.js
|
||
```sh
|
||
cd nodejs
|
||
npm install
|
||
npm test # 91 tests
|
||
npm run cli -- verify id github:jason
|
||
```
|
||
Full guide: [`nodejs/README.md`](nodejs/README.md).
|
||
|
||
### Python
|
||
```sh
|
||
cd python
|
||
python3 -m venv .venv
|
||
.venv/bin/pip install -r requirements.txt
|
||
.venv/bin/python kez_cli.py identity new
|
||
```
|
||
Full guide: [`python/README.md`](python/README.md).
|
||
|
||
### Sigchain storage server (optional)
|
||
```sh
|
||
cd rust-sig-server
|
||
cargo build --release
|
||
./target/release/kez-sig-server # listens on :7878
|
||
```
|
||
Full guide: [`rust-sig-server/README.md`](rust-sig-server/README.md).
|
||
|
||
## Cross-testing
|
||
|
||
```sh
|
||
./crosstest.sh
|
||
```
|
||
|
||
Runs 55 scenarios that swap implementations at the artifact boundary:
|
||
|
||
| # | Scenarios |
|
||
|---|---|
|
||
| 1–14 | Rust ↔ Node: JSON / compact / markdown / DNS claims, nostr + ed25519 |
|
||
| 15–20 | Rust ↔ Node sigchains: build in one, parse + show in the other; JSONL byte parity |
|
||
| 21–44 | **Python ↔ Rust and Python ↔ Node** claims: every format × key type, both directions |
|
||
| — | Python ↔ both peers DNS zone form, both directions |
|
||
| — | Python ↔ both peers sigchains: build/show both ways, JSONL byte parity, ed25519 |
|
||
|
||
If all 55 pass: JCS canonicalization, both signature suites (BIP-340 Schnorr
|
||
and Ed25519), the compact `kez:z1:` zstd+base64url encoding, the Markdown
|
||
fence, the DNS TXT shape, and the sigchain JSONL bundle format are all
|
||
byte-compatible across all three implementations.
|
||
|
||
Pass `-v` for verbose output (echoes intermediate commands and proofs).
|
||
|
||
## What ships in v0.2
|
||
|
||
- **Five channel plugins** in each implementation: `dns:`, `github:`,
|
||
`nostr:`, `bluesky:`, `ap:` (alias `mastodon:`).
|
||
- **Four wire encodings**: JSON, compact, Markdown fence, DNS TXT.
|
||
- **Two primary-key algorithms**: nostr/secp256k1 Schnorr (BIP-340) and
|
||
Ed25519 (RFC 8032).
|
||
- **JCS (RFC 8785)** canonicalization for everything signed.
|
||
- **No API keys required for any channel.**
|
||
|
||
## What's not done yet
|
||
|
||
Tracked in [`rust/README.md`](rust/README.md#whats-not-done-yet) and the
|
||
spec:
|
||
|
||
- **`verify id` consulting the sigchain.** Sigchain types, CLI commands
|
||
(`kez sigchain add/revoke/show/export/publish`), and the storage server
|
||
all exist. But proof verification doesn't yet fetch the chain to check
|
||
for revocations — every `verify` is still a single one-shot proof check.
|
||
- `rotate` and `add_device` sigchain ops.
|
||
- `expires_at` enforcement during claim verify.
|
||
- Typed `VerificationStatus.status` reflecting the five failure modes
|
||
(`valid` / `revoked` / `expired` / `unreachable` / `fork`).
|
||
- Auth-required publishers (GitHub gist, Bluesky, ActivityPub).
|
||
|
||
## License
|
||
|
||
Dual-licensed under MIT or Apache-2.0.
|