aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-30 16:58:31 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-30 16:58:31 +0200
commit6d167392f6f8ede37e2794a68a3738f8ba03131d (patch)
tree9caacef15dd034c6425f4bb623e0cd50a28ec52a /packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
parent8926f163dad9d32dc06c3a142658a4e11d9c12c1 (diff)
downloadmeshbay-6d167392f6f8ede37e2794a68a3738f8ba03131d.tar.gz
feat(client): the desktop application keeps M and every node identity in its main process
keyring.js derives, opens, mints, seals, signs and agrees there; the page gets public keys and a handle. Argon2 comes from the page's own WebAssembly build (Electron's crypto has none). Without OS key storage the page keeps its keys as a browser does. A node's bundle is settled after connecting, re-sealed when the key changed. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/keyderive.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/keyderive.js22
1 files changed, 20 insertions, 2 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
index 8f820ec..d847aab 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/keyderive.js
@@ -165,6 +165,24 @@ async function deriveBundleSessionKey(password, username, userId, pepperB64, pep
}
/**
+ * The session's bundle key wherever it is kept. In a browser, derived here. In
+ * the desktop application, derived and kept by its main process, and what
+ * comes back is a handle — `{ native, userId, pepperVersion }` — that opens
+ * nothing by itself: the transport asks the application for what it needs.
+ * `pending`: a passphrase change, held aside until the hub accepts it.
+ */
+async function sessionBundleKey(password, username, userId, pepperB64, pepperVersion,
+ { pending = false } = {}) {
+ const P = typeof window !== 'undefined' && window.MeshBayPlatform;
+ if (P && P.nativeKeys && await P.nativeKeys()) {
+ if (!userId || !pepperB64) throw new Error('the hub did not provide the bundle pepper');
+ await P.keys.deriveSession({ password, username, userId, pepperB64, pepperVersion, pending });
+ return { native: true, userId, pepperVersion: pepperVersion || 1, pending };
+ }
+ return deriveBundleSessionKey(password, username, userId, pepperB64, pepperVersion);
+}
+
+/**
* The key that seals this account's identity on ONE node. A leaked one opens
* that node's bundle and no other.
*/
@@ -428,7 +446,7 @@ async function loginAndRecover(username, password) {
refreshToken: data.refresh_token,
// The pepper rides on the sign-in response, so this costs no extra call;
// it is folded into the key here and not kept.
- bundleKey: await deriveBundleSessionKey(
+ bundleKey: await sessionBundleKey(
password, username, _subOf(data.access_token),
data.bundle_pepper, data.bundle_pepper_version),
};
@@ -457,7 +475,7 @@ window.MeshBayKeys = {
deriveAuthKey,
// The bundle key (docs/MESHBAY_DESIGN.md §3.1, §3.7): one session key per
// sign-in, one derived key per node, one format.
- deriveBundleSessionKey, nodeBundleKey, fetchBundlePepper,
+ deriveBundleSessionKey, sessionBundleKey, nodeBundleKey, fetchBundlePepper,
encryptBundle, decryptBundle, bundleFormat,
// Account recovery key (docs/MESHBAY_DESIGN.md §3.6).
generateRecoveryKey, deriveRecoveryKey,