UNPKG

pocket-messaging

Version:

A small cryptographic messaging library written in TypeScript both for browser and nodejs supporting TCP and WebSockets

94 lines (93 loc) 3.16 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.EncryptedClient = void 0; const Crypto_1 = require("./Crypto"); const pocket_sockets_1 = require("pocket-sockets"); /** * Wrap an already connected and handshooked socket client as encrypted. * */ class EncryptedClient extends pocket_sockets_1.WrappedClient { constructor(client, outgoingKey, outgoingNonce, incomingKey, incomingNonce, peerPublicKey) { super(client); this.outgoingKey = outgoingKey; this.outgoingNonce = outgoingNonce; this.incomingKey = incomingKey; this.incomingNonce = incomingNonce; this.peerPublicKey = peerPublicKey; this.handlers = {}; this.handleOnData = async (data) => { if (Buffer.isBuffer(data)) { this.incomingData = Buffer.concat([this.incomingData, data]); this.decryptData(); } else { throw new Error("EncryptedClient does not work with text data"); } }; this.incomingData = Buffer.alloc(0); } async init() { await super.init(); await (0, Crypto_1.init)(); // Init sodium } unRead(data) { throw new Error("unRead function not available in EncryptedClient"); } getPeerPublicKey() { return this.peerPublicKey; } decryptData() { const ret = (0, Crypto_1.unbox)(this.incomingData, this.incomingNonce, this.incomingKey); if (!ret) { // Not enough data in chunk return; } const [decrypted, nextNonce, bytesConsumed] = ret; this.incomingNonce = nextNonce; this.incomingData = this.incomingData.slice(bytesConsumed); this.triggerEvent("data", decrypted); if (this.incomingData.length > 0) { this.decryptData(); } } send(data) { if (Buffer.isBuffer(data)) { // encrypt data const [encryptedData, nextNonce] = (0, Crypto_1.box)(data, this.outgoingNonce, this.outgoingKey); this.outgoingNonce = nextNonce; this.client.send(encryptedData); } else { throw new Error("EncryptedClient does not work with text data"); } } onData(fn) { this.hookEvent("data", fn); if ((this.handlers["data"] ?? []).length === 1) { this.client.onData(this.handleOnData); } } offData(fn) { this.unhookEvent("data", fn); if ((this.handlers["data"] ?? []).length === 0) { this.client.offData(this.handleOnData); } } hookEvent(type, callback) { const cbs = this.handlers[type] || []; this.handlers[type] = cbs; cbs.push(callback); } unhookEvent(type, callback) { const cbs = (this.handlers[type] || []).filter((cb) => callback !== cb); this.handlers[type] = cbs; } triggerEvent(type, ...args) { const cbs = this.handlers[type] || []; cbs.forEach(callback => { callback(...args); }); } } exports.EncryptedClient = EncryptedClient;