diff options
| author | Adam Soltys <[email protected]> | 2025-09-29 21:47:18 -0700 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2025-09-29 21:50:57 -0700 |
| commit | 481dec5b1cfa2a085dda500ce0c390b38cb4a8b0 (patch) | |
| tree | 892efd033af9e889ca60cb816183deb0f2e8c2ef | |
| parent | c901c9571ff9406188a8bbb68c701ad3b21c24eb (diff) | |
| download | coinos-server-481dec5b1cfa2a085dda500ce0c390b38cb4a8b0.tar.gz coinos-server-481dec5b1cfa2a085dda500ce0c390b38cb4a8b0.zip | |
rotate server key
| -rw-r--r-- | config.ts.sample | 1 | ||||
| -rw-r--r-- | lib/nostr.ts | 9 | ||||
| -rw-r--r-- | lib/notifications.ts | 6 | ||||
| -rw-r--r-- | lib/nwc.ts | 41 | ||||
| -rw-r--r-- | routes/lnurl.ts | 6 | ||||
| -rw-r--r-- | routes/users.ts | 6 |
6 files changed, 53 insertions, 16 deletions
diff --git a/config.ts.sample b/config.ts.sample index d58e2f70..1becf362 100644 --- a/config.ts.sample +++ b/config.ts.sample @@ -36,6 +36,7 @@ export default { adminpass: "pwa", support: "[email protected]", nostrKey: "nsec1msk3dqy2pzqy2murmm5s5gejfgkjkm2zesnh266gud2wcvhcunzqlu0h90", + nostrKey2: "nsec17ugnsk0qrnakf7xaxzckya4xvx58q063k6q4vq2l577k4uyv9r0qmdcgm5", mintUrl: "http://mint:3338", square: { environment: SquareEnvironment.Sandbox, diff --git a/lib/nostr.ts b/lib/nostr.ts index 4c28ebc9..1d4ab56f 100644 --- a/lib/nostr.ts +++ b/lib/nostr.ts @@ -16,7 +16,12 @@ export const serverSecret = bytesToHex( nip19.decode(config.nostrKey).data as Uint8Array, ); +export const serverSecret2 = bytesToHex( + nip19.decode(config.nostrKey2).data as Uint8Array, +); + export const serverPubkey = getPublicKey(serverSecret); +export const serverPubkey2 = getPublicKey(serverSecret2); const alwaysTrue: any = (t: Event) => { t[Symbol("verified")] = true; @@ -42,7 +47,7 @@ export async function publish(ev, url = config.nostr) { export async function handleZap(invoice, sender = undefined) { try { - const pubkey = serverPubkey; + const pubkey = serverPubkey2; const zapreq = JSON.parse(invoice.description); if (!zapreq.tags || zapreq.tags.length === 0) { @@ -95,7 +100,7 @@ export async function handleZap(invoice, sender = undefined) { tags.push(["preimage", invoice.payment_preimage]); const ev = { pubkey, kind, created_at, content, tags }; - const signed = await finalizeEvent(ev, serverSecret); + const signed = await finalizeEvent(ev, serverSecret2); l("sending receipt"); diff --git a/lib/notifications.ts b/lib/notifications.ts index d5b4f73f..31175916 100644 --- a/lib/notifications.ts +++ b/lib/notifications.ts @@ -4,7 +4,7 @@ import ln from "$lib/ln"; import { err, l, warn } from "$lib/logging"; import { mail, templates } from "$lib/mail"; import mqtt from "$lib/mqtt"; -import { publish, serverSecret } from "$lib/nostr"; +import { publish, serverSecret2 } from "$lib/nostr"; import { emit } from "$lib/sockets"; import { f, fiat, fmt, getUser, link, nada, t } from "$lib/utils"; import { hexToBytes } from "@noble/hashes/utils"; @@ -108,7 +108,7 @@ export const nwcNotify = async (p) => { notification, }); - const content = await nip04.encrypt(serverSecret, pubkey, payload); + const content = await nip04.encrypt(serverSecret2, pubkey, payload); const unsigned = { content, @@ -117,7 +117,7 @@ export const nwcNotify = async (p) => { created_at: Math.floor(Date.now() / 1000), }; - const event = finalizeEvent(unsigned, hexToBytes(serverSecret)); + const event = finalizeEvent(unsigned, hexToBytes(serverSecret2)); publish(event).catch(nada); } @@ -3,7 +3,13 @@ import { db, g } from "$lib/db"; import { generate } from "$lib/invoices"; import ln from "$lib/ln"; import { err, l, warn } from "$lib/logging"; -import { handleZap, serverPubkey, serverSecret } from "$lib/nostr"; +import { + handleZap, + serverPubkey, + serverPubkey2, + serverSecret, + serverSecret2, +} from "$lib/nostr"; import { sendInternal, sendKeysend, sendLightning } from "$lib/payments"; import { fail, getInvoice, sleep } from "$lib/utils"; import rpc from "@coinos/rpc"; @@ -12,6 +18,11 @@ import { Relay } from "nostr"; import { finalizeEvent, nip04 } from "nostr-tools"; import type { UnsignedEvent } from "nostr-tools"; +const serverKeys = { + [serverPubkey]: serverSecret, + [serverPubkey2]: serverSecret2, +}; + const result = (result) => ({ result }); const error = (error) => ({ error }); const bc = rpc(config.bitcoin); @@ -32,7 +43,7 @@ export default () => { const r = new Relay("ws://sf:7777"); r.on("open", async (_) => { - r.subscribe("nwc", { kinds: [23194], "#p": [serverPubkey] }); + r.subscribe("nwc", { kinds: [23194], "#p": [serverPubkey, serverPubkey2] }); const info = await finalizeEvent( { created_at: Math.floor(Date.now() / 1000), @@ -46,16 +57,34 @@ export default () => { hexToBytes(serverSecret), ); r.send(["EVENT", info]); + + const info2 = await finalizeEvent( + { + created_at: Math.floor(Date.now() / 1000), + kind: 13194, + tags: [ + ["p", serverPubkey2], + ["notifications", "payment_received payment_sent"], + ], + content: methods.join(" "), + }, + hexToBytes(serverSecret2), + ); + r.send(["EVENT", info2]); }); r.on("event", async (sub, ev) => { try { if (sub !== "nwc") return; if (await db.sIsMember("handled", ev.id)) return; + db.sAdd("handled", ev.id); let { content, pubkey } = ev; + const pk = ev.tags.find((t) => t[0] === "p")[1]; + console.log(pk); + const sk = serverKeys[pk]; const { params, method } = JSON.parse( - await nip04.decrypt(serverSecret, pubkey, content), + await nip04.decrypt(sk, pubkey, content), ); // console.log("nwc", method, params, pubkey); @@ -69,7 +98,7 @@ export default () => { const result = await handle(method, params, ev, app, user); const payload = JSON.stringify({ result_type: method, ...result }); - content = await nip04.encrypt(serverSecret, pubkey, payload); + content = await nip04.encrypt(sk, pubkey, payload); let response: UnsignedEvent = { created_at: Math.floor(Date.now() / 1000), @@ -82,9 +111,10 @@ export default () => { content, }; - response = await finalizeEvent(response, hexToBytes(serverSecret)); + response = await finalizeEvent(response, hexToBytes(sk)); r.send(["EVENT", response]); } catch (e) { + console.log("BOOM", e); err( "problem with nwc", pubkey, @@ -94,6 +124,7 @@ export default () => { ); } } catch (e) { + console.log("BOOM2", e); err("problem with nwc", e.message); } }); diff --git a/routes/lnurl.ts b/routes/lnurl.ts index 239da2bd..729cca58 100644 --- a/routes/lnurl.ts +++ b/routes/lnurl.ts @@ -1,7 +1,7 @@ import { db, g, s } from "$lib/db"; import { generate } from "$lib/invoices"; import { err, warn } from "$lib/logging"; -import { serverPubkey } from "$lib/nostr"; +import { serverPubkey2 } from "$lib/nostr"; import { SATS, bail, fail, getInvoice, getUser } from "$lib/utils"; import { bech32 } from "bech32"; import got from "got"; @@ -82,7 +82,7 @@ export default { minSendable, maxSendable, metadata, - nostrPubkey: serverPubkey, + nostrPubkey: serverPubkey2, commentAllowed: 512, callback: `${URL}/api/lnurl/${id}`, tag: "payRequest", @@ -220,7 +220,7 @@ export default { minSendable: invoice.amount ? total : 1000, maxSendable: invoice.amount ? total : 10 * 1000 * SATS, metadata, - nostrPubkey: serverPubkey, + nostrPubkey: serverPubkey2, commentAllowed: 512, callback: `${URL}/api/lnurl/${id}`, tag: "payRequest", diff --git a/routes/users.ts b/routes/users.ts index 94deeed7..7b9a486b 100644 --- a/routes/users.ts +++ b/routes/users.ts @@ -5,7 +5,7 @@ import { requirePin } from "$lib/auth"; import { db, g, ga, s } from "$lib/db"; import { err, l, warn } from "$lib/logging"; import { mail, templates } from "$lib/mail"; -import { getNostrUser, getProfile, serverPubkey } from "$lib/nostr"; +import { getNostrUser, getProfile, serverPubkey2 } from "$lib/nostr"; import { reconcile } from "$lib/payments"; import register from "$lib/register"; import { emit } from "$lib/sockets"; @@ -899,7 +899,7 @@ export default { }), ); - app.nwc = `nostr+walletconnect://${serverPubkey}?relay=${relay}&secret=${app.secret}&lud16=${lud16}`; + app.nwc = `nostr+walletconnect://${serverPubkey2}?relay=${relay}&secret=${app.secret}&lud16=${lud16}`; app.payments = payments.filter((p) => p); res.send(app); @@ -915,7 +915,7 @@ export default { await Promise.all( apps.map(async (a) => { if (a.secret) - a.nwc = `nostr+walletconnect://${serverPubkey}?relay=${relay}&secret=${a.secret}&lud16=${lud16}`; + a.nwc = `nostr+walletconnect://${serverPubkey2}?relay=${relay}&secret=${a.secret}&lud16=${lud16}`; const pids = await db.lRange(`${a.pubkey}:payments`, 0, -1); let payments = await Promise.all( |
