diff --git a/package.json b/package.json index 181fc4e34d..6c42a3cf32 100644 --- a/package.json +++ b/package.json @@ -64,6 +64,7 @@ "lodash.merge": "^4.6.2", "lodash.pick": "^4.4.0", "lodash.snakecase": "^4.1.1", + "nostr-tools": "^2.1.0", "pubsub-js": "^1.9.4", "react": "^18.2.0", "react-confetti": "^6.1.0", diff --git a/src/common/utils/lruCache.ts b/src/common/utils/lruCache.ts new file mode 100644 index 0000000000..1cd96052cd --- /dev/null +++ b/src/common/utils/lruCache.ts @@ -0,0 +1,33 @@ +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(k as T); + + if (this.keys.length > this.maxSize * 2) { + this.keys.splice(-this.maxSize); + } + } + + 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/index.ts b/src/extension/background-script/actions/nostr/index.ts index 32fb85eee4..c1db56ac37 100644 --- a/src/extension/background-script/actions/nostr/index.ts +++ b/src/extension/background-script/actions/nostr/index.ts @@ -8,6 +8,8 @@ import getPrivateKey from "./getPrivateKey"; import getPublicKeyOrPrompt from "./getPublicKeyOrPrompt"; import getRelays from "./getRelays"; import isEnabled from "./isEnabled"; +import nip44DecryptOrPrompt from "./nip44DecryptOrPrompt"; +import nip44EncryptOrPrompt from "./nip44EncryptOrPrompt"; import removePrivateKey from "./removePrivateKey"; import setPrivateKey from "./setPrivateKey"; import signEventOrPrompt from "./signEventOrPrompt"; @@ -23,6 +25,8 @@ export { getPublicKeyOrPrompt, getRelays, isEnabled, + nip44DecryptOrPrompt, + nip44EncryptOrPrompt, removePrivateKey, setPrivateKey, signEventOrPrompt, 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..2fe61996f7 --- /dev/null +++ b/src/extension/background-script/actions/nostr/nip44DecryptOrPrompt.ts @@ -0,0 +1,68 @@ +import { USER_REJECTED_ERROR } from "~/common/constants"; +import utils from "~/common/lib/utils"; +import { getHostFromSender } from "~/common/utils/helpers"; +import { + addPermissionFor, + hasPermissionFor, +} from "~/extension/background-script/permissions"; +import state from "~/extension/background-script/state"; +import { MessageNip44DecryptGet, PermissionMethodNostr, Sender } from "~/types"; + +const nip44DecryptOrPrompt = async ( + message: MessageNip44DecryptGet, + 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.ciphertext + ); + + return { data: response }; + } else { + const promptResponse = await utils.openPrompt<{ + confirm: boolean; + rememberPermission: boolean; + }>({ + ...message, + action: "public/nostr/confirmDecrypt", + }); + + // 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.ciphertext + ); + + 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..5ab42232bc --- /dev/null +++ b/src/extension/background-script/actions/nostr/nip44EncryptOrPrompt.ts @@ -0,0 +1,72 @@ +import { USER_REJECTED_ERROR } from "~/common/constants"; +import nostr from "~/common/lib/nostr"; +import utils from "~/common/lib/utils"; +import { getHostFromSender } from "~/common/utils/helpers"; +import { + addPermissionFor, + hasPermissionFor, +} from "~/extension/background-script/permissions"; +import state from "~/extension/background-script/state"; +import { MessageNip44EncryptGet, PermissionMethodNostr, Sender } from "~/types"; + +const nip44EncryptOrPrompt = async ( + message: MessageNip44EncryptGet, + 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 + ); + return { data: response }; + } else { + const promptResponse = await utils.openPrompt<{ + confirm: boolean; + rememberPermission: boolean; + }>({ + ...message, + action: "public/nostr/confirmEncrypt", + args: { + encrypt: { + recipientNpub: nostr.hexToNip19(message.args.peer, "npub"), + message: message.args.plaintext, + }, + }, + }); + + // 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 + ); + + 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..0324c7ff08 100644 --- a/src/extension/background-script/nostr/index.ts +++ b/src/extension/background-script/nostr/index.ts @@ -1,20 +1,33 @@ import { schnorr } from "@noble/curves/secp256k1"; import * as secp256k1 from "@noble/secp256k1"; +import { nip44 } from "nostr-tools"; import { Buffer } from "buffer"; import * as CryptoJS from "crypto-js"; 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"; class Nostr { - privateKey: string; + nip44SharedSecretCache = new LRUCache(100); - constructor(privateKey: string) { - this.privateKey = privateKey; + constructor(readonly privateKey: string) {} + + // Deriving shared secret is an expensive computation + getNip44SharedSecret(peerPubkey: string) { + let key = this.nip44SharedSecretCache.get(peerPubkey); + + if (!key) { + key = nip44.v2.utils.getConversationKey(this.privateKey, peerPubkey); + + this.nip44SharedSecretCache.set(peerPubkey, key); + } + + return key; } getPublicKey() { @@ -69,6 +82,14 @@ class Nostr { return Utf8.stringify(decrypted); } + nip44Encrypt(peer: string, plaintext: string) { + return nip44.v2.encrypt(plaintext, this.getNip44SharedSecret(peer)); + } + + nip44Decrypt(peer: string, ciphertext: string) { + return nip44.v2.decrypt(ciphertext, this.getNip44SharedSecret(peer)); + } + getEventHash(event: Event) { return getEventHash(event); } diff --git a/src/extension/background-script/router.ts b/src/extension/background-script/router.ts index 688d017536..2378b6de4a 100644 --- a/src/extension/background-script/router.ts +++ b/src/extension/background-script/router.ts @@ -128,6 +128,8 @@ const routes = { getRelays: nostr.getRelays, encryptOrPrompt: nostr.encryptOrPrompt, decryptOrPrompt: nostr.decryptOrPrompt, + nip44EncryptOrPrompt: nostr.nip44EncryptOrPrompt, + nip44DecryptOrPrompt: nostr.nip44DecryptOrPrompt, }, }, }; diff --git a/src/extension/content-script/nostr.js b/src/extension/content-script/nostr.js index e3d8a287d2..3b67440a03 100644 --- a/src/extension/content-script/nostr.js +++ b/src/extension/content-script/nostr.js @@ -13,6 +13,8 @@ const nostrCalls = [ "nostr/enable", "nostr/encryptOrPrompt", "nostr/decryptOrPrompt", + "nostr/nip44EncryptOrPrompt", + "nostr/nip44DecryptOrPrompt", "nostr/on", "nostr/off", "nostr/emit", diff --git a/src/extension/providers/nostr/index.ts b/src/extension/providers/nostr/index.ts index 2570a8a01f..48c264404e 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 extends ProviderBase { nip04 = new Nip04(this); + nip44 = new Nip44(this); constructor() { super("nostr"); @@ -70,3 +71,27 @@ class Nip04 { }); } } + +class Nip44 { + provider: NostrProvider; + + constructor(provider: NostrProvider) { + this.provider = provider; + } + + async encrypt(peer: string, plaintext: string) { + await this.provider.enable(); + return this.provider.execute("nip44EncryptOrPrompt", { + peer, + plaintext, + }); + } + + async decrypt(peer: string, ciphertext: string) { + await this.provider.enable(); + return this.provider.execute("nip44DecryptOrPrompt", { + peer, + ciphertext, + }); + } +} diff --git a/src/i18n/locales/cs/translation.json b/src/i18n/locales/cs/translation.json index ffc48587e5..4a36035924 100644 --- a/src/i18n/locales/cs/translation.json +++ b/src/i18n/locales/cs/translation.json @@ -831,6 +831,9 @@ "nostr": { "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 8ca85a3d39..8caa6623a7 100644 --- a/src/i18n/locales/da/translation.json +++ b/src/i18n/locales/da/translation.json @@ -699,6 +699,9 @@ "nostr": { "getpublickey": "Læs din offentlige nøgle", "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 e5ed615d55..3f4fae15aa 100644 --- a/src/i18n/locales/de/translation.json +++ b/src/i18n/locales/de/translation.json @@ -1214,6 +1214,9 @@ "nostr": { "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 19c7ed1e4d..572307d51a 100644 --- a/src/i18n/locales/en/translation.json +++ b/src/i18n/locales/en/translation.json @@ -1167,11 +1167,6 @@ "webln": { "getbalance": "Read the balance of your account" }, - "nostr": { - "getpublickey": "Read your public key", - "signmessage": "Sign message with your key", - "nip04decrypt": "Decrypt data" - }, "bitcoin": { "getaddress": "Read your Bitcoin receive address" }, @@ -1179,6 +1174,14 @@ "getaddress": "Read your Liquid receive address", "signschnorr": "Sign message with your key" }, + "nostr": { + "getpublickey": "Read your public key.", + "nip04encrypt": "Encrypt data.", + "nip04decrypt": "Decrypt data.", + "nip44encrypt": "Encrypt data.", + "nip44decrypt": "Decrypt data.", + "signmessage": "Sign message with your key." + }, "commando": { "bkpr-listbalances": "List of all current and historical account balances", "checkmessage": "Verify that the signature was generated by a given node", diff --git a/src/i18n/locales/es/translation.json b/src/i18n/locales/es/translation.json index 2d42f47f87..3e2a6f797a 100644 --- a/src/i18n/locales/es/translation.json +++ b/src/i18n/locales/es/translation.json @@ -846,9 +846,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" + "nip04decrypt": "Descifrar datos", + "nip04encrypt": "Cifrar 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 77b9f48533..424cfd0f1e 100644 --- a/src/i18n/locales/fa/translation.json +++ b/src/i18n/locales/fa/translation.json @@ -984,6 +984,9 @@ "nostr": { "getpublickey": "کلید عمومی تان را بخوانید", "nip04decrypt": "رمزگشایی داده", + "nip04encrypt": "رمزنگاری داده", + "nip44decrypt": "رمزگشایی داده", + "nip44encrypt": "رمزنگاری داده", "signmessage": "پیام را با کلید خود امضا کنید" }, "commando": { diff --git a/src/i18n/locales/fr/translation.json b/src/i18n/locales/fr/translation.json index 66378ae9e5..b77a41eeba 100644 --- a/src/i18n/locales/fr/translation.json +++ b/src/i18n/locales/fr/translation.json @@ -705,6 +705,9 @@ "nostr": { "getpublickey": "Lisez votre clé publique", "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 bf6fafbf7d..b76e435dc6 100644 --- a/src/i18n/locales/hi/translation.json +++ b/src/i18n/locales/hi/translation.json @@ -1151,7 +1151,10 @@ "permissions": { "nostr": { "getpublickey": "अपनी सार्वजनिक कुंजी पढ़ें", - "nip04decrypt": "डेटा डिक्रिप्ट करें", + "nip04decrypt": "डेटा डिक्रिप्ट करे", + "nip04encrypt": "डेटा एन्क्रिप्ट करे", + "nip44decrypt": "डेटा डिक्रिप्ट करे", + "nip44encrypt": "डेटा एन्क्रिप्ट करे", "signmessage": "अपनी चाबी से संदेश पर हस्ताक्षर करें" }, "commando": { diff --git a/src/i18n/locales/id/translation.json b/src/i18n/locales/id/translation.json index dd447b1ad1..a3494dda10 100644 --- a/src/i18n/locales/id/translation.json +++ b/src/i18n/locales/id/translation.json @@ -797,6 +797,9 @@ "permissions": { "nostr": { "nip04decrypt": "Dekripsi data", + "nip04encrypt": "Enkripsi data", + "nip44decrypt": "Dekripsi data", + "nip44encrypt": "Enkripsi data", "getpublickey": "Membaca kunci publik Anda" }, "commando": { diff --git a/src/i18n/locales/it/translation.json b/src/i18n/locales/it/translation.json index 9796906b65..46cbb63dd0 100644 --- a/src/i18n/locales/it/translation.json +++ b/src/i18n/locales/it/translation.json @@ -774,8 +774,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 76b044c582..7ca63cc513 100644 --- a/src/i18n/locales/mr/translation.json +++ b/src/i18n/locales/mr/translation.json @@ -721,6 +721,9 @@ "nostr": { "getpublickey": "तुमची सार्वजनिक की वाचा", "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 6ca968e523..bd2da331e0 100644 --- a/src/i18n/locales/pl/translation.json +++ b/src/i18n/locales/pl/translation.json @@ -851,6 +851,9 @@ "nostr": { "getpublickey": "Czytanie Twojego klucza publicznego.", "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/pt_BR/translation.json b/src/i18n/locales/pt_BR/translation.json index f02aacbdf0..9c49be4ced 100644 --- a/src/i18n/locales/pt_BR/translation.json +++ b/src/i18n/locales/pt_BR/translation.json @@ -1104,8 +1104,11 @@ "permissions": { "nostr": { "getpublickey": "Ler sua chave pública", - "signmessage": "Assinar mensagem com sua chave", - "nip04decrypt": "Descriptografar dados" + "nip04decrypt": "Descriptografar dados", + "nip04encrypt": "Criptografar dados", + "nip44decrypt": "Descriptografar dados", + "nip44encrypt": "Criptografar dados", + "signmessage": "Assinar mensagem com sua chave" }, "lnc": { "openchannel": "" diff --git a/src/i18n/locales/ru/translation.json b/src/i18n/locales/ru/translation.json index 773563deba..0fb67ef3b7 100644 --- a/src/i18n/locales/ru/translation.json +++ b/src/i18n/locales/ru/translation.json @@ -709,6 +709,9 @@ "nostr": { "getpublickey": "", "nip04decrypt": "", + "nip04encrypt": "", + "nip44decrypt": "", + "nip44encrypt": "", "signmessage": "" }, "commando": { diff --git a/src/i18n/locales/sl/translation.json b/src/i18n/locales/sl/translation.json index 01be28d13b..baf2ae7b6b 100644 --- a/src/i18n/locales/sl/translation.json +++ b/src/i18n/locales/sl/translation.json @@ -630,9 +630,12 @@ "getaddress": "Bere tvoj Liquid naslov za prejemanje" }, "nostr": { - "signmessage": "Podpiši sporočilo s svojim ključem", + "getpublickey": "Bere tvoj javni ključ", "nip04decrypt": "Dekriptiraj podatke", - "getpublickey": "Bere tvoj javni ključ" + "nip04encrypt": "Kriptiraj podatke", + "nip44decrypt": "Dekriptiraj podatke", + "nip44encrypt": "Kriptiraj podatke", + "signmessage": "Podpiši sporočilo s svojim ključem" }, "webln": { "getbalance": "Bere stanje tvojega računa" diff --git a/src/i18n/locales/sv/translation.json b/src/i18n/locales/sv/translation.json index 860b3b23e2..06113443db 100644 --- a/src/i18n/locales/sv/translation.json +++ b/src/i18n/locales/sv/translation.json @@ -1079,8 +1079,11 @@ }, "permissions": { "nostr": { - "nip04decrypt": "Dekryptera data", "getpublickey": "Läs din publika nyckel", + "nip04decrypt": "Dekryptera data", + "nip04encrypt": "Kryptera data", + "nip44decrypt": "Dekryptera data", + "nip44encrypt": "Kryptera data", "signmessage": "Skriv under meddelandet med din nyckel" }, "lnd": { diff --git a/src/i18n/locales/th/translation.json b/src/i18n/locales/th/translation.json index 78f00e57b0..63fb8ca534 100644 --- a/src/i18n/locales/th/translation.json +++ b/src/i18n/locales/th/translation.json @@ -772,6 +772,8 @@ "nostr": { "signmessage": "เซ็นข้อความด้วย key ของคุณ", "nip04decrypt": "ถอดรหัสข้อมูล", + "nip44encrypt": "เข้ารหัสข้อมูล", + "nip44decrypt": "ถอดรหัสข้อมูล", "getpublickey": "แสดง public key ของคุณ" }, "commando": { diff --git a/src/i18n/locales/uk/translation.json b/src/i18n/locales/uk/translation.json index 2df940cbca..e581cfa736 100644 --- a/src/i18n/locales/uk/translation.json +++ b/src/i18n/locales/uk/translation.json @@ -699,6 +699,9 @@ "nostr": { "getpublickey": "", "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 4b7ce4737a..5a3deb98ec 100644 --- a/src/i18n/locales/zh_Hans/translation.json +++ b/src/i18n/locales/zh_Hans/translation.json @@ -972,9 +972,12 @@ }, "permissions": { "nostr": { - "signmessage": "使用你的密钥签署消息", + "getpublickey": "读取你的公钥", "nip04decrypt": "解密数据", - "getpublickey": "读取你的公钥" + "nip04encrypt": "加密数据", + "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 53dde1b6c5..8a3d05375e 100644 --- a/src/i18n/locales/zh_Hant/translation.json +++ b/src/i18n/locales/zh_Hant/translation.json @@ -981,6 +981,9 @@ "nostr": { "getpublickey": "讀取你的公鑰", "nip04decrypt": "解密數據", + "nip04encrypt": "加密數據", + "nip44decrypt": "解密數據", + "nip44encrypt": "加密數據", "signmessage": "用你的密鑰簽署消息" }, "commando": { diff --git a/src/types.ts b/src/types.ts index 6bc4f7f414..19e1338450 100644 --- a/src/types.ts +++ b/src/types.ts @@ -175,6 +175,11 @@ export type NavigationState = { message: string; }; + nip44Encrypt: { + recipientNpub: string; + message: string; + }; + psbt?: string; requestPermission: { method: string; @@ -560,6 +565,22 @@ export interface MessageDecryptGet extends MessageDefault { action: "decrypt"; } +export interface MessageNip44EncryptGet extends MessageDefault { + args: { + peer: string; + plaintext: string; + }; + action: "encrypt"; +} + +export interface MessageNip44DecryptGet extends MessageDefault { + args: { + peer: string; + ciphertext: string; + }; + action: "decrypt"; +} + export interface MessageSignPsbt extends MessageDefault { args: { psbt: string; @@ -769,6 +790,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 39068a1ef4..9616eefcbc 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1065,6 +1065,11 @@ resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.2.0.tgz#a12cda60f3cf1ab5d7c77068c3711d2366649ed7" integrity sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw== +"@noble/ciphers@^0.5.1": + version "0.5.1" + resolved "https://registry.yarnpkg.com/@noble/ciphers/-/ciphers-0.5.1.tgz#292f388b69c9ed80d49dca1a5cbfd4ff06852111" + integrity sha512-aNE06lbe36ifvMbbWvmmF/8jx6EQPu2HVg70V95T+iGjOuYwPpAccwAQc2HlXO2D0aiQ3zavbMga4jjWnrpiPA== + "@noble/curves@1.1.0", "@noble/curves@~1.1.0": version "1.1.0" resolved "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz" @@ -1072,6 +1077,13 @@ dependencies: "@noble/hashes" "1.3.1" +"@noble/curves@1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.2.0.tgz#92d7e12e4e49b23105a2555c6984d41733d65c35" + integrity sha512-oYclrNgRaM9SsBUBVbb8M6DTV7ZHRTKugureoYEncY5c65HOmRzvSiTE3y5CYaPYJA/GVkrhXEoF0M3Ya9PMnw== + dependencies: + "@noble/hashes" "1.3.2" + "@noble/curves@^1.3.0", "@noble/curves@~1.3.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/curves/-/curves-1.3.0.tgz#01be46da4fd195822dab821e72f71bf4aeec635e" @@ -1084,16 +1096,16 @@ resolved "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz" integrity sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA== +"@noble/hashes@1.3.2", "@noble/hashes@^1.1.5": + version "1.3.2" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" + integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== + "@noble/hashes@1.3.3", "@noble/hashes@~1.3.2": version "1.3.3" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.3.tgz#39908da56a4adc270147bb07968bf3b16cfe1699" integrity sha512-V7/fPHgl+jsVPXqqeOzT8egNj2iBIVt+ECeMMG8TdcnTikP3oaBtUVqpT/gYCR68aEBJSF+XbYUxStjbFMqIIA== -"@noble/hashes@^1.1.5": - version "1.3.2" - resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.2.tgz#6f26dbc8fbc7205873ce3cee2f690eba0d421b39" - integrity sha512-MVC8EAQp7MvEcm30KWENFjgR+Mkmf+D189XJTkFIlwohU5hcBbn1ZkKq7KVTi2Hme3PMGF390DaL52beVrIihQ== - "@noble/hashes@^1.2.0": version "1.3.0" resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.3.0.tgz#085fd70f6d7d9d109671090ccae1d3bec62554a1" @@ -7243,6 +7255,25 @@ nostr-tools@^1.17.0: "@scure/bip32" "1.3.1" "@scure/bip39" "1.2.1" +nostr-tools@^2.1.0: + version "2.3.1" + resolved "https://registry.yarnpkg.com/nostr-tools/-/nostr-tools-2.3.1.tgz#348d3c4aab0ab00716f93d6e2a72333d8c7da982" + integrity sha512-qjKx2C3EzwiQOe2LPSPyCnp07pGz1pWaWjDXcm+L2y2c8iTECbvlzujDANm3nJUjWL5+LVRUVDovTZ1a/DC4Bg== + dependencies: + "@noble/ciphers" "^0.5.1" + "@noble/curves" "1.2.0" + "@noble/hashes" "1.3.1" + "@scure/base" "1.1.1" + "@scure/bip32" "1.3.1" + "@scure/bip39" "1.2.1" + optionalDependencies: + nostr-wasm v0.1.0 + +nostr-wasm@v0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/nostr-wasm/-/nostr-wasm-0.1.0.tgz#17af486745feb2b7dd29503fdd81613a24058d94" + integrity sha512-78BTryCLcLYv96ONU8Ws3Q1JzjlAt+43pWQhIl86xZmWeegYCNLPml7yQ+gG3vR6V5h4XGj+TxO+SS5dsThQIA== + npm-run-path@^4.0.1: version "4.0.1" resolved "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz"