Add encryption for chat groups

This commit is contained in:
Franck Royer 2021-09-23 15:42:15 +10:00
parent bbf5cc6b00
commit 8f702928bc
No known key found for this signature in database
GPG Key ID: A82ED75A8DFC50A4
6 changed files with 35 additions and 11 deletions

View File

@ -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",

View File

@ -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 {

View File

@ -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);
}

View File

@ -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.";

View File

@ -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<void> {
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);

View File

@ -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