aboutsummaryrefslogtreecommitdiffstats
path: root/src/lib/nostr.ts
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib/nostr.ts')
-rw-r--r--src/lib/nostr.ts42
1 files changed, 30 insertions, 12 deletions
diff --git a/src/lib/nostr.ts b/src/lib/nostr.ts
index bfaa14c1..2e993f9d 100644
--- a/src/lib/nostr.ts
+++ b/src/lib/nostr.ts
@@ -8,7 +8,7 @@ import {
signer as $signer,
} from "$lib/store";
import { post, wait } from "$lib/utils";
-import { bytesToHex } from "@noble/hashes/utils";
+import { bytesToHex, hexToBytes } from "@noble/hashes/utils.js";
import {
type EventTemplate,
finalizeEvent,
@@ -20,6 +20,7 @@ import {
import { decrypt as nip44decrypt, getConversationKey } from "nostr-tools/nip44";
import { Relay } from "nostr-tools/relay";
import { get } from "svelte/store";
+import cookies from "js-cookie";
import {
decrypt as nip49decrypt,
@@ -72,12 +73,22 @@ export const getPrivateKey = async (user: User): Promise<Uint8Array> => {
}
}
- const { nsec } = user;
+ // /me no longer returns the encrypted key; /login decrypts it into the
+ // sk cookie instead. user.nsec is only present on a fresh login response.
+ // Sessions without either (nostr or older logins) fetch it with the
+ // password.
+ const sk = browser && cookies.get("sk");
+ let { nsec } = user;
- if (nsec) {
+ if (!sk && !nsec && user.hasnsec)
+ ({ nsec } = await post("/nsec", { password: await getPassword() }));
+
+ if (sk) {
+ k = hexToBytes(sk);
+ } else if (nsec) {
k = nip49decrypt(nsec, await getPassword());
} else {
- throw new Error("nsec not available");
+ throw new Error("Log in again with your password to unlock your nostr key");
}
localStorage.setItem("nsec", nip19.nsecEncode(k));
@@ -105,7 +116,7 @@ export const encryptNsec = async (nsec: string) => {
};
export const sign = async (event, user) => {
- if (user?.nsec && !get($signer)?.ready) {
+ if ((user?.hasnsec || user?.nsec) && !get($signer)?.ready) {
const sk = await getPrivateKey(user);
$signer.set({
@@ -117,8 +128,14 @@ export const sign = async (event, user) => {
eventToSign.set(event);
let unsubscribe;
- const { method, params } = await new Promise((r) => {
- unsubscribe = $signer.subscribe((v) => v?.ready && r(v));
+ const { method, params } = await new Promise((r, j) => {
+ unsubscribe = $signer.subscribe((v) => {
+ if (v === "cancel") {
+ j("cancelled");
+ $signer.set(undefined);
+ }
+ v?.ready && r(v);
+ });
});
await unsubscribe();
const signedEvent = await signingMethods[method](event, params);
@@ -148,7 +165,8 @@ const signingMethods = {
params: [JSON.stringify(event)],
};
- const content = await nip04.encrypt(sk, pk, JSON.stringify(signEvent));
+ const skBytes = hexToBytes(sk);
+ const content = await nip04.encrypt(skBytes, pk, JSON.stringify(signEvent));
const signedSignEvent = finalizeEvent(
{
@@ -158,7 +176,7 @@ const signingMethods = {
content,
tags: [["p", pk]],
},
- sk,
+ skBytes,
);
const relay = await Relay.connect(nostrConnectRelay);
@@ -171,9 +189,9 @@ const signingMethods = {
try {
let response;
try {
- response = JSON.parse(await nip04.decrypt(sk, pk, event.content));
+ response = JSON.parse(await nip04.decrypt(hexToBytes(sk), pk, event.content));
} catch (e) {
- const ck = await getConversationKey(sk, pk);
+ const ck = await getConversationKey(hexToBytes(sk), pk);
response = JSON.parse(await nip44decrypt(event.content, ck));
}
@@ -187,7 +205,7 @@ const signingMethods = {
},
async nsec(event, { sk }) {
- return finalizeEvent(event, sk);
+ return finalizeEvent(event, hexToBytes(sk));
},
async extension(event) {