aboutsummaryrefslogtreecommitdiffstats
path: root/docs/MESHBAY_DESIGN.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/MESHBAY_DESIGN.md')
-rw-r--r--docs/MESHBAY_DESIGN.md17
1 files changed, 8 insertions, 9 deletions
diff --git a/docs/MESHBAY_DESIGN.md b/docs/MESHBAY_DESIGN.md
index 74c1050..23c587e 100644
--- a/docs/MESHBAY_DESIGN.md
+++ b/docs/MESHBAY_DESIGN.md
@@ -638,17 +638,17 @@ Every private key lives in an encrypted keystore on the machine that owns it. Th
hub never sees one.
**Domain separation is consistent and mandatory.** Every derivation uses a
-distinct `info` string, and the AES variant adds an `:aes` suffix so two ciphers
-can never derive the same key from one group key. This is a small detail that
-prevents cross-protocol key reuse, and it is checked rather than assumed.
+distinct `info` string, so no two purposes can derive the same key from one group
+key. The chunk and wrap strings end in `:aes`, left from a second cipher that no
+longer exists; it stays because it is part of every key already derived.
### 4.2 Group key wrapping (ECIES)
```
wrap: sk_eph, pk_eph = X25519.generate() # fresh per bundle
shared = X25519(sk_eph, pk_recipient)
- wrap_key = HKDF(shared, salt=pk_eph, info="meshbay:gek_wrap:v1", len=32)
- wrapped = AEAD(wrap_key).encrypt(nonce, gek, aad=pk_recipient)
+ wrap_key = HKDF(shared, salt=pk_eph, info="meshbay:gek_wrap:v1:aes", len=32)
+ wrapped = AES-256-GCM(wrap_key).encrypt(nonce, gek, aad=pk_recipient)
bundle = pk_eph ‖ nonce ‖ wrapped
unwrap: shared = X25519(sk_recipient, pk_eph) # same derivation
@@ -678,20 +678,19 @@ time. This avoids double storage and makes key rotation feasible without
re-encrypting terabytes.
```
-disk (plaintext) → compress → per-chunk AEAD under a group-derived key → transport → client
+disk (plaintext) → per-chunk AES-256-GCM under a group-derived key → transport → client
```
- Chunk size 1 MB: amortises AEAD overhead and enables seeking, because each chunk
is independently decryptable.
-- `chunk_key = HKDF(GEK, salt=None, info="file:" ‖ blake3(file) ‖ ":chunk:" ‖ index)`.
+- `chunk_key = HKDF(GEK, salt=None, info="file:" ‖ blake3(file) ‖ ":chunk:" ‖ index ‖ ":aes")`.
The salt is omitted deliberately: the group key is CSPRNG output and already
uniform, so the file and chunk context belongs in `info`, which is the correct
HKDF usage (**M5**, first review).
- **Chunk authentication is the AEAD tag**, not a per-chunk signature. The tag
authenticates the ciphertext under a key only members hold, which is what the
signature was for.
-- Compression precedes encryption, because compression is ineffective on
- ciphertext.
+- **Chunks are not compressed**: a chunk is encrypted and sent as it was read.
- Upload chunk size is 48 KB, which is what fits the SCTP limit after msgpack
overhead.