From 5e69a9bedf91fe5d2db71fff3029e95e3e89d151 Mon Sep 17 00:00:00 2001 From: Anton Kovalenko Date: Fri, 7 Jan 2022 17:51:29 +0300 Subject: [PATCH] Support ECIES encryption for payment destination --- package-lock.json | 40 +++++++++++++++++++++++++++++-- package.json | 3 +++ src/App.svelte | 61 +++++++++++++++++++++++++++++++---------------- src/ecies.js | 38 +++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+), 23 deletions(-) create mode 100644 src/ecies.js diff --git a/package-lock.json b/package-lock.json index e686477..34d3c64 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,15 +1,18 @@ { - "name": "svelte-app", + "name": "lnurl-pay.me", "version": "1.0.0", "lockfileVersion": 2, "requires": true, "packages": { "": { - "name": "svelte-app", + "name": "lnurl-pay.me", "version": "1.0.0", "dependencies": { "@imask/svelte": "^6.1.0", + "@noble/hashes": "^0.5.9", + "@noble/secp256k1": "^1.4.0", "bech32": "^2.0.0", + "jscrypto": "^1.0.2", "kjua": "^0.9.0", "sirv-cli": "^1.0.0", "sveltestrap": "^5.4.0", @@ -74,6 +77,16 @@ "svelte": ">=3.0.0" } }, + "node_modules/@noble/hashes": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", + "integrity": "sha512-7lN1Qh6d8DUGmfN36XRsbN/WcGIPNtTGhkw26vWId/DlCIGsYJJootTtPGghTLcn/AaXPx2Q0b3cacrwXa7OVw==" + }, + "node_modules/@noble/secp256k1": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.4.0.tgz", + "integrity": "sha512-cYpUbQ2uitPgf5QuQnpi8Nu+ZmQjSDunFKw6vvxaOSkbMUhCf4K723WLUuuK1K/sf6H/dvqKbmEAeop5i3qTJg==" + }, "node_modules/@polka/url": { "version": "1.0.0-next.15", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz", @@ -629,6 +642,14 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "node_modules/jscrypto": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.2.tgz", + "integrity": "sha512-r+oNJLGTv1nkNMBBq3c70xYrFDgJOYVgs2OHijz5Ht+0KJ0yObD0oYxC9mN72KLzVfXw+osspg6t27IZvuTUxw==", + "bin": { + "jscrypto": "bin/cli.js" + } + }, "node_modules/kjua": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/kjua/-/kjua-0.9.0.tgz", @@ -1220,6 +1241,16 @@ "imask": "^6.1.0" } }, + "@noble/hashes": { + "version": "0.5.9", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-0.5.9.tgz", + "integrity": "sha512-7lN1Qh6d8DUGmfN36XRsbN/WcGIPNtTGhkw26vWId/DlCIGsYJJootTtPGghTLcn/AaXPx2Q0b3cacrwXa7OVw==" + }, + "@noble/secp256k1": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@noble/secp256k1/-/secp256k1-1.4.0.tgz", + "integrity": "sha512-cYpUbQ2uitPgf5QuQnpi8Nu+ZmQjSDunFKw6vvxaOSkbMUhCf4K723WLUuuK1K/sf6H/dvqKbmEAeop5i3qTJg==" + }, "@polka/url": { "version": "1.0.0-next.15", "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.15.tgz", @@ -1660,6 +1691,11 @@ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true }, + "jscrypto": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/jscrypto/-/jscrypto-1.0.2.tgz", + "integrity": "sha512-r+oNJLGTv1nkNMBBq3c70xYrFDgJOYVgs2OHijz5Ht+0KJ0yObD0oYxC9mN72KLzVfXw+osspg6t27IZvuTUxw==" + }, "kjua": { "version": "0.9.0", "resolved": "https://registry.npmjs.org/kjua/-/kjua-0.9.0.tgz", diff --git a/package.json b/package.json index 6daca7d..4760bc8 100644 --- a/package.json +++ b/package.json @@ -21,7 +21,10 @@ }, "dependencies": { "@imask/svelte": "^6.1.0", + "@noble/hashes": "^0.5.9", + "@noble/secp256k1": "^1.4.0", "bech32": "^2.0.0", + "jscrypto": "^1.0.2", "kjua": "^0.9.0", "sirv-cli": "^1.0.0", "sveltestrap": "^5.4.0", diff --git a/src/App.svelte b/src/App.svelte index e7d5add..1560d70 100644 --- a/src/App.svelte +++ b/src/App.svelte @@ -8,6 +8,7 @@ import InputMask from './InputMask.svelte'; import payways from './payways.js'; + import QR from './QR.svelte'; import CTC from './CTC.svelte'; @@ -17,7 +18,8 @@ import UTF8 from 'utf-8' import PayFlow from './PayFlow.svelte'; - + import { ecEncrypt } from './ecies.js'; + let payway = payways[0]; setTimeout(()=>{ @@ -28,8 +30,12 @@ let inputId; let amountMask; let realAmount; + let extAccount; + let briefAccount; + let encrypt = false; $: inputId = payway.iid||payway.id; + $: accountReady = accountComplete && accounts[inputId] $: amountMask = { mask: Number, scale:2, min: payway.min, max:payway.max, @@ -39,6 +45,10 @@ $: realAmount = amounts[payway.id] && ( Math.max(Math.min(amounts[payway.id], payway.max),payway.min)) + + $: extAccount = accountReady ? (encrypt? "0g" + ecEncrypt(accounts[inputId].padEnd(8)): accounts[inputId]):""; + + $: briefAccount = extAccount ? (encrypt ? extAccount.slice(0,28)+"…" : extAccount):"" function genAutoMemo(payway,account,amount) { if (!account) @@ -52,16 +62,12 @@ } let autoMemo; - $: autoMemo = genAutoMemo(payway, - accountComplete && accounts[inputId], - realAmount) + $: autoMemo = genAutoMemo(payway, briefAccount, realAmount) let lightningAddress; - $: lightningAddress = accountComplete ? - genAddress(payway, accounts[inputId], realAmount):"" + $: lightningAddress = accountComplete ? genAddress(payway, extAccount, realAmount):"" function lnurlEncode(url) { - return bech32.encode("LNURL", - bech32.toWords(UTF8.setBytesFromString(url)),2048) + return bech32.encode("LNURL", bech32.toWords(UTF8.setBytesFromString(url)),2048) } function toHexString(byteArray) { @@ -69,6 +75,7 @@ return ('0' + (byte & 0xFF).toString(16)).slice(-2); }).join('') } + function genAddress(payway,account,amount) { if (!account || !payway) return "" @@ -80,11 +87,12 @@ return prefix + account + "@" + payway.id + ".lnurl-pay.me" } - function genLNURL(payway,account,amount,memo) { + function genLNURL(payway,account,amount,memo,isEncrypted) { let params = new URLSearchParams(); params.set("mtg","pay"); params.set("p",payway.id); - params.set("acc",toHexString(UTF8.setBytesFromString(account))) + // don't hex-encode bech32-encoded account + params.set("acc",isEncrypted? account: toHexString(UTF8.setBytesFromString(account))) params.set("v","1") if (amount) { params.set(payway.currency.toLowerCase(),amount) @@ -95,6 +103,7 @@ return lnurlEncode("https://lnurl-pay.me/pay?"+params.toString()).toUpperCase() } + let accounts = {}; let amounts = {}; let memo; @@ -102,7 +111,7 @@ let lnurl; $: lnurl = accountComplete ? - genLNURL(payway, accounts[inputId], realAmount, memo) : ""; + genLNURL(payway, extAccount, realAmount, memo, encrypt) : ""; const curr = { "UAH":"₴", @@ -138,15 +147,26 @@ {#key payway}