From 8f702928bc1216718f934d376354cd5e6e400e08 Mon Sep 17 00:00:00 2001 From: Franck Royer Date: Thu, 23 Sep 2021 15:42:15 +1000 Subject: [PATCH] Add encryption for chat groups --- packages/status-communities/package.json | 1 + packages/status-communities/src/chat.ts | 16 +++++++++++++--- packages/status-communities/src/encryption.ts | 9 +++++++++ .../status-communities/src/messenger.spec.ts | 4 ++-- packages/status-communities/src/messenger.ts | 13 ++++++++----- yarn.lock | 3 ++- 6 files changed, 35 insertions(+), 11 deletions(-) create mode 100644 packages/status-communities/src/encryption.ts diff --git a/packages/status-communities/package.json b/packages/status-communities/package.json index cf5a4389..09a82cd4 100644 --- a/packages/status-communities/package.json +++ b/packages/status-communities/package.json @@ -44,6 +44,7 @@ }, "dependencies": { "buffer": "^6.0.3", + "ecies-geth": "^1.5.3", "js-sha3": "^0.8.0", "js-waku": "^0.12.0", "protobufjs": "^6.11.2", diff --git a/packages/status-communities/src/chat.ts b/packages/status-communities/src/chat.ts index 2de593a1..20abeb14 100644 --- a/packages/status-communities/src/chat.ts +++ b/packages/status-communities/src/chat.ts @@ -1,13 +1,23 @@ import { ChatMessage } from "./chat_message"; import { chatIdToContentTopic } from "./contentTopic"; +import { createSymKeyFromPassword } from "./encryption"; +/** + * Represent a chat room. Only public chats are currently supported. + */ export class Chat { private lastClockValue?: number; private lastMessage?: ChatMessage; - public id: string; - constructor(id: string) { - this.id = id; + private constructor(public id: string, public symKey: Uint8Array) {} + + /** + * 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 { diff --git a/packages/status-communities/src/encryption.ts b/packages/status-communities/src/encryption.ts new file mode 100644 index 00000000..4aa297b2 --- /dev/null +++ b/packages/status-communities/src/encryption.ts @@ -0,0 +1,9 @@ +import { kdf } from "ecies-geth"; + +const AESKeyLength = 32; // bytes + +export async function createSymKeyFromPassword( + password: string +): Promise { + return kdf(Buffer.from(password, "utf-8"), AESKeyLength); +} diff --git a/packages/status-communities/src/messenger.spec.ts b/packages/status-communities/src/messenger.spec.ts index e6441f7f..dd074b8f 100644 --- a/packages/status-communities/src/messenger.spec.ts +++ b/packages/status-communities/src/messenger.spec.ts @@ -47,8 +47,8 @@ describe("Messenger", () => { it("Sends & Receive message in public chat", async function () { this.timeout(10_000); - messengerAlice.joinChat(testChatId); - messengerBob.joinChat(testChatId); + await messengerAlice.joinChat(testChatId); + await messengerBob.joinChat(testChatId); const text = "This is a message."; diff --git a/packages/status-communities/src/messenger.ts b/packages/status-communities/src/messenger.ts index 0436a96d..05cfbb89 100644 --- a/packages/status-communities/src/messenger.ts +++ b/packages/status-communities/src/messenger.ts @@ -39,10 +39,12 @@ export class Messenger { * * 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"; - const chat = new Chat(chatId); + const chat = await Chat.create(chatId); + + this.waku.relay.addDecryptionKey(chat.symKey); this.waku.relay.addObserver( (wakuMessage: WakuMessage) => { @@ -72,7 +74,7 @@ export class Messenger { */ public async sendMessage(text: string, chatId: string): Promise { 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); @@ -82,10 +84,11 @@ export class Messenger { this.identity ); - // TODO: Use version 1 with signature + // TODO: Add signature const wakuMessage = await WakuMessage.fromBytes( appMetadataMessage.encode(), - chat.contentTopic + chat.contentTopic, + { symKey: chat.symKey } ); await this.waku.relay.send(wakuMessage); diff --git a/yarn.lock b/yarn.lock index c5160f68..7a787ad0 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1734,7 +1734,7 @@ __metadata: languageName: node linkType: hard -"ecies-geth@npm:^1.5.2": +"ecies-geth@npm:^1.5.2, ecies-geth@npm:^1.5.3": version: 1.5.3 resolution: "ecies-geth@npm:1.5.3" dependencies: @@ -5635,6 +5635,7 @@ fsevents@~2.3.2: "@typescript-eslint/parser": ^4.31.1 buffer: ^6.0.3 chai: ^4.3.4 + ecies-geth: ^1.5.3 eslint: ^7.32.0 eslint-config-prettier: ^8.3.0 eslint-import-resolver-node: ^0.3.6