aboutsummaryrefslogtreecommitdiffstats
path: root/packages/meshbay-hub/src/meshbay_hub/static/crypto.js
diff options
context:
space:
mode:
Diffstat (limited to 'packages/meshbay-hub/src/meshbay_hub/static/crypto.js')
-rw-r--r--packages/meshbay-hub/src/meshbay_hub/static/crypto.js54
1 files changed, 54 insertions, 0 deletions
diff --git a/packages/meshbay-hub/src/meshbay_hub/static/crypto.js b/packages/meshbay-hub/src/meshbay_hub/static/crypto.js
index 27e97d3..c239cc8 100644
--- a/packages/meshbay-hub/src/meshbay_hub/static/crypto.js
+++ b/packages/meshbay-hub/src/meshbay_hub/static/crypto.js
@@ -451,6 +451,7 @@ const JOIN_PREFIX = new TextEncoder().encode('meshbay:join:v1');
const DEVICE_REQ_PREFIX = new TextEncoder().encode('meshbay:device_req:v1');
const DEVICE_ADD_PREFIX = new TextEncoder().encode('meshbay:device_add:v1');
const DEVICE_HELLO_PREFIX = new TextEncoder().encode('meshbay:device_hello:v1');
+const DEVICE_REVOKE_PREFIX = new TextEncoder().encode('meshbay:device_revoke:v1');
function joinTranscript(nodePkB64, groupId, userId, pkEdB64, pkXB64, nonceNode, ts) {
const enc = new TextEncoder();
@@ -503,6 +504,22 @@ function deviceAddTranscript(nodePkB64, userId, pkEdB64, pkXB64, nonceNode, ts)
}
/**
+ * Retiring one of the account's devices. A prefix of its own: were it the
+ * admission transcript, a signature given to retire a key would admit it.
+ */
+function deviceRevokeTranscript(nodePkB64, userId, pkEdB64, nonceNode, ts) {
+ const enc = new TextEncoder();
+ const body = _lenPrefixed([
+ enc.encode(nodePkB64), enc.encode(userId), enc.encode(pkEdB64),
+ nonceNode, enc.encode(String(ts)),
+ ]);
+ const out = new Uint8Array(DEVICE_REVOKE_PREFIX.length + body.length);
+ out.set(DEVICE_REVOKE_PREFIX, 0);
+ out.set(body, DEVICE_REVOKE_PREFIX.length);
+ return out;
+}
+
+/**
* "Which of this account's devices am I?", mirroring
* `meshbay_common/device.py:device_hello_transcript`.
*
@@ -560,6 +577,42 @@ function constantTimeEqual(a, b) {
return diff === 0;
}
+/**
+ * What an identity signs, by kind. The only way anything here gets signed with
+ * an identity: a caller names what it is signing and gives the fields, and the
+ * bytes are built from them — with the identity's own public keys wherever a
+ * transcript names them. The desktop application builds the same bytes in its
+ * main process (meshbay-client/src/transcripts.js) and signs nothing else,
+ * which is what makes a signature from it mean what its kind says.
+ *
+ * Bytes cross as base64: `nonceNode`, `nonce`, `ct`.
+ */
+function transcriptFor(kind, f, own) {
+ const nonceNode = () => b64decode(f.nonceNode);
+ switch (kind) {
+ case 'join':
+ return joinTranscript(f.nodePk, f.groupId || '', f.userId, own.pkEdB64, own.pkXB64,
+ nonceNode(), f.ts);
+ case 'device_hello':
+ return deviceHelloTranscript(f.nodePk, f.groupId || '', f.userId, own.pkEdB64,
+ nonceNode(), f.ts);
+ case 'device_request':
+ return deviceRequestTranscript(f.nodePk, f.userId, own.pkEdB64, own.pkXB64,
+ f.codeHash, nonceNode(), f.ts);
+ case 'device_add':
+ return deviceAddTranscript(f.nodePk, f.userId, f.pkEd, f.pkX, nonceNode(), f.ts);
+ case 'device_revoke':
+ return deviceRevokeTranscript(f.nodePk, f.userId, f.pkEd, nonceNode(), f.ts);
+ case 'chat':
+ return chatSigningTranscript(f.groupId || '', f.epoch, b64decode(own.pkEdB64),
+ b64decode(f.nonce), b64decode(f.ct));
+ case 'admin':
+ return adminTranscript(f.op, f.nodePk, f.groupId || '', f.subject, f.nonce, f.ts);
+ default:
+ throw new Error(`Refused: nothing is signed as "${kind}"`);
+ }
+}
+
/** Verify the node's Ed25519 signature over the handshake transcript (C3). */
async function verifyNodeSignature(nodePkB64, sigB64, transcript) {
const raw = b64decode(nodePkB64);
@@ -576,6 +629,7 @@ window.MeshBayCrypto = {
inviteCreateSubject, tmdbConfigSubject, handshakeTranscript, handshakeProof, webrtcBinding,
challengeTranscript, joinTranscript, verifyNodeSignature, constantTimeEqual,
deviceRequestTranscript, deviceAddTranscript, deviceHelloTranscript,
+ deviceRevokeTranscript, transcriptFor,
deviceCodeHash,
sealChat, openChat, chatSigningTranscript, verifyChatSignature,
normalizeCode,