From 91297944791a36f30302ef8c86dd69ebeb177671 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Wed, 30 Sep 2026 15:06:14 +0200 Subject: 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 --- .../meshbay-hub/src/meshbay_hub/static/profile-page.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/profile-page.js') diff --git a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js index d3d06d7..7a309a9 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/profile-page.js @@ -141,10 +141,18 @@ export function ProfilePage({ user, onLogout }) { try { // Re-wrap every reachable node's identity bundle first — if this cannot // run at all the account is left untouched. + // Both keys from the passphrases, with the pepper this open session asks + // for: the old one opens the bundles as they are, the new one seals them. + const K = window.MeshBayKeys; + const { pepper, version } = await K.fetchBundlePepper(user.token); + const oldKey = await K.deriveBundleSessionKey( + cpOld, user.username, user.userId, pepper, version); + const newKey = await K.deriveBundleSessionKey( + cpNew, user.username, user.userId, pepper, version); const result = await window.MeshBayTransport.rewrapAllNodes({ hubUrl: HUB, token: user.token, username: user.username, userId: user.userId, - oldPassphrase: cpOld, newPassphrase: cpNew, + bundleKey: oldKey, newBundleKey: newKey, onProgress: setCpProgress, }); @@ -158,8 +166,8 @@ export function ProfilePage({ user, onLogout }) { // Keep this tab signed in with the fresh pair, and move the session's // bundle key forward so the next node connection opens the new bundles. setAuth({ ...user, token: resp.access_token, refreshToken: resp.refresh_token }); - session.bundleKey = result.newBundleKey; - _storeBundleKey(result.newBundleKey); + session.bundleKey = newKey; + _storeBundleKey(newKey); setCpResult(result); setCpPhase('done'); -- cgit v1.2.3