@cryptforge/key-exchange 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,806 @@
1
+ "use strict";
2
+ var __create = Object.create;
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __getProtoOf = Object.getPrototypeOf;
7
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
8
+ var __export = (target, all) => {
9
+ for (var name in all)
10
+ __defProp(target, name, { get: all[name], enumerable: true });
11
+ };
12
+ var __copyProps = (to, from, except, desc) => {
13
+ if (from && typeof from === "object" || typeof from === "function") {
14
+ for (let key of __getOwnPropNames(from))
15
+ if (!__hasOwnProp.call(to, key) && key !== except)
16
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
17
+ }
18
+ return to;
19
+ };
20
+ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
21
+ // If the importer is in node compatibility mode or this is not an ESM
22
+ // file that has been converted to a CommonJS file using a Babel-
23
+ // compatible transform (i.e. "__esModule" has not been set), then set
24
+ // "default" to the CommonJS "module.exports" for node compatibility.
25
+ isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
26
+ mod
27
+ ));
28
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
29
+
30
+ // src/electron-main.ts
31
+ var electron_main_exports = {};
32
+ __export(electron_main_exports, {
33
+ CoreTransportLogic: () => CoreTransportLogic,
34
+ setupKeyExchangeHandlers: () => setupKeyExchangeHandlers
35
+ });
36
+ module.exports = __toCommonJS(electron_main_exports);
37
+
38
+ // src/types/messages.ts
39
+ var MESSAGES = {
40
+ enableBroadcast: "admin:broadcast:enable",
41
+ connect: "client:topic:connect",
42
+ onClientConnection: "admin:topic:connected",
43
+ requestKeystore: "client:keystore:request",
44
+ onKeystoreRequestInvalidPIN: "admin:pin:invalid",
45
+ onKeystoreRequestValidPIN: "admin:pin:valid",
46
+ onKeystoreRequest: "admin:request:received",
47
+ approveRequest: "admin:request:approve",
48
+ onClientApproval: "client:request:approved",
49
+ denyRequest: "admin:request:deny",
50
+ onClientDenial: "client:request:denied",
51
+ onCompletion: "server:link:complete",
52
+ disableBroadcast: "admin:broadcast:disable",
53
+ onBroadcastDisable: "client:broadcast:disabled",
54
+ getDeviceInfo: "client:request:deviceInfo",
55
+ getHostname: "client:request:hostname",
56
+ // Presence/Network messages
57
+ connectPresence: "network:connect",
58
+ broadcastClientState: "network:broadcast",
59
+ onClientStateRequest: "network:request",
60
+ onClientStateUpdate: "network:update"
61
+ };
62
+
63
+ // src/electron/main/setupExhangeHandlers.ts
64
+ var import_electron2 = require("electron");
65
+
66
+ // src/useNetworkPresenceServer.ts
67
+ var import_hyperswarm = __toESM(require("hyperswarm"));
68
+ var import_b4a = __toESM(require("b4a"));
69
+ function useNetworkPresence(onUpdate, onRequest) {
70
+ const deviceIDs = /* @__PURE__ */ new Map();
71
+ const swarm = new import_hyperswarm.default();
72
+ swarm.on("connection", (connection) => {
73
+ const name = import_b4a.default.toString(connection.remotePublicKey, "hex");
74
+ console.log("Presence: * got a connection from:", name, "*");
75
+ connections.push(connection);
76
+ sendStateRequestMessage(connection);
77
+ connection.once("close", () => {
78
+ console.log(
79
+ `Presence: Connection closed. Removing connection ${import_b4a.default.toString(
80
+ connection.remotePublicKey,
81
+ "hex"
82
+ )}`
83
+ );
84
+ connections.splice(connections.indexOf(connection), 1);
85
+ const id = deviceIDs.get(import_b4a.default.toString(connection.remotePublicKey, "hex"));
86
+ if (id) {
87
+ broadcastStatusMessage(id, "unknown");
88
+ }
89
+ deviceIDs.delete(import_b4a.default.toString(connection.remotePublicKey, "hex"));
90
+ });
91
+ connection.on("data", (data) => {
92
+ let parsedData;
93
+ try {
94
+ parsedData = JSON.parse(data);
95
+ } catch (error) {
96
+ console.error("Error parsing data:", error);
97
+ return;
98
+ }
99
+ const header = parsedData;
100
+ console.log(
101
+ "Presence: got data for ",
102
+ connection.publicKey.toString("hex")
103
+ );
104
+ if (header.type === "update") {
105
+ const payload = parsedData;
106
+ onUpdate({ id: payload.id, state: payload.state });
107
+ deviceIDs.set(
108
+ import_b4a.default.toString(connection.remotePublicKey, "hex"),
109
+ payload.id
110
+ );
111
+ } else if (header.type === "request") {
112
+ onRequest();
113
+ }
114
+ });
115
+ connection.on("error", (error) => {
116
+ console.error(
117
+ `Presence: Connection error on connection ${import_b4a.default.toString(
118
+ connection.remotePublicKey,
119
+ "hex"
120
+ )}: ${error}`
121
+ );
122
+ });
123
+ });
124
+ const connections = [];
125
+ const connect = async (topic, id) => {
126
+ console.log("Presence: connecting to topic: ", topic);
127
+ const key = import_b4a.default.from(topic, "hex");
128
+ console.log("key: ", key);
129
+ const discovery = swarm.join(key, { client: true, server: true });
130
+ console.log("got discovery: ");
131
+ const publicKey = import_b4a.default.toString(
132
+ discovery.swarm.keyPair?.publicKey || discovery.swarm.publicKey || Buffer.alloc(32),
133
+ "hex"
134
+ );
135
+ console.log("Presence: public key is ", publicKey);
136
+ deviceIDs.set(publicKey, id);
137
+ discovery.flushed().then(() => {
138
+ console.log("Presence: joined topic:", import_b4a.default.toString(key, "hex"));
139
+ });
140
+ };
141
+ const sendStateRequestMessage = async (connection) => {
142
+ const message = {
143
+ type: "request"
144
+ };
145
+ const payload = JSON.stringify(message);
146
+ console.log(
147
+ "sending state request message to: ",
148
+ connection.publicKey.toString("hex")
149
+ );
150
+ connection.write(payload);
151
+ };
152
+ const receiveStatusMessage = async (id, state) => {
153
+ return broadcastStatusMessage(id, state);
154
+ };
155
+ const broadcastStatusMessage = (id, state) => {
156
+ console.log(`server got connection state message for ${id}: `, state);
157
+ const message = {
158
+ type: "update",
159
+ id,
160
+ state
161
+ };
162
+ console.log("active connections: ", connections.length);
163
+ const payload = JSON.stringify(message);
164
+ for (const connection of connections) {
165
+ console.log("sending message to: ", connection.publicKey.toString("hex"));
166
+ connection.write(payload);
167
+ }
168
+ onUpdate(message);
169
+ };
170
+ return {
171
+ connect,
172
+ receiveStatusMessage
173
+ };
174
+ }
175
+
176
+ // src/client/useKeyExchangeClient.ts
177
+ var import_hyperdht = __toESM(require("hyperdht"));
178
+ var import_b4a3 = __toESM(require("b4a"));
179
+
180
+ // src/server/messages.ts
181
+ var import_b4a2 = __toESM(require("b4a"));
182
+ var syncSetupEventRoutes = {
183
+ onClientConnection: MESSAGES.onClientConnection,
184
+ onKeystoreRequest: MESSAGES.onKeystoreRequest,
185
+ onClientApproval: MESSAGES.onClientApproval,
186
+ onClientDenial: MESSAGES.onClientDenial,
187
+ onCompletion: MESSAGES.onCompletion,
188
+ onBroadcastDisable: MESSAGES.onBroadcastDisable,
189
+ onKeystoreRequestInvalidPIN: MESSAGES.onKeystoreRequestInvalidPIN,
190
+ onKeystoreRequestValidPIN: MESSAGES.onKeystoreRequestValidPIN
191
+ };
192
+ var requestHeaders = [
193
+ {
194
+ code: 1e3,
195
+ name: "Request PIN",
196
+ description: "The Client is asking the Server to show UI of a PIN screen for the user to enter on the Client"
197
+ },
198
+ {
199
+ code: 2e3,
200
+ name: "Request Keystore",
201
+ description: "The Client is asking the Server to show UI for the user to approve or reject the request"
202
+ }
203
+ ];
204
+ var sendRequest = async (options) => {
205
+ const index = requestHeaders.findIndex(
206
+ (response) => response.name === options.header
207
+ );
208
+ if (index !== -1) {
209
+ const header = requestHeaders[index];
210
+ const body = options.body();
211
+ const request = {
212
+ header,
213
+ body
214
+ };
215
+ const payload = JSON.stringify(request);
216
+ for (const socket of options.to) {
217
+ console.log(
218
+ `hyperswarm: sending ${header.name} to connection ${import_b4a2.default.toString(
219
+ socket.remotePublicKey,
220
+ "hex"
221
+ )}`
222
+ );
223
+ socket.write(payload);
224
+ }
225
+ } else {
226
+ console.log(`Request with name \`${options.header}\` not found`);
227
+ }
228
+ };
229
+ var responseHeaders = [
230
+ {
231
+ code: 1501,
232
+ name: "Connection Failure: Broadcast disabled",
233
+ type: "Failure"
234
+ },
235
+ { code: 2200, name: "Authentication Succeeded", type: "Success" },
236
+ { code: 2400, name: "Authentication Error: Invalid PIN", type: "Error" },
237
+ { code: 3200, name: "Transmition Succeeded: Approved", type: "Success" },
238
+ { code: 3201, name: "Transmition Succeeded: Rejected", type: "Success" },
239
+ { code: 4200, name: "Setup Succeeded", type: "Success" }
240
+ ];
241
+ var sendResponse = (options) => {
242
+ const index = responseHeaders.findIndex(
243
+ (response) => response.name === options.header
244
+ );
245
+ if (index !== -1) {
246
+ const header = responseHeaders[index];
247
+ const data = options.body();
248
+ const response = {
249
+ header,
250
+ body: data
251
+ };
252
+ const payload = JSON.stringify(response);
253
+ for (const socket of options.to) {
254
+ console.log(
255
+ `hyperswarm: sending ${header.name} to connection ${import_b4a2.default.toString(
256
+ socket.remotePublicKey,
257
+ "hex"
258
+ )}`
259
+ );
260
+ socket.write(payload);
261
+ }
262
+ } else {
263
+ console.log(`Response with name \`${options.header}\` not found`);
264
+ }
265
+ };
266
+
267
+ // src/client/useKeyExchangeClient.ts
268
+ function useKeyExchangeClient(onEvent) {
269
+ let socket;
270
+ let deviceName;
271
+ let appName;
272
+ const connect = async (options) => {
273
+ deviceName = options.name;
274
+ appName = options.app;
275
+ return new Promise((resolve) => {
276
+ console.log(`client: connecting to server on ${options.key}`);
277
+ const publicKey = import_b4a3.default.from(options.key, "hex");
278
+ const dht = new import_hyperdht.default();
279
+ socket = dht.connect(publicKey);
280
+ socket.once("open", () => {
281
+ const name = import_b4a3.default.toString(socket.remotePublicKey, "hex");
282
+ console.log(`client: got a connection on ${name}`);
283
+ resolve();
284
+ });
285
+ socket.on("data", (data) => {
286
+ parseResponse(data);
287
+ });
288
+ socket.on("error", (error) => {
289
+ onConnectionError(error);
290
+ });
291
+ });
292
+ };
293
+ const parseResponse = async (data) => {
294
+ console.log(`client: got data: ${data}`);
295
+ const parsedData = JSON.parse(data);
296
+ const payload = parsedData;
297
+ console.log("payload");
298
+ console.log(payload);
299
+ switch (payload.header.name) {
300
+ case "Connection Failure: Broadcast disabled":
301
+ onEvent({
302
+ route: syncSetupEventRoutes["onBroadcastDisable"],
303
+ data: {}
304
+ });
305
+ break;
306
+ case "Transmition Succeeded: Approved":
307
+ const identity = payload.body.identity;
308
+ const appId = payload.body.appId;
309
+ onEvent({
310
+ route: syncSetupEventRoutes["onClientApproval"],
311
+ data: { identity, appId }
312
+ });
313
+ break;
314
+ case "Transmition Succeeded: Rejected":
315
+ onEvent({ route: syncSetupEventRoutes["onClientDenial"], data: {} });
316
+ break;
317
+ case "Setup Succeeded":
318
+ onEvent({ route: syncSetupEventRoutes["onCompletion"], data: {} });
319
+ break;
320
+ case "Authentication Error: Invalid PIN":
321
+ onEvent({
322
+ route: syncSetupEventRoutes["onKeystoreRequestInvalidPIN"],
323
+ data: {
324
+ reason: "Invalid PIN Entered"
325
+ }
326
+ });
327
+ break;
328
+ case "Authentication Succeeded":
329
+ onEvent({
330
+ route: syncSetupEventRoutes["onKeystoreRequestValidPIN"],
331
+ data: {}
332
+ });
333
+ break;
334
+ default:
335
+ console.error(`error: response ${payload} not handled in client`);
336
+ break;
337
+ }
338
+ };
339
+ const onConnectionError = async (error) => {
340
+ console.log(`client: Connection error: ${error}`);
341
+ const route = syncSetupEventRoutes["onBroadcastDisable"];
342
+ switch (error.code) {
343
+ case "PEER_NOT_FOUND":
344
+ onEvent({
345
+ route,
346
+ data: {
347
+ title: "Peer Not Found",
348
+ description: "Another device with the specified broadcast key could not be located."
349
+ }
350
+ });
351
+ break;
352
+ default:
353
+ onEvent({
354
+ route,
355
+ data: {
356
+ title: "Client Disconnected",
357
+ description: "The connection to your other device was lost. Please ensure you have another device that is broadcasting"
358
+ }
359
+ });
360
+ break;
361
+ }
362
+ };
363
+ const requestPIN = async () => {
364
+ await sendRequest({
365
+ to: [socket],
366
+ header: "Request PIN",
367
+ body: () => {
368
+ return { deviceName, appName };
369
+ }
370
+ });
371
+ };
372
+ const requestKeystore = async (pin) => {
373
+ await sendRequest({
374
+ to: [socket],
375
+ header: "Request Keystore",
376
+ body: () => {
377
+ return {
378
+ pin
379
+ };
380
+ }
381
+ });
382
+ const route = syncSetupEventRoutes["onKeystoreRequest"];
383
+ onEvent({ route, data: {} });
384
+ };
385
+ return {
386
+ connect,
387
+ requestPIN,
388
+ requestKeystore
389
+ };
390
+ }
391
+
392
+ // src/server/useKeyExchangeServer.ts
393
+ var import_hyperdht2 = __toESM(require("hyperdht"));
394
+ var import_b4a4 = __toESM(require("b4a"));
395
+ function useKeyExchangeServer(onEvent) {
396
+ let client;
397
+ let dht;
398
+ const keyPair = import_hyperdht2.default.keyPair();
399
+ const getKey = () => {
400
+ return import_b4a4.default.toString(keyPair.publicKey, "hex");
401
+ };
402
+ const generateRandomPIN = () => {
403
+ return Math.floor(1e5 + Math.random() * 9e5);
404
+ };
405
+ const pin = generateRandomPIN();
406
+ const getPIN = () => {
407
+ return `${pin}`;
408
+ };
409
+ let server;
410
+ const createServer = async () => {
411
+ dht = new import_hyperdht2.default();
412
+ server = await dht.createServer((socket) => {
413
+ const name = import_b4a4.default.toString(socket.remotePublicKey, "hex");
414
+ console.log(`server: got a connection on \`${name}\``);
415
+ socket.on("data", (data) => {
416
+ parseRequest(data);
417
+ });
418
+ socket.on("error", (error) => {
419
+ onConnectionError(error);
420
+ });
421
+ client = socket;
422
+ });
423
+ };
424
+ const parseRequest = (data) => {
425
+ console.log(`server: got data: ${data}`);
426
+ const parsedData = JSON.parse(data);
427
+ const payload = parsedData;
428
+ console.log("payload");
429
+ console.log(payload);
430
+ switch (payload.header.name) {
431
+ case "Request PIN":
432
+ onRequestPin(payload.body);
433
+ break;
434
+ case "Request Keystore":
435
+ onRequestKeystore(payload.body);
436
+ break;
437
+ }
438
+ };
439
+ const onConnectionError = (error) => {
440
+ console.log(`server: Connection error: ${error}`);
441
+ };
442
+ const onRequestPin = (body) => {
443
+ const route = syncSetupEventRoutes["onClientConnection"];
444
+ onEvent({
445
+ route,
446
+ data: {
447
+ pin: getPIN(),
448
+ name: body.deviceName,
449
+ app: body.appName
450
+ }
451
+ });
452
+ };
453
+ const onRequestKeystore = (body) => {
454
+ const pin2 = body.pin;
455
+ if (pin2 !== getPIN()) {
456
+ sendResponse({
457
+ to: [client],
458
+ header: "Authentication Error: Invalid PIN",
459
+ body: () => {
460
+ return {};
461
+ }
462
+ });
463
+ return;
464
+ } else {
465
+ sendResponse({
466
+ to: [client],
467
+ header: "Authentication Succeeded",
468
+ body: () => {
469
+ return {};
470
+ }
471
+ });
472
+ }
473
+ const route = syncSetupEventRoutes["onKeystoreRequest"];
474
+ onEvent({
475
+ route,
476
+ data: {}
477
+ });
478
+ };
479
+ const onRequestDenied = () => {
480
+ const route = syncSetupEventRoutes["onClientDenial"];
481
+ onEvent({ route, data: {} });
482
+ };
483
+ const onSetupComplete = () => {
484
+ const route = syncSetupEventRoutes["onCompletion"];
485
+ onEvent({ route, data: {} });
486
+ };
487
+ const beginBroadcast = async () => {
488
+ await createServer();
489
+ await server.listen(keyPair);
490
+ await server.refresh();
491
+ console.log(`server: opened connection to ${getKey()}`);
492
+ };
493
+ const endBroadcast = async () => {
494
+ if (server) {
495
+ await server.close();
496
+ console.log(`server: closed connection to ${getKey()}`);
497
+ }
498
+ if (dht) {
499
+ await dht.destroy();
500
+ console.log(`server: destroyed dht`);
501
+ }
502
+ };
503
+ const approveRequest = async (identity, appId) => {
504
+ sendResponse({
505
+ to: [client],
506
+ header: "Transmition Succeeded: Approved",
507
+ body: () => {
508
+ return {
509
+ identity,
510
+ appId
511
+ };
512
+ }
513
+ });
514
+ };
515
+ const completeSetupSuccess = async () => {
516
+ console.log("sending compltion message to client");
517
+ sendResponse({
518
+ to: [client],
519
+ header: "Setup Succeeded",
520
+ body: () => {
521
+ return {};
522
+ }
523
+ });
524
+ onSetupComplete();
525
+ };
526
+ const rejectRequest = async () => {
527
+ sendResponse({
528
+ to: [client],
529
+ header: "Transmition Succeeded: Rejected",
530
+ body: () => {
531
+ return {};
532
+ }
533
+ });
534
+ onRequestDenied();
535
+ };
536
+ const broadcastDisabled = async () => {
537
+ if (client) {
538
+ sendResponse({
539
+ to: [client],
540
+ header: "Connection Failure: Broadcast disabled",
541
+ body: () => {
542
+ return {};
543
+ }
544
+ });
545
+ }
546
+ };
547
+ return {
548
+ getKey,
549
+ getPIN,
550
+ beginBroadcast,
551
+ endBroadcast,
552
+ approveRequest,
553
+ completeSetupSuccess,
554
+ rejectRequest,
555
+ broadcastDisabled
556
+ };
557
+ }
558
+
559
+ // src/CoreTransportLogic.ts
560
+ var import_crypto = __toESM(require("crypto"));
561
+ var import_os = __toESM(require("os"));
562
+ var import_systeminformation = __toESM(require("systeminformation"));
563
+ var CoreTransportLogic = class {
564
+ syncServer;
565
+ syncClient;
566
+ presence;
567
+ deviceInfo = null;
568
+ handleEvent;
569
+ presenceConnected = false;
570
+ constructor(handleEvent = () => {
571
+ }) {
572
+ this.handleEvent = handleEvent;
573
+ this.syncServer = useKeyExchangeServer(this.handleEvent);
574
+ this.syncClient = useKeyExchangeClient(this.handleEvent);
575
+ this.presence = useNetworkPresence(
576
+ this.onStateUpdate.bind(this),
577
+ this.onStateRequest.bind(this)
578
+ );
579
+ this.initializeDeviceInfo();
580
+ }
581
+ async initializeDeviceInfo() {
582
+ this.deviceInfo = await this.getDeviceInfo();
583
+ }
584
+ onStateUpdate(response) {
585
+ console.log("received state message for:", response.id);
586
+ this.handleEvent({ route: MESSAGES.onClientStateUpdate, data: response });
587
+ }
588
+ onStateRequest() {
589
+ console.log("received state request");
590
+ this.handleEvent({ route: MESSAGES.onClientStateRequest, data: {} });
591
+ }
592
+ delay(ms) {
593
+ return new Promise((resolve) => setTimeout(resolve, ms));
594
+ }
595
+ // Sync methods
596
+ async enableBroadcast() {
597
+ console.log(`admin: enabled broadcast`);
598
+ try {
599
+ await this.syncServer.beginBroadcast();
600
+ return this.syncServer.getKey();
601
+ } catch (error) {
602
+ const code = error && typeof error === "object" && "code" in error ? error.code : "UNKNOWN";
603
+ console.error("Error on broadcast enable during topic sync setup:", code);
604
+ if (code === "ALREADY_LISTENING") {
605
+ return this.syncServer.getKey();
606
+ }
607
+ throw error;
608
+ }
609
+ }
610
+ async connect(topic, name, app) {
611
+ console.log(`client: requested connection to ${topic}`);
612
+ try {
613
+ await this.syncClient.connect({ key: topic, name, app });
614
+ await this.syncClient.requestPIN();
615
+ } catch (error) {
616
+ console.error("Error on topic connect during sync setup:", error);
617
+ throw error;
618
+ }
619
+ }
620
+ async requestKeystore(pin) {
621
+ console.log(`client: requested keystore using pin \`${pin}\``);
622
+ try {
623
+ await this.syncClient.requestKeystore(pin);
624
+ } catch (error) {
625
+ console.error("Error on keystore request during sync setup:", error);
626
+ throw error;
627
+ }
628
+ }
629
+ async approveRequest(data) {
630
+ console.log(`admin: request approved`);
631
+ try {
632
+ await this.syncServer.approveRequest(data.identity, data.appId);
633
+ await this.delay(3e3);
634
+ await this.syncServer.completeSetupSuccess();
635
+ } catch (error) {
636
+ console.error("Error on request approve during sync setup:", error);
637
+ throw error;
638
+ }
639
+ }
640
+ async denyRequest() {
641
+ console.log(`admin: request denied`);
642
+ try {
643
+ await this.syncServer.rejectRequest();
644
+ } catch (error) {
645
+ console.error("Error on request deny during sync setup:", error);
646
+ throw error;
647
+ }
648
+ }
649
+ async disableBroadcast() {
650
+ try {
651
+ await this.syncServer.endBroadcast();
652
+ await this.syncServer.broadcastDisabled();
653
+ } catch (error) {
654
+ console.error("Error on broadcast disable during sync setup:", error);
655
+ throw error;
656
+ }
657
+ }
658
+ // Device methods
659
+ async getDeviceInfo() {
660
+ if (this.deviceInfo) {
661
+ return this.deviceInfo;
662
+ }
663
+ const hostname = import_os.default.hostname();
664
+ const osInfo = await import_systeminformation.default.osInfo();
665
+ const uuid = await import_systeminformation.default.uuid();
666
+ const serial = osInfo.serial;
667
+ const distro = osInfo.distro;
668
+ const arch = osInfo.arch;
669
+ const hardwareUUID = uuid.hardware;
670
+ const key = serial + distro + arch + hardwareUUID;
671
+ const hash = import_crypto.default.createHash("sha256").update(key).digest("hex");
672
+ return { id: hash, name: hostname };
673
+ }
674
+ async getHostname() {
675
+ return import_os.default.hostname();
676
+ }
677
+ // Network methods
678
+ async connectPresence(topic) {
679
+ if (this.presenceConnected) {
680
+ console.log("Presence already connected, skipping");
681
+ return;
682
+ }
683
+ const deviceInfo = await this.getDeviceInfo();
684
+ const topicHash = import_crypto.default.createHash("sha256").update(topic).digest("hex");
685
+ console.log(`Connecting presence network to topic: ${topicHash}`);
686
+ await this.presence.connect(topicHash, deviceInfo.id);
687
+ this.presenceConnected = true;
688
+ }
689
+ broadcastClientState(id, state) {
690
+ this.presence.receiveStatusMessage(id, state);
691
+ }
692
+ };
693
+
694
+ // src/electron/main/keyTransportMain.ts
695
+ var import_electron = require("electron");
696
+ var KeyTransportMain = class {
697
+ core;
698
+ peers = /* @__PURE__ */ new Map();
699
+ constructor() {
700
+ this.core = new CoreTransportLogic(this.handleEvent.bind(this));
701
+ }
702
+ /**
703
+ * Electron-specific event routing via IPC
704
+ */
705
+ handleEvent = (options) => {
706
+ console.log(
707
+ `received event with route: \`${options.route}\` data:`,
708
+ options.data
709
+ );
710
+ const allWindows = import_electron.BrowserWindow.getAllWindows();
711
+ allWindows.forEach((window) => {
712
+ window.webContents.send(options.route, options.data);
713
+ });
714
+ };
715
+ // Sync namespace - delegate to core for logic, no-ops for callbacks
716
+ enableBroadcast = () => this.core.enableBroadcast();
717
+ connect = (topic, name, app) => this.core.connect(topic, name, app);
718
+ onClientConnection = async (_callback) => {
719
+ };
720
+ requestKeystore = (pin) => this.core.requestKeystore(pin);
721
+ onKeystoreRequestInvalidPIN = async (_callback) => {
722
+ };
723
+ onKeystoreRequestValidPIN = async (_callback) => {
724
+ };
725
+ onKeystoreRequest = async (_callback) => {
726
+ };
727
+ approveRequest = (data) => this.core.approveRequest(data);
728
+ onClientApproval = async (_callback) => {
729
+ };
730
+ denyRequest = () => this.core.denyRequest();
731
+ onClientDenial = async (_callback) => {
732
+ };
733
+ onCompletion = async (_callback) => {
734
+ };
735
+ disableBroadcast = () => this.core.disableBroadcast();
736
+ onBroadcastDisable = async (_callback) => {
737
+ };
738
+ getDeviceInfo = () => this.core.getDeviceInfo();
739
+ getHostname = () => this.core.getHostname();
740
+ connectPresence = async (topic) => {
741
+ return this.core.connectPresence(topic);
742
+ };
743
+ broadcastClientState = async (id, state) => {
744
+ this.peers.set(id, state);
745
+ this.core.broadcastClientState(id, state);
746
+ };
747
+ onClientStateRequest = async (_callback) => {
748
+ };
749
+ onClientStateUpdate = async (_callback) => {
750
+ };
751
+ getPeerState = (id) => {
752
+ return this.peers.get(id);
753
+ };
754
+ getAllPeers = () => {
755
+ return this.peers;
756
+ };
757
+ };
758
+
759
+ // src/electron/main/setupExhangeHandlers.ts
760
+ var setupKeyExchangeHandlers = () => {
761
+ const transport = new KeyTransportMain();
762
+ import_electron2.ipcMain.handle(MESSAGES.enableBroadcast, async () => {
763
+ return transport.enableBroadcast();
764
+ });
765
+ import_electron2.ipcMain.handle(
766
+ MESSAGES.connect,
767
+ async (_event, topic, name, app) => {
768
+ return transport.connect(topic, name, app);
769
+ }
770
+ );
771
+ import_electron2.ipcMain.handle(MESSAGES.requestKeystore, async (_event, pin) => {
772
+ return transport.requestKeystore(pin);
773
+ });
774
+ import_electron2.ipcMain.handle(
775
+ MESSAGES.approveRequest,
776
+ async (_event, data) => {
777
+ return transport.approveRequest(data);
778
+ }
779
+ );
780
+ import_electron2.ipcMain.handle(MESSAGES.denyRequest, async () => {
781
+ return transport.denyRequest();
782
+ });
783
+ import_electron2.ipcMain.handle(MESSAGES.disableBroadcast, async () => {
784
+ return transport.disableBroadcast();
785
+ });
786
+ import_electron2.ipcMain.handle(MESSAGES.getDeviceInfo, async () => {
787
+ return transport.getDeviceInfo();
788
+ });
789
+ import_electron2.ipcMain.handle(MESSAGES.getHostname, async () => {
790
+ return transport.getHostname();
791
+ });
792
+ import_electron2.ipcMain.handle(MESSAGES.connectPresence, async (_event, topic) => {
793
+ return transport.connectPresence(topic);
794
+ });
795
+ import_electron2.ipcMain.handle(
796
+ MESSAGES.broadcastClientState,
797
+ async (_event, id, state) => {
798
+ return transport.broadcastClientState(id, state);
799
+ }
800
+ );
801
+ };
802
+ // Annotate the CommonJS export names for ESM import in node:
803
+ 0 && (module.exports = {
804
+ CoreTransportLogic,
805
+ setupKeyExchangeHandlers
806
+ });