1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
|
import { browser } from "$app/environment";
import { getCachedPrfKey } from "$lib/passwordCache";
const DERIVATION_EVENT = {
kind: 1,
created_at: 0,
content: "coinos-wallet-key-derivation",
tags: [],
};
async function hashSignature(sig: string): Promise<ArrayBuffer> {
const sigBytes = new Uint8Array(sig.length / 2);
for (let i = 0; i < sig.length; i += 2) sigBytes[i / 2] = parseInt(sig.slice(i, i + 2), 16);
return crypto.subtle.digest("SHA-256", sigBytes);
}
/**
* Silent helper. Checks localStorage for nsec, signs fixed event locally,
* caches and returns entropy. Returns null if no nsec stored.
*/
export async function tryDeriveFromNsec(): Promise<ArrayBuffer | null> {
if (!browser) return null;
const nsec = localStorage.getItem("nsec");
if (!nsec) return null;
try {
const [nip19, { finalizeEvent }] = await Promise.all([
import("nostr-tools/nip19"),
import("nostr-tools/pure"),
]);
const sk = nip19.decode(nsec).data as Uint8Array;
const signed = finalizeEvent({ ...DERIVATION_EVENT } as any, sk);
return await hashSignature(signed.sig);
} catch (e) {
console.log("nsec entropy derivation failed", e);
return null;
}
}
/**
* Non-interactive. Checks cached prfKey, then tries silent nsec derivation.
* Returns null if neither available. Use in onMount and auto-provisioning.
*/
export async function getWalletEntropy(): Promise<ArrayBuffer | null> {
const cached = getCachedPrfKey();
if (cached) return cached;
return tryDeriveFromNsec();
}
/**
* Interactive. Tries silent nsec first, then calls sign() from $lib/nostr
* which shows Nostr.svelte modal if signer isn't ready. Caches result.
* Use for "Unlock" buttons.
*/
export async function deriveNostrEntropy(): Promise<ArrayBuffer> {
const cached = getCachedPrfKey();
if (cached) return cached;
const fromNsec = await tryDeriveFromNsec();
if (fromNsec) return fromNsec;
const { sign } = await import("$lib/nostr");
const signed = await sign({ ...DERIVATION_EVENT });
return hashSignature(signed.sig);
}
|