From 9584cc69507fa312726e4071539bc62ee1947fc5 Mon Sep 17 00:00:00 2001 From: Jonathan Staab Date: Thu, 10 Aug 2023 14:30:32 -0700 Subject: [PATCH] feat: add NIP 44 encryption support --- package.json | 3 + src/common/utils/lruCache.ts | 29 ++++++++ .../actions/nostr/nip44DecryptOrPrompt.ts | 70 +++++++++++++++++++ .../actions/nostr/nip44EncryptOrPrompt.ts | 70 +++++++++++++++++++ .../nostr/__test__/nostr.test.ts | 35 +++++++++- .../background-script/nostr/index.ts | 66 ++++++++++++++++- src/extension/providers/nostr/index.ts | 23 ++++++ src/i18n/locales/cs/translation.json | 4 +- src/i18n/locales/da/translation.json | 4 +- src/i18n/locales/de/translation.json | 2 + src/i18n/locales/en/translation.json | 2 + src/i18n/locales/es/translation.json | 6 +- src/i18n/locales/fa/translation.json | 4 +- src/i18n/locales/fr/translation.json | 4 +- src/i18n/locales/hi/translation.json | 4 +- src/i18n/locales/id/translation.json | 6 +- src/i18n/locales/it/translation.json | 4 +- src/i18n/locales/mr/translation.json | 4 +- src/i18n/locales/pl/translation.json | 4 +- src/i18n/locales/ro/translation.json | 4 +- src/i18n/locales/ru/translation.json | 4 +- src/i18n/locales/sv/translation.json | 8 ++- src/i18n/locales/uk/translation.json | 4 +- src/i18n/locales/zh_Hans/translation.json | 6 +- src/i18n/locales/zh_Hant/translation.json | 4 +- src/types.ts | 19 +++++ yarn.lock | 9 ++- 27 files changed, 375 insertions(+), 27 deletions(-) create mode 100644 src/common/utils/lruCache.ts create mode 100644 src/extension/background-script/actions/nostr/nip44DecryptOrPrompt.ts create mode 100644 src/extension/background-script/actions/nostr/nip44EncryptOrPrompt.ts diff --git a/package.json b/package.json index 5bae111279..9668d666aa 100644 --- a/package.json +++ b/package.json @@ -38,8 +38,11 @@ "@bitcoin-design/bitcoin-icons-react": "^0.1.9", "@headlessui/react": "^1.7.16", "@lightninglabs/lnc-web": "^0.2.4-alpha", + "@noble/ciphers": "^0.2.0", "@noble/curves": "^1.1.0", + "@noble/hashes": "^1.3.1", "@noble/secp256k1": "^2.0.0", + "@scure/base": "^1.1.1", "@scure/bip32": "^1.3.1", "@scure/bip39": "^1.2.1", "@scure/btc-signer": "^0.5.1", diff --git a/src/common/utils/lruCache.ts b/src/common/utils/lruCache.ts new file mode 100644 index 0000000000..269b14e758 --- /dev/null +++ b/src/common/utils/lruCache.ts @@ -0,0 +1,29 @@ +export class LRUCache { + map = new Map(); + keys: T[] = []; + + constructor(readonly maxSize: number) {} + + has(k: T) { + return this.map.has(k); + } + + get(k: T) { + const v = this.map.get(k); + + if (v !== undefined) { + this.keys.push(this.keys.shift() as T); + } + + return v; + } + + set(k: T, v: U) { + this.map.set(k, v); + this.keys.push(k); + + if (this.map.size > this.maxSize) { + this.map.delete(this.keys.shift() as T); + } + } +} diff --git a/src/extension/background-script/actions/nostr/nip44DecryptOrPrompt.ts b/src/extension/background-script/actions/nostr/nip44DecryptOrPrompt.ts new file mode 100644 index 0000000000..479c3814cd --- /dev/null +++ b/src/extension/background-script/actions/nostr/nip44DecryptOrPrompt.ts @@ -0,0 +1,70 @@ +import { USER_REJECTED_ERROR } from "~/common/constants"; +import utils from "~/common/lib/utils"; +import { getHostFromSender } from "~/common/utils/helpers"; +import state from "~/extension/background-script/state"; +import i18n from "~/i18n/i18nConfig"; +import { Nip44MessageDecryptGet, PermissionMethodNostr, Sender } from "~/types"; + +import { addPermissionFor, hasPermissionFor } from "./helpers"; + +const nip44DecryptOrPrompt = async ( + message: Nip44MessageDecryptGet, + sender: Sender +) => { + const host = getHostFromSender(sender); + if (!host) return; + + try { + const hasPermission = await hasPermissionFor( + PermissionMethodNostr["NOSTR_NIP44DECRYPT"], + host + ); + + if (hasPermission) { + const nostr = await state.getState().getNostr(); + const response = await nostr.nip44Decrypt( + message.args.peer, + message.args.payload + ); + + return { data: response }; + } else { + const promptResponse = await utils.openPrompt<{ + confirm: boolean; + rememberPermission: boolean; + }>({ + ...message, + action: "public/nostr/confirm", + args: { + description: i18n.t("permissions:nostr.nip44decrypt"), + }, + }); + + // add permission to db only if user decided to always allow this request + if (promptResponse.data.rememberPermission) { + await addPermissionFor( + PermissionMethodNostr["NOSTR_NIP44DECRYPT"], + host + ); + } + if (promptResponse.data.confirm) { + const nostr = await state.getState().getNostr(); + const response = await nostr.nip44Decrypt( + message.args.peer, + message.args.payload + ); + + return { data: response }; + } else { + return { error: USER_REJECTED_ERROR }; + } + } + } catch (e) { + console.error("decrypt failed", e); + if (e instanceof Error) { + return { error: e.message }; + } + } +}; + +export default nip44DecryptOrPrompt; diff --git a/src/extension/background-script/actions/nostr/nip44EncryptOrPrompt.ts b/src/extension/background-script/actions/nostr/nip44EncryptOrPrompt.ts new file mode 100644 index 0000000000..0c4d2aa872 --- /dev/null +++ b/src/extension/background-script/actions/nostr/nip44EncryptOrPrompt.ts @@ -0,0 +1,70 @@ +import { USER_REJECTED_ERROR } from "~/common/constants"; +import utils from "~/common/lib/utils"; +import { getHostFromSender } from "~/common/utils/helpers"; +import state from "~/extension/background-script/state"; +import i18n from "~/i18n/i18nConfig"; +import { Nip44MessageEncryptGet, PermissionMethodNostr, Sender } from "~/types"; + +import { addPermissionFor, hasPermissionFor } from "./helpers"; + +const nip44EncryptOrPrompt = async ( + message: Nip44MessageEncryptGet, + sender: Sender +) => { + const host = getHostFromSender(sender); + if (!host) return; + + try { + const hasPermission = await hasPermissionFor( + PermissionMethodNostr["NOSTR_NIP44ENCRYPT"], + host + ); + + if (hasPermission) { + const response = (await state.getState().getNostr()).nip44Encrypt( + message.args.peer, + message.args.plaintext, + message.args.v + ); + + return { data: response }; + } else { + const promptResponse = await utils.openPrompt<{ + confirm: boolean; + rememberPermission: boolean; + }>({ + ...message, + action: "public/nostr/confirm", + args: { + description: i18n.t("permissions:nostr.nip44encrypt"), + }, + }); + + // add permission to db only if user decided to always allow this request + if (promptResponse.data.rememberPermission) { + await addPermissionFor( + PermissionMethodNostr["NOSTR_NIP44ENCRYPT"], + host + ); + } + if (promptResponse.data.confirm) { + const response = (await state.getState().getNostr()).nip44Encrypt( + message.args.peer, + message.args.plaintext, + message.args.v + ); + + return { data: response }; + } else { + return { error: USER_REJECTED_ERROR }; + } + } + } catch (e) { + console.error("encrypt failed", e); + if (e instanceof Error) { + return { error: e.message }; + } + } +}; + +export default nip44EncryptOrPrompt; diff --git a/src/extension/background-script/nostr/__test__/nostr.test.ts b/src/extension/background-script/nostr/__test__/nostr.test.ts index 779fd65007..3db5956d9a 100644 --- a/src/extension/background-script/nostr/__test__/nostr.test.ts +++ b/src/extension/background-script/nostr/__test__/nostr.test.ts @@ -18,7 +18,7 @@ const carol = { publicKey: "a8c7d70a7d2e2826ce519a0a490fb953464c9d130235c321282983cd73be333f", }; -describe("nostr", () => { +describe("nostr.nip04", () => { test("encrypt & decrypt", async () => { const aliceNostr = new Nostr(alice.privateKey); @@ -50,3 +50,36 @@ describe("nostr", () => { expect(decrypted).not.toMatch(message); }); }); + +describe("nostr.nip44", () => { + test("encrypt & decrypt", async () => { + const aliceNostr = new Nostr(alice.privateKey); + + const message = "Secret message that is sent from Alice to Bob"; + const encrypted = aliceNostr.nip44Encrypt(bob.publicKey, message); + + const bobNostr = new Nostr(bob.privateKey); + + const decrypted = await bobNostr.nip44Decrypt(alice.publicKey, encrypted); + + expect(decrypted).toMatch(message); + }); + + test("Carol can't decrypt Alice's message for Bob", async () => { + const aliceNostr = new Nostr(alice.privateKey); + + const message = "Secret message that is sent from Alice to Bob"; + const encrypted = aliceNostr.nip44Encrypt(bob.publicKey, message); + + const carolNostr = new Nostr(carol.privateKey); + + let decrypted; + try { + decrypted = await carolNostr.nip44Decrypt(alice.publicKey, encrypted); + } catch (e) { + decrypted = "error decrypting message"; + } + + expect(decrypted).not.toMatch(message); + }); +}); diff --git a/src/extension/background-script/nostr/index.ts b/src/extension/background-script/nostr/index.ts index ef468791b9..e3805ea1dd 100644 --- a/src/extension/background-script/nostr/index.ts +++ b/src/extension/background-script/nostr/index.ts @@ -1,3 +1,7 @@ +import { base64 } from "@scure/base"; +import { randomBytes } from "@noble/hashes/utils"; +import { sha256 } from "@noble/hashes/sha256"; +import { xchacha20 } from "@noble/ciphers/chacha"; import { schnorr } from "@noble/curves/secp256k1"; import * as secp256k1 from "@noble/secp256k1"; import { Buffer } from "buffer"; @@ -6,15 +10,33 @@ import { AES } from "crypto-js"; import Base64 from "crypto-js/enc-base64"; import Hex from "crypto-js/enc-hex"; import Utf8 from "crypto-js/enc-utf8"; +import { LRUCache } from "~/common/utils/lruCache"; import { Event } from "~/extension/providers/nostr/types"; import { getEventHash, signEvent } from "../actions/nostr/helpers"; +const utf8Decoder = new TextDecoder(); + +const utf8Encoder = new TextEncoder(); + class Nostr { - privateKey: string; + nip44SharedSecretCache = new LRUCache(100); + + constructor(readonly privateKey: string) {} + + // Deriving shared secret is an expensive computation + getNip44SharedSecret(pk: string) { + let key = this.nip44SharedSecretCache.get(pk); - constructor(privateKey: string) { - this.privateKey = privateKey; + if (!key) { + key = sha256( + secp256k1.getSharedSecret(this.privateKey, "02" + pk).subarray(1, 33) + ); + + this.nip44SharedSecretCache.set(pk, key); + } + + return key; } getPublicKey() { @@ -69,6 +91,44 @@ class Nostr { return Utf8.stringify(decrypted); } + nip44Encrypt(pubkey: string, text: string, v = 1) { + if (v !== 1) { + throw new Error("NIP44: unknown encryption version"); + } + + const nonce = randomBytes(24); + const plaintext = utf8Encoder.encode(text); + const key = this.getNip44SharedSecret(pubkey); + const ciphertext = xchacha20(key, nonce, plaintext); + + const payload = new Uint8Array(25 + ciphertext.length); + payload.set([v], 0); + payload.set(nonce, 1); + payload.set(ciphertext, 25); + + return base64.encode(payload); + } + + nip44Decrypt(pubkey: string, payload: string) { + let data; + try { + data = base64.decode(payload); + } catch (e) { + throw new Error(`NIP44: failed to base64 decode payload: ${e}`); + } + + if (data[0] !== 1) { + throw new Error(`NIP44: unknown encryption version: ${data[0]}`); + } + + const nonce = data.slice(1, 25); + const ciphertext = data.slice(25); + const key = this.getNip44SharedSecret(pubkey); + const plaintext = xchacha20(key, nonce, ciphertext); + + return utf8Decoder.decode(plaintext); + } + getEventHash(event: Event) { return getEventHash(event); } diff --git a/src/extension/providers/nostr/index.ts b/src/extension/providers/nostr/index.ts index ab1686023e..9f72ad0f34 100644 --- a/src/extension/providers/nostr/index.ts +++ b/src/extension/providers/nostr/index.ts @@ -10,6 +10,7 @@ declare global { export default class NostrProvider { nip04 = new Nip04(this); + nip44 = new Nip44(this); enabled: boolean; private _eventEmitter: EventEmitter; @@ -89,3 +90,25 @@ class Nip04 { return this.provider.execute("decryptOrPrompt", { peer, ciphertext }); } } + +class Nip44 { + provider: NostrProvider; + + constructor(provider: NostrProvider) { + this.provider = provider; + } + + async encrypt(peer: string, plaintext: string, v: number) { + await this.provider.enable(); + return this.provider.execute("nip44EncryptOrPrompt", { + peer, + plaintext, + v, + }); + } + + async decrypt(peer: string, payload: string) { + await this.provider.enable(); + return this.provider.execute("nip44DecryptOrPrompt", { peer, payload }); + } +} diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index 65471a881c..ad87fbaa86 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -855,9 +855,11 @@ "invoice": "Vytvořit novou platební fakturu." }, "nostr": { - "nip04encrypt": "Zašifrovat data.", "getpublickey": "Přečíst svůj veřejný klíč.", "nip04decrypt": "Dešifrovat data.", + "nip04encrypt": "Zašifrovat data.", + "nip44decrypt": "Dešifrovat data.", + "nip44encrypt": "Zašifrovat data.", "signmessage": "Podepsat zprávu klíčem." }, "lnc": { diff --git a/src/i18n/locales/da/translation.json b/src/i18n/locales/da/translation.json index 74b4495e46..365e4c3cf2 100644 --- a/src/i18n/locales/da/translation.json +++ b/src/i18n/locales/da/translation.json @@ -802,8 +802,10 @@ "permissions": { "nostr": { "getpublickey": "Læs din offentlige nøgle.", - "nip04encrypt": "Krypter data.", "nip04decrypt": "De-krypter data.", + "nip04encrypt": "Krypter data.", + "nip44decrypt": "De-krypter data.", + "nip44encrypt": "Krypter data.", "signmessage": "Underskriv meddelelse med din nøgle." }, "commando": { diff --git a/src/i18n/locales/de/translation.json b/src/i18n/locales/de/translation.json index 85c80cb261..f4965d2090 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -1129,6 +1129,8 @@ "getpublickey": "Lese deinen öffentlichen Schlüssel.", "nip04decrypt": "Daten entschlüsseln.", "nip04encrypt": "Daten verschlüsseln.", + "nip44decrypt": "Daten entschlüsseln.", + "nip44encrypt": "Daten verschlüsseln.", "signmessage": "Unterschreibe deine Nachricht mit deinem Schlüssel." }, "lnc": { diff --git a/src/i18n/locales/en/translation.json b/src/i18n/locales/en/translation.json index ba7b237d15..110b418f58 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -1079,6 +1079,8 @@ "getpublickey": "Read your public key.", "nip04encrypt": "Encrypt data.", "nip04decrypt": "Decrypt data.", + "nip44encrypt": "Encrypt data.", + "nip44decrypt": "Decrypt data.", "signmessage": "Sign message with your key." }, "commando": { diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index 6018a3df5a..4727c80e38 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -937,10 +937,12 @@ "feerates": "Devuelve las tarifas que utilizará CLN." }, "nostr": { - "signmessage": "Firma el mensaje con tu clave.", "getpublickey": "Leer tu clave pública.", + "nip04decrypt": "Descifrar datos.", "nip04encrypt": "Cifrar datos.", - "nip04decrypt": "Descifrar datos." + "nip44decrypt": "Descifrar datos.", + "nip44encrypt": "Cifrar datos.", + "signmessage": "Firma el mensaje con tu clave." }, "lnd": { "queryroutes": "Consultar una posible ruta.", diff --git a/src/i18n/locales/fa/translation.json b/src/i18n/locales/fa/translation.json index 85f5013214..124e0aad44 100644 --- a/src/i18n/locales/fa/translation.json +++ b/src/i18n/locales/fa/translation.json @@ -1042,8 +1042,10 @@ "permissions": { "nostr": { "getpublickey": "کلید عمومی تان را بخوانید.", - "nip04encrypt": "رمزنگاری داده.", "nip04decrypt": "رمزگشایی داده.", + "nip04encrypt": "رمزنگاری داده.", + "nip44decrypt": "رمزگشایی داده.", + "nip44encrypt": "رمزنگاری داده.", "signmessage": "پیام را با کلید خود امضا کنید." }, "commando": { diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 425ede57cf..801e41ec34 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -808,8 +808,10 @@ "permissions": { "nostr": { "getpublickey": "Lisez votre clé publique.", - "nip04encrypt": "Crypter les données.", "nip04decrypt": "Déchiffrer les données.", + "nip04encrypt": "Crypter les données.", + "nip44decrypt": "Déchiffrer les données.", + "nip44encrypt": "Crypter les données.", "signmessage": "Signez le message avec votre clé." }, "commando": { diff --git a/src/i18n/locales/hi/translation.json b/src/i18n/locales/hi/translation.json index 4592a58d37..5b73aefc10 100644 --- a/src/i18n/locales/hi/translation.json +++ b/src/i18n/locales/hi/translation.json @@ -766,8 +766,10 @@ "permissions": { "nostr": { "getpublickey": "अपनी सार्वजनिक कुंजी पढ़ें।", - "nip04encrypt": "डेटा एन्क्रिप्ट करें।", "nip04decrypt": "डेटा डिक्रिप्ट करें।", + "nip04encrypt": "डेटा एन्क्रिप्ट करें।", + "nip44decrypt": "डेटा डिक्रिप्ट करें।", + "nip44encrypt": "डेटा एन्क्रिप्ट करें।", "signmessage": "अपनी चाबी से संदेश पर हस्ताक्षर करें।" }, "commando": { diff --git a/src/i18n/locales/id/translation.json b/src/i18n/locales/id/translation.json index a71c83bc1f..7d3ddebbf7 100644 --- a/src/i18n/locales/id/translation.json +++ b/src/i18n/locales/id/translation.json @@ -942,9 +942,11 @@ }, "permissions": { "nostr": { - "nip04decrypt": "Dekripsi data.", "getpublickey": "Membaca kunci publik Anda.", - "nip04encrypt": "Enkripsi data." + "nip04decrypt": "Dekripsi data.", + "nip04encrypt": "Enkripsi data.", + "nip44decrypt": "Dekripsi data.", + "nip44encrypt": "Enkripsi data." }, "commando": { "decode": "Decode teks bolt11/bolt12/rune." diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index 24079fee5d..c7c77853a3 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -878,9 +878,11 @@ "addinvoice": "Crea nuove ricevute di pagamento." }, "nostr": { - "nip04decrypt": "Decripta i dati.", "getpublickey": "Leggi la tua chiave pubblica.", + "nip04decrypt": "Decripta i dati.", "nip04encrypt": "Cripta i dati.", + "nip44decrypt": "Decripta i dati.", + "nip44encrypt": "Cripta i dati.", "signmessage": "Firma il messaggio con la tua chiave." } } diff --git a/src/i18n/locales/mr/translation.json b/src/i18n/locales/mr/translation.json index 88451ef422..87e124713a 100644 --- a/src/i18n/locales/mr/translation.json +++ b/src/i18n/locales/mr/translation.json @@ -825,8 +825,10 @@ "permissions": { "nostr": { "getpublickey": "तुमची सार्वजनिक की वाचा.", - "nip04encrypt": "डेटा Encrypt करा.", "nip04decrypt": "डेटा Decrypt करा.", + "nip04encrypt": "डेटा Encrypt करा.", + "nip44decrypt": "डेटा Decrypt करा.", + "nip44encrypt": "डेटा Encrypt करा.", "signmessage": "तुमच्या किल्लीने संदेशावर स्वाक्षरी करा." }, "commando": { diff --git a/src/i18n/locales/pl/translation.json b/src/i18n/locales/pl/translation.json index 226692343c..4b6cc09c22 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -855,8 +855,10 @@ "permissions": { "nostr": { "getpublickey": "Czytanie Twojego klucza publicznego.", - "nip04encrypt": "Szyfrowanie danych.", "nip04decrypt": "Deszyfrowanie danych.", + "nip04encrypt": "Szyfrowanie danych.", + "nip44decrypt": "Deszyfrowanie danych.", + "nip44encrypt": "Szyfrowanie danych.", "signmessage": "Podpisywanie wiadomości Twoim kluczem." }, "commando": { diff --git a/src/i18n/locales/ro/translation.json b/src/i18n/locales/ro/translation.json index 3086eae740..44179d3a89 100644 --- a/src/i18n/locales/ro/translation.json +++ b/src/i18n/locales/ro/translation.json @@ -802,8 +802,10 @@ "permissions": { "nostr": { "getpublickey": "", - "nip04encrypt": "", "nip04decrypt": "", + "nip04encrypt": "", + "nip44decrypt": "", + "nip44encrypt": "", "signmessage": "" }, "commando": { diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index 35a642e604..dd4e9dde92 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -802,8 +802,10 @@ "permissions": { "nostr": { "getpublickey": "", - "nip04encrypt": "", "nip04decrypt": "", + "nip04encrypt": "", + "nip44decrypt": "", + "nip44encrypt": "", "signmessage": "" }, "commando": { diff --git a/src/i18n/locales/sv/translation.json b/src/i18n/locales/sv/translation.json index 94e1f9b696..5d1be8824e 100644 --- a/src/i18n/locales/sv/translation.json +++ b/src/i18n/locales/sv/translation.json @@ -1041,10 +1041,12 @@ }, "permissions": { "nostr": { - "nip04decrypt": "Dekryptera data.", "getpublickey": "Läs din publika nyckel.", - "signmessage": "Skriv under meddelandet med din nyckel.", - "nip04encrypt": "Kryptera data." + "nip04decrypt": "Dekryptera data.", + "nip04encrypt": "Kryptera data.", + "nip44decrypt": "Dekryptera data.", + "nip44encrypt": "Kryptera data.", + "signmessage": "Skriv under meddelandet med din nyckel." }, "lnd": { "channelbalance": "Få en rapport om de totala medlen över alla öppna kanaler.", diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index d83980887f..e5966e043f 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -802,8 +802,10 @@ "permissions": { "nostr": { "getpublickey": "", - "nip04encrypt": "", "nip04decrypt": "", + "nip04encrypt": "", + "nip44decrypt": "", + "nip44encrypt": "", "signmessage": "" }, "commando": { diff --git a/src/i18n/locales/zh_Hans/translation.json b/src/i18n/locales/zh_Hans/translation.json index fdde975a45..46be059574 100644 --- a/src/i18n/locales/zh_Hans/translation.json +++ b/src/i18n/locales/zh_Hans/translation.json @@ -1070,10 +1070,12 @@ }, "permissions": { "nostr": { - "signmessage": "使用你的密钥签署消息。", + "getpublickey": "读取你的公钥。", "nip04decrypt": "解密数据。", "nip04encrypt": "加密数据。", - "getpublickey": "读取你的公钥。" + "nip44decrypt": "解密数据。", + "nip44encrypt": "加密数据。", + "signmessage": "使用你的密钥签署消息。" }, "commando": { "bkpr-listbalances": "所有当前和历史帐户余额列表。", diff --git a/src/i18n/locales/zh_Hant/translation.json b/src/i18n/locales/zh_Hant/translation.json index 26de60a38f..62d5f0d231 100644 --- a/src/i18n/locales/zh_Hant/translation.json +++ b/src/i18n/locales/zh_Hant/translation.json @@ -1073,8 +1073,10 @@ "permissions": { "nostr": { "getpublickey": "讀取你的公鑰。", - "nip04encrypt": "加密數據。", "nip04decrypt": "解密數據。", + "nip04encrypt": "加密數據。", + "nip44decrypt": "解密數據。", + "nip44encrypt": "加密數據。", "signmessage": "用你的密鑰簽署消息。" }, "commando": { diff --git a/src/types.ts b/src/types.ts index ab2bfd472c..6c54c171c9 100644 --- a/src/types.ts +++ b/src/types.ts @@ -540,6 +540,23 @@ export interface MessageDecryptGet extends MessageDefault { action: "decrypt"; } +export interface Nip44MessageEncryptGet extends MessageDefault { + args: { + peer: string; + plaintext: string; + v: 1; + }; + action: "encrypt"; +} + +export interface Nip44MessageDecryptGet extends MessageDefault { + args: { + peer: string; + payload: string; + }; + action: "decrypt"; +} + export interface MessageBalanceGet extends MessageDefault { action: "getBalance"; } @@ -686,6 +703,8 @@ export enum PermissionMethodNostr { NOSTR_GETPUBLICKEY = "nostr/getPublicKey", NOSTR_NIP04DECRYPT = "nostr/nip04decrypt", NOSTR_NIP04ENCRYPT = "nostr/nip04encrypt", + NOSTR_NIP44DECRYPT = "nostr/nip44decrypt", + NOSTR_NIP44ENCRYPT = "nostr/nip44encrypt", } export interface DbPermission { diff --git a/yarn.lock b/yarn.lock index 5f80780a64..70731dd445 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1004,6 +1004,11 @@ strict-event-emitter "^0.2.4" web-encoding "^1.1.5" +"@noble/ciphers@^0.2.0": + version "0.2.0" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.2.0.tgz#a12cda60f3cf1ab5d7c77068c3711d2366649ed7" + integrity sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw== + "@noble/curves@1.1.0", "@noble/curves@^1.1.0", "@noble/curves@~1.1.0": version "1.1.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.1.0.tgz#f13fc667c89184bc04cccb9b11e8e7bae27d8c3d" @@ -1023,7 +1028,7 @@ resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" integrity sha512-ilHEACi9DwqJB0pw7kv+Apvh50jiiSyR/cQ3y4W7lOR5mhvn/50FLUfsnfJz0BDZtl/RR16kXvptiv6q1msYZg== -"@noble/hashes@1.3.1", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": +"@noble/hashes@1.3.1", "@noble/hashes@^1.3.1", "@noble/hashes@~1.3.0", "@noble/hashes@~1.3.1": version "1.3.1" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.1.tgz#8831ef002114670c603c458ab8b11328406953a9" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== @@ -1097,7 +1102,7 @@ resolved "https://registry.yarnpkg.com/@remix-run/router/-/router-1.7.2.tgz#cba1cf0a04bc04cb66027c51fa600e9cbc388bc8" integrity sha512-7Lcn7IqGMV+vizMPoEl5F0XDshcdDYtMI6uJLQdQz5CfZAwy3vvGKYSUk789qndt5dEC4HfSjviSYlSoHGL2+A== -"@scure/base@1.1.1", "@scure/base@~1.1.0", "@scure/base@~1.1.1": +"@scure/base@1.1.1", "@scure/base@^1.1.1", "@scure/base@~1.1.0", "@scure/base@~1.1.1": version "1.1.1" resolved "https://registry.yarnpkg.com/@scure/base/-/base-1.1.1.tgz#ebb651ee52ff84f420097055f4bf46cfba403938" integrity sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==