Add encryption for chat groups
This commit is contained in:
parent
bbf5cc6b00
commit
8f702928bc
|
@ -44,6 +44,7 @@
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
|
"ecies-geth": "^1.5.3",
|
||||||
"js-sha3": "^0.8.0",
|
"js-sha3": "^0.8.0",
|
||||||
"js-waku": "^0.12.0",
|
"js-waku": "^0.12.0",
|
||||||
"protobufjs": "^6.11.2",
|
"protobufjs": "^6.11.2",
|
||||||
|
|
|
@ -1,13 +1,23 @@
|
||||||
import { ChatMessage } from "./chat_message";
|
import { ChatMessage } from "./chat_message";
|
||||||
import { chatIdToContentTopic } from "./contentTopic";
|
import { chatIdToContentTopic } from "./contentTopic";
|
||||||
|
import { createSymKeyFromPassword } from "./encryption";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Represent a chat room. Only public chats are currently supported.
|
||||||
|
*/
|
||||||
export class Chat {
|
export class Chat {
|
||||||
private lastClockValue?: number;
|
private lastClockValue?: number;
|
||||||
private lastMessage?: ChatMessage;
|
private lastMessage?: ChatMessage;
|
||||||
public id: string;
|
|
||||||
|
|
||||||
constructor(id: string) {
|
private constructor(public id: string, public symKey: Uint8Array) {}
|
||||||
this.id = id;
|
|
||||||
|
/**
|
||||||
|
* Create a public chat room.
|
||||||
|
*/
|
||||||
|
public static async create(id: string) {
|
||||||
|
const symKey = await createSymKeyFromPassword(id);
|
||||||
|
|
||||||
|
return new Chat(id, symKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
public get contentTopic(): string {
|
public get contentTopic(): string {
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
import { kdf } from "ecies-geth";
|
||||||
|
|
||||||
|
const AESKeyLength = 32; // bytes
|
||||||
|
|
||||||
|
export async function createSymKeyFromPassword(
|
||||||
|
password: string
|
||||||
|
): Promise<Uint8Array> {
|
||||||
|
return kdf(Buffer.from(password, "utf-8"), AESKeyLength);
|
||||||
|
}
|
|
@ -47,8 +47,8 @@ describe("Messenger", () => {
|
||||||
it("Sends & Receive message in public chat", async function () {
|
it("Sends & Receive message in public chat", async function () {
|
||||||
this.timeout(10_000);
|
this.timeout(10_000);
|
||||||
|
|
||||||
messengerAlice.joinChat(testChatId);
|
await messengerAlice.joinChat(testChatId);
|
||||||
messengerBob.joinChat(testChatId);
|
await messengerBob.joinChat(testChatId);
|
||||||
|
|
||||||
const text = "This is a message.";
|
const text = "This is a message.";
|
||||||
|
|
||||||
|
|
|
@ -39,10 +39,12 @@ export class Messenger {
|
||||||
*
|
*
|
||||||
* Use `addListener` to get messages received on this chat.
|
* Use `addListener` to get messages received on this chat.
|
||||||
*/
|
*/
|
||||||
public joinChat(chatId: string) {
|
public async joinChat(chatId: string) {
|
||||||
if (this.chatsById.has(chatId)) throw "Chat already joined";
|
if (this.chatsById.has(chatId)) throw "Chat already joined";
|
||||||
|
|
||||||
const chat = new Chat(chatId);
|
const chat = await Chat.create(chatId);
|
||||||
|
|
||||||
|
this.waku.relay.addDecryptionKey(chat.symKey);
|
||||||
|
|
||||||
this.waku.relay.addObserver(
|
this.waku.relay.addObserver(
|
||||||
(wakuMessage: WakuMessage) => {
|
(wakuMessage: WakuMessage) => {
|
||||||
|
@ -72,7 +74,7 @@ export class Messenger {
|
||||||
*/
|
*/
|
||||||
public async sendMessage(text: string, chatId: string): Promise<void> {
|
public async sendMessage(text: string, chatId: string): Promise<void> {
|
||||||
const chat = this.chatsById.get(chatId);
|
const chat = this.chatsById.get(chatId);
|
||||||
if (!chat) throw `Chat not joined: ${chatId}`;
|
if (!chat) throw `Failed to send message, chat not joined: ${chatId}`;
|
||||||
|
|
||||||
const chatMessage = chat.createMessage(text);
|
const chatMessage = chat.createMessage(text);
|
||||||
|
|
||||||
|
@ -82,10 +84,11 @@ export class Messenger {
|
||||||
this.identity
|
this.identity
|
||||||
);
|
);
|
||||||
|
|
||||||
// TODO: Use version 1 with signature
|
// TODO: Add signature
|
||||||
const wakuMessage = await WakuMessage.fromBytes(
|
const wakuMessage = await WakuMessage.fromBytes(
|
||||||
appMetadataMessage.encode(),
|
appMetadataMessage.encode(),
|
||||||
chat.contentTopic
|
chat.contentTopic,
|
||||||
|
{ symKey: chat.symKey }
|
||||||
);
|
);
|
||||||
|
|
||||||
await this.waku.relay.send(wakuMessage);
|
await this.waku.relay.send(wakuMessage);
|
||||||
|
|
|
@ -1734,7 +1734,7 @@ __metadata:
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"ecies-geth@npm:^1.5.2":
|
"ecies-geth@npm:^1.5.2, ecies-geth@npm:^1.5.3":
|
||||||
version: 1.5.3
|
version: 1.5.3
|
||||||
resolution: "ecies-geth@npm:1.5.3"
|
resolution: "ecies-geth@npm:1.5.3"
|
||||||
dependencies:
|
dependencies:
|
||||||
|
@ -5635,6 +5635,7 @@ fsevents@~2.3.2:
|
||||||
"@typescript-eslint/parser": ^4.31.1
|
"@typescript-eslint/parser": ^4.31.1
|
||||||
buffer: ^6.0.3
|
buffer: ^6.0.3
|
||||||
chai: ^4.3.4
|
chai: ^4.3.4
|
||||||
|
ecies-geth: ^1.5.3
|
||||||
eslint: ^7.32.0
|
eslint: ^7.32.0
|
||||||
eslint-config-prettier: ^8.3.0
|
eslint-config-prettier: ^8.3.0
|
||||||
eslint-import-resolver-node: ^0.3.6
|
eslint-import-resolver-node: ^0.3.6
|
||||||
|
|
Loading…
Reference in New Issue