summaryrefslogtreecommitdiffstats
path: root/docs/meshbay-draft-v3.md
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-08-09 14:57:01 +0200
committerChristophe Besson <cbesson@gmail.com>2026-08-09 14:57:01 +0200
commit44b9e74153f5e32b3665f319429b3b08fd3662d5 (patch)
treeed5cc7643bc703de248b35cc509ae1d843ff7012 /docs/meshbay-draft-v3.md
parentaed220d9f0bab42efd57b56851319e840ab8ae26 (diff)
downloadmeshbay-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.md33
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).