Kez/python/README.md
Jason Tudisco d0e96c17fb docs(python): add TUTORIAL.md mirroring rust/nodejs + link from READMEs
Completes the parallel tutorial set across all three implementations.
Python now has the same friendly step-by-step walkthrough that the
Rust and Node sides have had since the original tutorial commits.

Python tutorial content mirrors the others 1:1, adapted for the
Python invocation style (.venv/bin/python kez_cli.py …), plus:

  • Programmatic section uses Python imports (NostrSecret.from_nsec,
    sign_claim, default_registry, etc.) instead of the TS imports
    from the Node tutorial.
  • Same "Recovery phrases" mini-chapter as rust/nodejs — both 12-word
    AND 24-word are explained, with the entropy table, picking guide,
    hardware-wallet-incompatibility callout, concrete backup advice
    ("pencil + paper, numbered words, fireproof, don't split,
    don't permute"), and "Working with phrases later" examples
    (`identity mnemonic`, `identity from-mnemonic`).
  • Notes that `sigchain publish` isn't in the Python CLI yet (only
    add/revoke/show/export) — match the actual current surface; the
    JSONL the Python CLI produces is byte-compatible with Rust/Node,
    so users can build the chain in Python and publish via either
    of the other CLIs in the meantime.
  • Troubleshooting includes ModuleNotFoundError: kez (a Python-
    specific footgun when running outside the venv).
  • Links to ../rust/TUTORIAL.md and ../nodejs/TUTORIAL.md as parallel
    references throughout.

python/README.md now opens with the same "New to KEZ? Read TUTORIAL.md"
callout as the rust and nodejs READMEs do.

Root README's quick-start blocks for each implementation now reference
BOTH the impl README (reference) AND the impl TUTORIAL (step-by-step,
on-ramp) instead of just the README.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-06-05 22:57:52 -06:00

114 lines
4.3 KiB
Markdown

# KEZ — Python Implementation
KEZ is a portable, decentralized identity graph. It lets one person say:
> "These accounts, keys, domains, and identities are all me."
…without depending on any central authority. Every connection is proven by a
signature against a key the user already controls. The protocol is specified in
[`../SPEC.md`](../SPEC.md); this directory is the Python implementation of that
spec.
It is **wire-compatible** with the [Rust](../rust/) and [Node](../nodejs/)
implementations: a claim signed here verifies there and vice versa, in every
direction. The repo-root [`crosstest.sh`](../crosstest.sh) proves it.
---
## What's in this directory
```
python/
├── pyproject.toml Package metadata + entry point (`kez`)
├── requirements.txt Runtime deps (cryptography, zstandard)
├── kez_cli.py Standalone launcher (used by ../crosstest.sh)
└── kez/
├── jcs.py RFC 8785 JSON canonicalization
├── bech32.py Bech32 (nsec/npub) encode/decode
├── schnorr.py Pure-Python BIP-340 Schnorr over secp256k1
├── identity.py `system:identifier` parsing + normalization
├── keys.py NostrSecret / Ed25519Secret signers + verification
├── envelope.py Envelope, claim & sigchain-event payloads, sign/verify
├── encodings.py JSON / compact (kez:z1:) / markdown / DNS / JSONL bundle
├── sigchain.py Append-only signed sigchain + on-disk storage
├── channels.py parse_proof across all four wire encodings
└── cli.py The `kez` command-line interface
```
---
## Setup
> **New to KEZ?** Read [**`TUTORIAL.md`**](TUTORIAL.md) — a friendly
> step-by-step walkthrough that takes you from "I have a nostr `nsec`"
> to "I have a verified, published sigchain," including the BIP-39
> recovery-phrase backup (12 or 24 words). It assumes nothing.
>
> This README is the reference; the tutorial is the on-ramp.
```sh
cd python
python3 -m venv .venv
.venv/bin/pip install -r requirements.txt
```
Then run the CLI either through the launcher or the installed entry point:
```sh
.venv/bin/python kez_cli.py identity new
# or, after `.venv/bin/pip install -e .`:
.venv/bin/kez identity new
```
---
## Crypto stack
| Concern | Choice | Why |
|---|---|---|
| JCS (RFC 8785) | hand-rolled (`jcs.py`) | KEZ payloads are strings/ints/objects only; a tiny dependency-free canonicalizer guarantees byte-identical output |
| secp256k1 Schnorr (BIP-340) | pure-Python reference (`schnorr.py`) | the native `coincurve`/`secp256k1` bindings fail to build on recent CPython; signing fixed-size digests is fast enough for a CLI. Signs with zero aux-rand to match Rust/Node exactly |
| Ed25519 (RFC 8032) | [`cryptography`](https://cryptography.io) | well-maintained, ships wheels |
| zstd | [`zstandard`](https://pypi.org/project/zstandard/) | level 3, matching the other impls; `decompressobj` handles frames without a content-size header |
| Bech32 | hand-rolled (`bech32.py`) | the BIP-173 reference is small and avoids a dependency |
All signing is **deterministic**, so the same claim signs identically every
time.
---
## CLI reference
```
kez identity new [--key-type nostr|ed25519]
kez claim create <subject> (--nsec <nsec> | --ed25519-seed <hex>)
[--format json|compact|markdown] [--out <path>]
kez claim dns <domain> (--nsec <nsec> | --ed25519-seed <hex>)
kez verify file <path>
kez sigchain add <subject> (--nsec | --ed25519-seed) [--proof-url <url>]
kez sigchain revoke <subject> (--nsec | --ed25519-seed)
kez sigchain show [--primary <id> | --nsec | --ed25519-seed]
kez sigchain export [--primary <id> | --nsec | --ed25519-seed]
[--format jsonl|compact] [--out <path>]
```
Sigchain state lives in `~/.kez/sigchains/<primary-with-colons-as-underscores>.jsonl`
— the same paths the Rust and Node CLIs use, so chains built by one are
readable by the others.
---
## What's not done yet
Matching the gap list in [`../rust/README.md`](../rust/README.md), the Python
CLI implements `claim`, `verify file`, and `sigchain add/revoke/show/export`.
Not yet ported: `verify id` channel resolution (network fetch), `sigchain
publish`, and the `rotate`/`add_device` ops.
## License
Dual-licensed under MIT or Apache-2.0.