aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js
diff options
context:
space:
mode:
authorChristophe Besson <cbesson@gmail.com>2026-09-30 15:48:51 +0200
committerChristophe Besson <cbesson@gmail.com>2026-09-30 15:48:51 +0200
commit8926f163dad9d32dc06c3a142658a4e11d9c12c1 (patch)
tree4d36d1c18154cb46e6e80c59ef6c607972caa81e /packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js
parent8d96cf2314b45e0737f932998b5422c27a2ae72e (diff)
downloadmeshbay-8926f163dad9d32dc06c3a142658a4e11d9c12c1.tar.gz
refactor(hub): the transport holds an identity, never a private key
Two public keys, sign() and shared(); the apps take transport.signFn. What holds the keys (this page, or the desktop main process) is the identity's business alone. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js26
1 files changed, 10 insertions, 16 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js b/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js
index 199b6a2..f17b1b6 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js
@@ -94,7 +94,7 @@ extendTransport(class {
* this node sees this account (and not at all in an open-join group).
*/
async joinGroup(userId, groupId, code) {
- if (!this._sessionKeys || !this._sessionKeys.skEdB64 || !this._sessionKeys.skXB64) {
+ if (!this._identity) {
throw new Error('Identity keys unavailable in this browser — sign in again');
}
if (!this._nonceNode || !this.nodePk) {
@@ -102,13 +102,12 @@ extendTransport(class {
}
const C = window.MeshBayCrypto;
- const pkEdB64 = await _pkEdFromSk(this._sessionKeys.skEdB64);
- const pkXB64 = await _pkFromSk(this._sessionKeys.skXB64);
+ const { pkEdB64, pkXB64 } = this._identity;
const ts = Math.floor(Date.now() / 1000);
const transcript = C.joinTranscript(
this.nodePk, groupId || '', userId, pkEdB64, pkXB64, this._nonceNode, ts);
- const sig = await window.MeshBayKeys.signBytes(this._sessionKeys.skEdB64, transcript);
+ const sig = await this._identity.sign(transcript);
const resp = await this._sendAndWait({
type: 'join_request',
@@ -133,9 +132,8 @@ extendTransport(class {
// Unwrap with our own secret key — the node wrapped for the public key we
// just proved we hold, so nobody else can open this.
- const skXRaw = Uint8Array.from(atob(this._sessionKeys.skXB64), c => c.charCodeAt(0));
const myPkX = Uint8Array.from(atob(pkXB64), c => c.charCodeAt(0));
- const gekRaw = await C.unwrapGEK(resp, skXRaw, myPkX);
+ const gekRaw = await C.unwrapGEK(resp, (pk) => this._identity.shared(pk), myPkX);
this._gekRaw = gekRaw;
// What the node's roster says this identity is, which is not what the hub
// says: `operator` here means this browser's key was paired with the node,
@@ -154,15 +152,14 @@ extendTransport(class {
* device cannot be handed a substituted key and sign for it by mistake.
*/
async requestDeviceAdd(userId) {
- if (!this._sessionKeys || !this._sessionKeys.skEdB64) {
+ if (!this._identity) {
throw new Error('Identity keys unavailable in this browser — sign in again');
}
if (!this._nonceNode || !this.nodePk) {
throw new Error('Handshake incomplete — reconnect and retry');
}
const C = window.MeshBayCrypto;
- const pkEdB64 = await _pkEdFromSk(this._sessionKeys.skEdB64);
- const pkXB64 = await _pkFromSk(this._sessionKeys.skXB64);
+ const { pkEdB64, pkXB64 } = this._identity;
// 40 bits from the platform CSPRNG, in the same alphabet as a pairing code
// so it reads and types the same way.
@@ -176,8 +173,7 @@ extendTransport(class {
const ts = Math.floor(Date.now() / 1000);
const transcript = C.deviceRequestTranscript(
this.nodePk, userId, pkEdB64, pkXB64, codeHash, this._nonceNode, ts);
- const sig = await window.MeshBayKeys.signBytes(
- this._sessionKeys.skEdB64, transcript);
+ const sig = await this._identity.sign(transcript);
const resp = await this._sendAndWait({
type: 'device_add_request', v: '0.1',
@@ -196,7 +192,7 @@ extendTransport(class {
* nothing to sign and nothing for a person to misread.
*/
async approveDevice(userId, code) {
- if (!this._sessionKeys || !this._sessionKeys.skEdB64) {
+ if (!this._identity) {
throw new Error('Identity keys unavailable in this browser — sign in again');
}
if (!this._nonceNode || !this.nodePk) {
@@ -231,8 +227,7 @@ extendTransport(class {
const ts = Math.floor(Date.now() / 1000);
const transcript = C.deviceAddTranscript(
this.nodePk, userId, pkEdB64, pkXB64, this._nonceNode, ts);
- const sig = await window.MeshBayKeys.signBytes(
- this._sessionKeys.skEdB64, transcript);
+ const sig = await this._identity.sign(transcript);
const resp = await this._sendAndWait({
type: 'device_add', v: '0.1',
pk_ed25519: pkEdB64, pk_x25519: pkXB64, code_hash: codeHash, ts, sig,
@@ -253,8 +248,7 @@ extendTransport(class {
const ts = Math.floor(Date.now() / 1000);
const transcript = C.deviceAddTranscript(
this.nodePk, userId, pkEdB64, pkXB64, this._nonceNode, ts);
- const sig = await window.MeshBayKeys.signBytes(
- this._sessionKeys.skEdB64, transcript);
+ const sig = await this._identity.sign(transcript);
const resp = await this._sendAndWait({
type: 'device_revoke', v: '0.1', pk_ed25519: pkEdB64, ts, sig,
});