MLS implementation

This commit is contained in:
Danny Morabito 2025-03-11 20:50:33 +01:00
parent fc6e1c59a5
commit a69e78389f
Signed by: dannym
GPG key ID: 7CC8056A5A04557E
5 changed files with 743 additions and 6 deletions

View file

@ -7,6 +7,7 @@ import type {
import {
getCCNPrivateKey,
getCCNPubkey,
getMLSPrivateKey,
isArray,
isLocalhost,
isValidJSON,
@ -21,6 +22,7 @@ import { mixQuery, sql, sqlPartial } from "./utils/queries.ts";
import { log, setupLogger } from "./utils/logs.ts";
import { getEveFilePath } from "./utils/files.ts";
import { MIN_POW, POW_TO_MINE } from "./consts.ts";
import { MLS } from "./mls.ts";
await setupLogger();
@ -36,6 +38,7 @@ if (!Deno.env.has("ENCRYPTION_KEY")) {
}
const db = new Database(await getEveFilePath("db"));
const mls = new MLS(await getMLSPrivateKey());
const pool = new nostrTools.SimplePool();
const relays = [
"wss://relay.arx-ccn.com/",
@ -114,10 +117,14 @@ async function createEncryptedEvent(
const randomPrivateKey = nostrTools.generateSecretKey();
const randomPrivateKeyPubKey = nostrTools.getPublicKey(randomPrivateKey);
const conversationKey = nip44.getConversationKey(randomPrivateKey, ccnPubKey);
const mlsEncryptedEvent = JSON.stringify(mls.encryptMessage(
ccnPubKey,
JSON.stringify(event),
));
const sealTemplate = {
kind: 13,
created_at: randomTimeUpTo2DaysInThePast(),
content: nip44.encrypt(JSON.stringify(event), conversationKey),
content: nip44.encrypt(mlsEncryptedEvent, conversationKey),
tags: [],
};
const seal = nostrTools.finalizeEvent(sealTemplate, ccnPrivateKey);
@ -136,25 +143,31 @@ async function createEncryptedEvent(
async function decryptEvent(
event: nostrTools.Event,
): Promise<nostrTools.VerifiedEvent> {
const ccnPrivkey = await getCCNPrivateKey();
if (event.kind !== 1059) {
throw new Error("Cannot decrypt event -- not a gift wrap");
}
const pow = nostrTools.nip13.getPow(event.id);
if (pow < MIN_POW) {
throw new Error("Cannot decrypt event -- PoW too low");
}
const conversationKey = nip44.getConversationKey(ccnPrivkey, event.pubkey);
const ccnPrivateKey = await getCCNPrivateKey();
const conversationKey = nip44.getConversationKey(ccnPrivateKey, event.pubkey);
const seal = JSON.parse(nip44.decrypt(event.content, conversationKey));
if (!seal) throw new Error("Cannot decrypt event -- no seal");
if (seal.kind !== 13) {
throw new Error("Cannot decrypt event subevent -- not a seal");
}
const content = JSON.parse(nip44.decrypt(seal.content, conversationKey));
const mlsEncryptedContent = JSON.parse(
nip44.decrypt(seal.content, conversationKey),
);
if (!mlsEncryptedContent) {
throw new Error("Cannot decrypt event -- no mls content");
}
const content = JSON.parse(
mls.decryptMessage(await getCCNPubkey(), mlsEncryptedContent)!,
);
return content as nostrTools.VerifiedEvent;
}