aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-30 15:06:14 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-30 15:06:14 +0200
commit91297944791a36f30302ef8c86dd69ebeb177671 (patch)
tree568188114baf438059458f1bc87903f4894cec90 /packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js
parenta55d40b74bda77dff6ec565abdd551607fc665d6 (diff)
downloadmeshbay-91297944791a36f30302ef8c86dd69ebeb177671.tar.gz
feat: bundles sealed per node under the passphrase and the hub's pepper
The session key is M = HKDF(Argon2(passphrase) || pepper, account id); each node's bundle key and the playlist key derive from it. Bundles are MBK3, bound to account and node; MBK1/MBK2 are refused by name, never replaced silently. Playlists move to key v2 and are re-sealed over unreadable node copies. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js16
1 files changed, 9 insertions, 7 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js b/packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js
index 0f41d1e..6323b96 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/playlist-crypto.js
@@ -47,21 +47,23 @@ const PAD_TO = 4096;
const NONCE_BYTES = 12;
/**
- * The playlist key, from the HKDF handle over the bundle key.
+ * The playlist key, from the session's bundle master key `M`
+ * (keyderive.js `deriveBundleSessionKey`).
*
- * A purpose-separated subkey rather than the bundle key reused with a different
+ * A purpose-separated subkey rather than a bundle key reused with a different
* AAD — the rule `groupbox.py` writes down for chunk keys, for the same reason.
- * v2 only: playlists are new, so there is no legacy blob and no v1 branch to
- * take by mistake.
+ * `v2`: the v1 key came from the passphrase alone, so a blob sealed under it
+ * was a second offline oracle for the passphrase on every node. Such a blob no
+ * longer opens, and the local copy is sealed again over it (playlists.js).
*/
-async function derivePlaylistKey(hkdfHandle) {
+async function derivePlaylistKey(masterKey) {
return crypto.subtle.deriveKey(
{
name: 'HKDF', hash: 'SHA-256',
salt: new Uint8Array(0),
- info: new TextEncoder().encode('meshbay:playlists:v1'),
+ info: new TextEncoder().encode('meshbay:playlists:v2'),
},
- hkdfHandle, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
+ masterKey, { name: 'AES-GCM', length: 256 }, false, ['encrypt', 'decrypt']);
}
/**