From 0378e8e0912a1a7e6cea4424e69d524e7afecbf8 Mon Sep 17 00:00:00 2001 From: Christophe Besson Date: Wed, 30 Sep 2026 21:04:39 +0200 Subject: fix: an identity signs a named kind, and a device approval answers a request The desktop main process builds every transcript itself from fields (transcripts.js) and signs no raw bytes; the page's identity has the same contract (crypto.js transcriptFor). The keyring seals no bundle while browser access is off. On the node, device_add must redeem a pending request filed by the same keys, and device_revoke is signed under its own prefix (meshbay:device_revoke:v1), so a retirement signature admits nothing. Co-Authored-By: Claude Opus 5.5 --- .../src/meshbay_hub/static/transport-devices.js | 28 ++++++++++++---------- 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js') 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 1cb248a..1c6fc78 100644 --- a/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js +++ b/packages/meshbay-hub/src/meshbay_hub/static/transport-devices.js @@ -105,9 +105,10 @@ extendTransport(class { 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 this._identity.sign(transcript); + const sig = await this._identity.signAs('join', { + nodePk: this.nodePk, groupId: groupId || '', userId, + nonceNode: C.b64encode(this._nonceNode), ts, + }); const resp = await this._sendAndWait({ type: 'join_request', @@ -171,9 +172,10 @@ extendTransport(class { const codeHash = await C.deviceCodeHash( C.normalizeCode(code), pkEdB64, pkXB64); const ts = Math.floor(Date.now() / 1000); - const transcript = C.deviceRequestTranscript( - this.nodePk, userId, pkEdB64, pkXB64, codeHash, this._nonceNode, ts); - const sig = await this._identity.sign(transcript); + const sig = await this._identity.signAs('device_request', { + nodePk: this.nodePk, userId, codeHash, + nonceNode: C.b64encode(this._nonceNode), ts, + }); const resp = await this._sendAndWait({ type: 'device_add_request', v: '0.1', @@ -225,9 +227,10 @@ extendTransport(class { async _countersign(userId, codeHash, pkEdB64, pkXB64) { const C = window.MeshBayCrypto; const ts = Math.floor(Date.now() / 1000); - const transcript = C.deviceAddTranscript( - this.nodePk, userId, pkEdB64, pkXB64, this._nonceNode, ts); - const sig = await this._identity.sign(transcript); + const sig = await this._identity.signAs('device_add', { + nodePk: this.nodePk, userId, pkEd: pkEdB64, pkX: pkXB64, + nonceNode: C.b64encode(this._nonceNode), ts, + }); const resp = await this._sendAndWait({ type: 'device_add', v: '0.1', pk_ed25519: pkEdB64, pk_x25519: pkXB64, code_hash: codeHash, ts, sig, @@ -246,9 +249,10 @@ extendTransport(class { async revokeDevice(userId, pkEdB64, pkXB64) { const C = window.MeshBayCrypto; const ts = Math.floor(Date.now() / 1000); - const transcript = C.deviceAddTranscript( - this.nodePk, userId, pkEdB64, pkXB64, this._nonceNode, ts); - const sig = await this._identity.sign(transcript); + const sig = await this._identity.signAs('device_revoke', { + nodePk: this.nodePk, userId, pkEd: pkEdB64, + nonceNode: C.b64encode(this._nonceNode), ts, + }); const resp = await this._sendAndWait({ type: 'device_revoke', v: '0.1', pk_ed25519: pkEdB64, ts, sig, }); -- cgit v1.2.3