175 lines
6.9 KiB
JavaScript
175 lines
6.9 KiB
JavaScript
"use strict";
|
|
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
}
|
|
Object.defineProperty(o, k2, desc);
|
|
}) : (function(o, m, k, k2) {
|
|
if (k2 === undefined) k2 = k;
|
|
o[k2] = m[k];
|
|
}));
|
|
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
}) : function(o, v) {
|
|
o["default"] = v;
|
|
});
|
|
var __importStar = (this && this.__importStar) || function (mod) {
|
|
if (mod && mod.__esModule) return mod;
|
|
var result = {};
|
|
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
__setModuleDefault(result, mod);
|
|
return result;
|
|
};
|
|
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, state, kind, f) {
|
|
if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
|
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
|
|
return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
|
|
};
|
|
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
};
|
|
var _a, _EventExt_getDmSharedKey;
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.EventExt = void 0;
|
|
const secp = __importStar(require("@noble/curves/secp256k1"));
|
|
const utils = __importStar(require("@noble/curves/abstract/utils"));
|
|
const _1 = require(".");
|
|
const base64_1 = __importDefault(require("@protobufjs/base64"));
|
|
const Util_1 = require("./Util");
|
|
class EventExt {
|
|
/**
|
|
* Get the pub key of the creator of this event NIP-26
|
|
*/
|
|
static getRootPubKey(e) {
|
|
const delegation = e.tags.find(a => a[0] === "delegation");
|
|
if (delegation?.[1]) {
|
|
// todo: verify sig
|
|
return delegation[1];
|
|
}
|
|
return e.pubkey;
|
|
}
|
|
/**
|
|
* Sign this message with a private key
|
|
*/
|
|
static sign(e, key) {
|
|
e.id = this.createId(e);
|
|
const sig = secp.schnorr.sign(e.id, key);
|
|
e.sig = utils.bytesToHex(sig);
|
|
if (!(secp.schnorr.verify(e.sig, e.id, e.pubkey))) {
|
|
throw new Error("Signing failed");
|
|
}
|
|
}
|
|
/**
|
|
* Check the signature of this message
|
|
* @returns True if valid signature
|
|
*/
|
|
static verify(e) {
|
|
const id = this.createId(e);
|
|
const result = secp.schnorr.verify(e.sig, id, e.pubkey);
|
|
return result;
|
|
}
|
|
static createId(e) {
|
|
const payload = [0, e.pubkey, e.created_at, e.kind, e.tags, e.content];
|
|
const hash = (0, Util_1.sha256)(JSON.stringify(payload));
|
|
if (e.id !== "" && hash !== e.id) {
|
|
console.debug(payload);
|
|
throw new Error("ID doesnt match!");
|
|
}
|
|
return hash;
|
|
}
|
|
/**
|
|
* Create a new event for a specific pubkey
|
|
*/
|
|
static forPubKey(pk, kind) {
|
|
return {
|
|
pubkey: pk,
|
|
kind: kind,
|
|
created_at: (0, Util_1.unixNow)(),
|
|
content: "",
|
|
tags: [],
|
|
id: "",
|
|
sig: "",
|
|
};
|
|
}
|
|
static extractThread(ev) {
|
|
const isThread = ev.tags.some(a => (a[0] === "e" && a[3] !== "mention") || a[0] == "a");
|
|
if (!isThread) {
|
|
return undefined;
|
|
}
|
|
const shouldWriteMarkers = ev.kind === _1.EventKind.TextNote;
|
|
const ret = {
|
|
mentions: [],
|
|
pubKeys: [],
|
|
};
|
|
const eTags = ev.tags.filter(a => a[0] === "e" || a[0] === "a").map((v, i) => new _1.Tag(v, i));
|
|
const marked = eTags.some(a => a.Marker !== undefined);
|
|
if (!marked) {
|
|
ret.root = eTags[0];
|
|
ret.root.Marker = shouldWriteMarkers ? "root" : undefined;
|
|
if (eTags.length > 1) {
|
|
ret.replyTo = eTags[1];
|
|
ret.replyTo.Marker = shouldWriteMarkers ? "reply" : undefined;
|
|
}
|
|
if (eTags.length > 2) {
|
|
ret.mentions = eTags.slice(2);
|
|
if (shouldWriteMarkers) {
|
|
ret.mentions.forEach(a => (a.Marker = "mention"));
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
const root = eTags.find(a => a.Marker === "root");
|
|
const reply = eTags.find(a => a.Marker === "reply");
|
|
ret.root = root;
|
|
ret.replyTo = reply;
|
|
ret.mentions = eTags.filter(a => a.Marker === "mention");
|
|
}
|
|
ret.pubKeys = Array.from(new Set(ev.tags.filter(a => a[0] === "p").map(a => a[1])));
|
|
return ret;
|
|
}
|
|
/**
|
|
* Encrypt the given message content
|
|
*/
|
|
static async encryptData(content, pubkey, privkey) {
|
|
const key = await __classPrivateFieldGet(this, _a, "m", _EventExt_getDmSharedKey).call(this, pubkey, privkey);
|
|
const iv = window.crypto.getRandomValues(new Uint8Array(16));
|
|
const data = new TextEncoder().encode(content);
|
|
const result = await window.crypto.subtle.encrypt({
|
|
name: "AES-CBC",
|
|
iv: iv,
|
|
}, key, data);
|
|
const uData = new Uint8Array(result);
|
|
return `${base64_1.default.encode(uData, 0, result.byteLength)}?iv=${base64_1.default.encode(iv, 0, 16)}`;
|
|
}
|
|
/**
|
|
* Decrypt the content of the message
|
|
*/
|
|
static async decryptData(cyphertext, privkey, pubkey) {
|
|
const key = await __classPrivateFieldGet(this, _a, "m", _EventExt_getDmSharedKey).call(this, pubkey, privkey);
|
|
const cSplit = cyphertext.split("?iv=");
|
|
const data = new Uint8Array(base64_1.default.length(cSplit[0]));
|
|
base64_1.default.decode(cSplit[0], data, 0);
|
|
const iv = new Uint8Array(base64_1.default.length(cSplit[1]));
|
|
base64_1.default.decode(cSplit[1], iv, 0);
|
|
const result = await window.crypto.subtle.decrypt({
|
|
name: "AES-CBC",
|
|
iv: iv,
|
|
}, key, data);
|
|
return new TextDecoder().decode(result);
|
|
}
|
|
/**
|
|
* Decrypt the content of this message in place
|
|
*/
|
|
static async decryptDm(content, privkey, pubkey) {
|
|
return await this.decryptData(content, privkey, pubkey);
|
|
}
|
|
}
|
|
exports.EventExt = EventExt;
|
|
_a = EventExt, _EventExt_getDmSharedKey = async function _EventExt_getDmSharedKey(pubkey, privkey) {
|
|
const sharedPoint = secp.secp256k1.getSharedSecret(privkey, "02" + pubkey);
|
|
const sharedX = sharedPoint.slice(1, 33);
|
|
return await window.crypto.subtle.importKey("raw", sharedX, { name: "AES-CBC" }, false, ["encrypt", "decrypt"]);
|
|
};
|
|
//# sourceMappingURL=EventExt.js.map
|