summaryrefslogtreecommitdiffstats
path: root/packages
diff options
context:
space:
mode:
Diffstat (limited to 'packages')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/app.js40
1 files changed, 40 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/app.js b/packages/meshbay-hub/src/meshbay_hub/static/app.js
index 6fefe0f..0aa74b4 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/app.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/app.js
@@ -122,6 +122,45 @@ function _restoreSessionKeys() {
} catch {}
}
+/** Public X25519 key from our own secret — never read back from the hub. */
+async function _pkXFromSk(skPkcs8B64) {
+ const raw = Uint8Array.from(atob(skPkcs8B64), c => c.charCodeAt(0));
+ const sk = await crypto.subtle.importKey('pkcs8', raw, { name: 'X25519' }, true, ['deriveBits']);
+ const jwk = await crypto.subtle.exportKey('jwk', sk);
+ const b64 = jwk.x.replace(/-/g, '+').replace(/_/g, '/');
+ const pad = b64.length % 4;
+ return pad ? b64 + '='.repeat(4 - pad) : b64;
+}
+
+/**
+ * Recover our identity keys from what this browser already holds.
+ *
+ * sessionStorage dies with the tab, but the encrypted keypair bundle sits in
+ * localStorage from registration and the key that opens it is in IndexedDB from
+ * login. Without this, closing the tab looked exactly like never having
+ * registered here — "this browser does not hold your keys", while both halves
+ * were on disk a few bytes apart.
+ */
+async function _recoverLocalKeys(username) {
+ if (_sessionKeys || !username) return;
+ try {
+ if (!_bundleKey) _bundleKey = await _loadBundleKey();
+ if (!_bundleKey || !window.MeshBayKeys) return;
+ const enc = localStorage.getItem(`meshbay_kp_${username}`);
+ if (!enc) return;
+ const keys = await window.MeshBayKeys.decryptBundleWithKey(enc, _bundleKey);
+ _sessionKeys = {
+ skXB64: keys.skX,
+ skEdB64: keys.skEd,
+ pkXB64: await _pkXFromSk(keys.skX),
+ };
+ _pendingBundlePush = enc; // still to be backed up to a node
+ _saveSessionKeys();
+ } catch (e) {
+ console.warn('[MeshBay] could not recover local keys:', e);
+ }
+}
+
function loadAuth() {
try {
return JSON.parse(localStorage.getItem(AUTH_KEY));
@@ -824,6 +863,7 @@ function GroupPage({ groupId, group, token, username, userId, onRefreshAuth }) {
gekRef.current = null;
if (!_bundleKey) _bundleKey = await _loadBundleKey();
_restoreSessionKeys();
+ await _recoverLocalKeys(username);
try {
const nodesData = await hubFetch(`/v1/groups/${groupId}/nodes`, { token });
if (cancelled) return;