diff options
| author | Adam Soltys <[email protected]> | 2026-02-16 20:56:39 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-16 20:56:39 -0800 |
| commit | b22c813f9fb3b4d69dade75d22e90e6779919f07 (patch) | |
| tree | 173fe377e83ad65ac6721dd567d8e90d9d204be8 /src/lib | |
| parent | 8bb150db1f73164030f9e8085c13765120363644 (diff) | |
| download | coinos-ui-b22c813f9fb3b4d69dade75d22e90e6779919f07.tar.gz coinos-ui-b22c813f9fb3b4d69dade75d22e90e6779919f07.zip | |
nostr key derivation
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/passwordCache.ts | 12 | ||||
| -rw-r--r-- | src/lib/walletEntropy.ts | 67 |
2 files changed, 73 insertions, 6 deletions
diff --git a/src/lib/passwordCache.ts b/src/lib/passwordCache.ts index 98272e0f..0ed36af1 100644 --- a/src/lib/passwordCache.ts +++ b/src/lib/passwordCache.ts @@ -5,12 +5,12 @@ const PASSWORD_KEY = "walletPassword"; const EXPIRES_KEY = "walletPasswordExpiresAt"; export const rememberForOptions = [ - { label: "Don't remember", ms: 0 }, - { label: "8 hours", ms: 8 * 60 * 60 * 1000 }, - { label: "1 day", ms: 24 * 60 * 60 * 1000 }, - { label: "1 week", ms: 7 * 24 * 60 * 60 * 1000 }, - { label: "1 month", ms: 30 * 24 * 60 * 60 * 1000 }, - { label: "1 year", ms: 365 * 24 * 60 * 60 * 1000 }, + { label: "user.settings.dontRemember", ms: 0 }, + { label: "user.settings.8hours", ms: 8 * 60 * 60 * 1000 }, + { label: "user.settings.1day", ms: 24 * 60 * 60 * 1000 }, + { label: "user.settings.1week", ms: 7 * 24 * 60 * 60 * 1000 }, + { label: "user.settings.1month", ms: 30 * 24 * 60 * 60 * 1000 }, + { label: "user.settings.1year", ms: 365 * 24 * 60 * 60 * 1000 }, ]; export const defaultRememberForMs = 30 * 24 * 60 * 60 * 1000; diff --git a/src/lib/walletEntropy.ts b/src/lib/walletEntropy.ts new file mode 100644 index 00000000..f022a2cc --- /dev/null +++ b/src/lib/walletEntropy.ts @@ -0,0 +1,67 @@ +import { browser } from "$app/environment"; +import { getCachedPrfKey, rememberPrfKey, defaultRememberForMs } 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 import("nostr-tools"); + const sk = nip19.decode(nsec).data as Uint8Array; + const signed = finalizeEvent({ ...DERIVATION_EVENT } as any, sk); + const entropy = await hashSignature(signed.sig); + rememberPrfKey(entropy, defaultRememberForMs); + return entropy; + } 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 }); + const entropy = await hashSignature(signed.sig); + rememberPrfKey(entropy, defaultRememberForMs); + return entropy; +} |
