🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
Book a DemoInstallSign in
Socket

@crypticat/core

Package Overview
Dependencies
Maintainers
1
Versions
21
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@crypticat/core - npm Package Compare versions

Comparing version

to
0.2.0

25

lib/client.d.ts
/// <reference types="node" />
import WebSocket from 'isomorphic-ws';
import { DiffieHellman, Cipher, Decipher } from 'crypto';

@@ -10,2 +9,3 @@ import { EventEmitter } from 'events';

decipher: Decipher;
nick: string | null;
}

@@ -18,19 +18,22 @@ export interface LinkState {

declare interface CrypticatClient {
on(event: 'message', listener: (nick: string, content: string) => void): this;
on(event: 'disconnect', listener: () => void): this;
on(event: 'message', listener: (userUid: string, nick: string | null, content: string) => void): this;
on(event: 'close', listener: () => void): this;
on(event: 'error', listener: (error: Error) => void): this;
on(event: 'connect', listener: (uid: string, nick: string | null) => void): this;
on(event: 'disconnect', listener: (uid: string, nick: string | null) => void): this;
}
declare class CrypticatClient extends EventEmitter {
linkState: LinkState;
room: string | null;
ws?: WebSocket;
private linkState;
private linkedNextYet;
private nick;
private ws?;
constructor();
connect(address: string): Promise<void>;
sendEncrypted(dir: 'next' | 'prev', message: {
action: string;
payload: object;
}): void;
joinRoom(name: string): Promise<void>;
sendMessage(nick: string, content: string): void;
sendMessage(content: string): void;
setNick(nick: string | null): void;
getNick(): string | null;
private assertWs;
private sendEncrypted;
}
export { CrypticatClient };

@@ -29,3 +29,4 @@ "use strict";

};
this.room = null;
this.linkedNextYet = false;
this.nick = '';
}

@@ -53,74 +54,104 @@ connect(address) {

this.ws.addEventListener('message', (message) => {
lib_1.assertDefined(this.ws);
const { action, payload } = JSON.parse(message.data);
switch (action) {
case 'GENERATE_KEY': {
this.linkState.df = crypto_1.default.createDiffieHellman(Buffer.from(payload.prime, 'hex'));
const key = this.linkState.df.generateKeys();
this.ws.send(JSON.stringify({
action: 'KEY',
payload: {
key: key.toString('hex')
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
try {
lib_1.assertDefined(this.ws);
const { action, payload } = JSON.parse(message.data);
switch (action) {
case 'GENERATE_KEY': {
lib_1.assertDefined(payload.prime);
this.linkState.df = crypto_1.default.createDiffieHellman(Buffer.from(payload.prime, 'hex'));
const key = this.linkState.df.generateKeys();
this.ws.send(JSON.stringify({
action: 'KEY',
payload: {
key: key.toString('hex')
}
}));
break;
}
case 'PREV_LINK':
case 'NEXT_LINK': {
lib_1.assertDefined(payload.key);
lib_1.assertDefined(payload.uid);
const dir = action === 'PREV_LINK' ? 'prev' : 'next';
if (action === 'NEXT_LINK' && !this.linkedNextYet) {
this.linkedNextYet = true;
this.emit('connect', payload.uid, (_a = payload.nick) !== null && _a !== void 0 ? _a : null);
this.sendEncrypted('prev', {
action: 'CONNECT',
payload: { uid: payload.uid, nick: payload.nick }
});
}
}));
break;
}
case 'PREV_LINK':
case 'NEXT_LINK': {
const dir = action === 'PREV_LINK' ? 'prev' : 'next';
lib_1.assertDefined(this.linkState.df);
const secret = this.linkState.df.computeSecret(Buffer.from(payload.key, 'hex'));
this.linkState[dir] = {
secret,
cipher: crypto_1.default.createCipheriv('aes-256-gcm', secret, iv),
decipher: crypto_1.default.createDecipheriv('aes-256-gcm', secret, iv),
uid: payload.uid
};
break;
}
case 'CLEAR_PREV_LINK':
case 'CLEAR_NEXT_LINK': {
const dir = action === 'CLEAR_PREV_LINK' ? 'prev' : 'next';
delete this.linkState[dir];
break;
}
case 'ENCRYPTED_PAYLOAD': {
if (payload.dir !== 'prev' && payload.dir !== 'next')
else if (this.linkedNextYet) {
console.log('DISCONNECTED', dir);
lib_1.assertDefined(this.linkState[dir]);
this.emit('disconnect', (_b = this.linkState[dir]) === null || _b === void 0 ? void 0 : _b.uid, (_d = (_c = this.linkState[dir]) === null || _c === void 0 ? void 0 : _c.nick) !== null && _d !== void 0 ? _d : null);
this.sendEncrypted(dir === 'prev' ? 'next' : 'prev', {
action: 'DISCONNECT',
payload: { uid: (_e = this.linkState[dir]) === null || _e === void 0 ? void 0 : _e.uid, nick: (_f = this.linkState[dir]) === null || _f === void 0 ? void 0 : _f.nick }
});
}
lib_1.assertDefined(this.linkState.df);
const secret = this.linkState.df.computeSecret(Buffer.from(payload.key, 'hex'));
this.linkState[dir] = {
secret,
cipher: crypto_1.default.createCipheriv('aes-256-gcm', secret, iv),
decipher: crypto_1.default.createDecipheriv('aes-256-gcm', secret, iv),
uid: payload.uid,
nick: payload.nick
};
break;
const inverseLink = this.linkState[payload.dir === 'prev' ? 'next' : 'prev'];
lib_1.assertDefined(inverseLink);
const decryptedMessage = inverseLink.decipher.update(Buffer.from(payload.encryptedMessage, 'hex'));
const parsed = JSON.parse(decryptedMessage.toString());
{
const { action, payload } = parsed;
switch (action) {
case 'MESSAGE': {
this.emit('message', payload.nick, payload.content);
break;
}
case 'CLEAR_PREV_LINK':
case 'CLEAR_NEXT_LINK': {
const dir = action === 'CLEAR_PREV_LINK' ? 'prev' : 'next';
delete this.linkState[dir];
break;
}
case 'ENCRYPTED_PAYLOAD': {
if (payload.dir !== 'prev' && payload.dir !== 'next')
break;
const inverseLink = this.linkState[payload.dir === 'prev' ? 'next' : 'prev'];
lib_1.assertDefined(inverseLink);
const decryptedMessage = inverseLink.decipher.update(Buffer.from(payload.encryptedMessage, 'hex'));
const parsed = JSON.parse(decryptedMessage.toString());
lib_1.assertDefined(payload.directFrom);
const originalFrom = (_g = parsed.from) !== null && _g !== void 0 ? _g : payload.directFrom;
{
const { action, payload } = parsed.message;
switch (action) {
case 'MESSAGE': {
lib_1.assertDefined(payload.content);
this.emit('message', originalFrom, payload.nick, payload.content);
if (inverseLink.uid === originalFrom) {
inverseLink.nick = payload.nick;
}
break;
}
case 'CONNECT': {
lib_1.assertDefined(payload.uid);
this.emit('connect', payload.uid, (_h = payload.nick) !== null && _h !== void 0 ? _h : null);
break;
}
case 'DISCONNECT': {
lib_1.assertDefined(payload.uid);
this.emit('disconnect', payload.uid, (_j = payload.nick) !== null && _j !== void 0 ? _j : null);
break;
}
}
}
const nextDir = payload.dir;
if (this.linkState[nextDir])
this.sendEncrypted(nextDir, parsed.message, originalFrom);
break;
}
const nextDir = payload.dir;
if (this.linkState[nextDir])
this.sendEncrypted(nextDir, parsed);
break;
}
}
catch (error) {
this.emit('error', error);
}
});
this.ws.addEventListener('close', () => this.emit('disconnect'));
this.ws.addEventListener('close', () => this.emit('close'));
});
}
sendEncrypted(dir, message) {
this.assertWs(this.ws);
const link = this.linkState[dir];
lib_1.assertDefined(link);
this.ws.send(JSON.stringify({
action: 'DISPATCH_ENCRYPTED',
payload: {
recipient: link.uid,
encryptedMessage: link.cipher.update(JSON.stringify(message)).toString('hex'),
dir
}
}));
}
joinRoom(name) {

@@ -131,3 +162,3 @@ return __awaiter(this, void 0, void 0, function* () {

action: 'JOIN_ROOM',
payload: { name }
payload: { name, nick: this.nick }
}));

@@ -137,7 +168,7 @@ this.linkState.df = null;

this.linkState.prev = null;
this.linkedNextYet = false;
yield lib_1.waitFor(this.ws, 'ROOM_READY');
this.room = name;
});
}
sendMessage(nick, content) {
sendMessage(content) {
this.assertWs(this.ws);

@@ -147,3 +178,3 @@ if (this.linkState.next) {

action: 'MESSAGE',
payload: { content, nick }
payload: { content, nick: this.nick }
});

@@ -154,13 +185,37 @@ }

action: 'MESSAGE',
payload: { content, nick }
payload: { content, nick: this.nick }
});
}
}
setNick(nick) {
this.nick = nick;
}
getNick() {
return this.nick;
}
assertWs(ws) {
if (ws === undefined || ws.readyState !== 1) {
throw new assert_1.AssertionError({ message: 'The websocket is not open!' });
if ((ws === null || ws === void 0 ? void 0 : ws.readyState) !== 1) {
throw new assert_1.AssertionError({
message: 'The websocket is not open!',
expected: 1,
actual: ws === null || ws === void 0 ? void 0 : ws.readyState
});
}
}
sendEncrypted(dir, message, from) {
this.assertWs(this.ws);
const link = this.linkState[dir];
if (!link)
return;
this.ws.send(JSON.stringify({
action: 'DISPATCH_ENCRYPTED',
payload: {
recipient: link.uid,
encryptedMessage: link.cipher.update(JSON.stringify({ message, from })).toString('hex'),
dir
}
}));
}
}
exports.CrypticatClient = CrypticatClient;
//# sourceMappingURL=client.js.map

@@ -16,3 +16,6 @@ "use strict";

if (thing === null || thing === undefined) {
throw new assert_1.AssertionError({ message: `Expected 'thing' to be defined, but received ${thing}` });
throw new assert_1.AssertionError({
message: `Expected thing to be defined`,
actual: thing
});
}

@@ -19,0 +22,0 @@ }

/// <reference types="node" />
import WebSocket from 'isomorphic-ws';
import { EventEmitter } from 'events';

@@ -13,3 +12,3 @@ import { Server as HttpServer } from 'http';

on(event: 'connect', listener: (uid: string) => void): this;
on(event: 'join', listener: (uid: string, room: string) => void): this;
on(event: 'join', listener: (uid: string, room: string, nick: string | null) => void): this;
on(event: 'dispatch', listener: (fromUid: string, toUid: string) => void): this;

@@ -19,7 +18,5 @@ on(event: 'disconnect', listener: (uid: string) => void): this;

declare class CrypticatServer extends EventEmitter {
sockets: {
[key: string]: WebSocket;
};
rooms: Room[];
wss?: WebSocket.Server;
private sockets;
private rooms;
private wss?;
constructor();

@@ -26,0 +23,0 @@ listen(location: HttpServer | HttpsServer | number, path?: string): void;

@@ -95,9 +95,10 @@ "use strict";

ws.addEventListener('message', (message) => __awaiter(this, void 0, void 0, function* () {
var _a;
const { action, payload } = JSON.parse(message.data);
switch (action) {
case 'JOIN_ROOM': {
this.emit('join', uid, payload.name);
if (room) {
lib_1.assertDefined(payload.name);
this.emit('join', uid, payload.name, (_a = payload.nick) !== null && _a !== void 0 ? _a : null);
if (room)
yield leaveRoom();
}
const existingRoom = this.rooms.find(({ name }) => name === payload.name);

@@ -135,3 +136,3 @@ if (!existingRoom) {

action: 'NEXT_LINK',
payload: { key: bobKey, uid }
payload: { key: bobKey, uid, nick: payload.nick }
}));

@@ -147,2 +148,5 @@ existingRoom.links.unshift(uid);

case 'DISPATCH_ENCRYPTED': {
lib_1.assertDefined(payload.recipient);
lib_1.assertDefined(payload.encryptedMessage);
lib_1.assertDefined(payload.dir);
this.emit('dispatch', uid, payload.recipient);

@@ -152,4 +156,4 @@ const recipientWs = this.sockets[payload.recipient];

action: 'ENCRYPTED_PAYLOAD',
from: uid,
payload: {
directFrom: uid,
encryptedMessage: payload.encryptedMessage,

@@ -156,0 +160,0 @@ dir: payload.dir

{
"name": "@crypticat/core",
"version": "0.1.10",
"version": "0.2.0",
"description": "Crypticat's core client and server implementation",

@@ -5,0 +5,0 @@ "author": "Kognise <felix.mattick@gmail.com>",

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet