diff options
| author | Christophe Besson <cbesson@gmail.com> | 2026-08-09 14:57:01 +0200 |
|---|---|---|
| committer | Christophe Besson <cbesson@gmail.com> | 2026-08-09 14:57:01 +0200 |
| commit | 44b9e74153f5e32b3665f319429b3b08fd3662d5 (patch) | |
| tree | ed5cc7643bc703de248b35cc509ae1d843ff7012 /docs/meshbay-draft-v3.md | |
| parent | aed220d9f0bab42efd57b56851319e840ab8ae26 (diff) | |
| download | meshbay-44b9e74153f5e32b3665f319429b3b08fd3662d5.tar.gz | |
docs: update all pointers after keyderive + QE restructure
CLAUDE.md: add QE/ to structure, key modules table, server state reference,
security rule updated (QE/ not keypair files), meshbay.org inventory pointer.
devel-phases.md: add milestones 6.6-6.9 (keyderive, bundle, demo scripts,
QUICKSTART rewrite). 81/81 tests.
docs/meshbay-draft-v3.md §6.1.1: new section documenting 3 key generation
strategies (Argon2id CLI, WebCrypto browser+bundle, keystore file) and the
algorithm mismatch caveat between CLI and web registration paths.
docs/USERGUIDE.md §2 Register+Login: replace "generate and persist before
registering" warning with the two clean strategies (derive_keys_from_password
for CLI, keyderive.js + keypair_bundle for browser). Login response updated
with keypair_bundle field.
hub/models.py + users.py + Alembic migration: keypair_bundle column on User,
stored at registration, returned at login (web clients only).
Co-Authored-By: Claude Sonnet 4.6 (1M context) <noreply@anthropic.com>
Diffstat (limited to 'docs/meshbay-draft-v3.md')
| -rw-r--r-- | docs/meshbay-draft-v3.md | 33 |
1 files changed, 33 insertions, 0 deletions
diff --git a/docs/meshbay-draft-v3.md b/docs/meshbay-draft-v3.md index c327415..6983191 100644 --- a/docs/meshbay-draft-v3.md +++ b/docs/meshbay-draft-v3.md @@ -406,6 +406,39 @@ All private keys stored exclusively on the node (or client device) in the encryp Both `PK_ed25519` and `PK_x25519` are registered with the hub at account creation. The hub exposes them via `GET /v1/users/{username}/pubkeys` so that group admins can wrap GEK bundles for members without any direct contact between nodes. +### 6.1.1 Key Generation Strategies + +Three strategies, depending on client type: + +**A — CLI / native node (Argon2id derivation)** +Keys are derived deterministically from `username + password`: +``` +salt = SHA-256("meshbay:v1:" + username) +seed = Argon2id(password, salt, length=64) +sk_ed25519 = Ed25519.from_private_bytes(seed[:32]) +sk_x25519 = X25519.from_private_bytes(seed[32:]) +``` +Same credentials → same keys on any machine. Password recovery = key recovery. +Implemented in `meshbay_common/keyderive.py::derive_keys_from_password()`. + +**B — Web browser (random keypairs + encrypted bundle)** +Browser generates random keypairs via WebCrypto `generateKey()`, encrypts them +with a PBKDF2-SHA512 derived key, and uploads the encrypted bundle to the hub +alongside the public keys. On subsequent logins, the hub returns the bundle +and the browser decrypts it locally with the password. + +The hub stores `keypair_bundle` (AES-256-GCM ciphertext) — opaque, cannot decrypt it. +Implemented in `static/keyderive.js`. Python side in `keyderive.py::encrypt_keypair_bundle()`. + +**C — Native node with keystore file** +Random keypairs generated once, stored in the Argon2id-encrypted keystore file +(`~/.config/meshbay/keystore.enc`). Standard operating mode for `meshbay-node`. + +**Algorithm mismatch note:** strategies A and B use different KDFs (Argon2id vs PBKDF2). +A user who registered via CLI (A) and later tries to recover via web (B) with the same +password will get different keypairs. This is by design: users pick one registration path. +Cross-path recovery requires the admin to issue new GEK bundles. + ### 6.2 GEK Management **Scope:** GEK applies to private groups only. Public groups use TLS transport only (no application-layer encryption). |