diff options
| author | Adam Soltys <[email protected]> | 2026-02-26 16:07:52 -0800 |
|---|---|---|
| committer | Adam Soltys <[email protected]> | 2026-02-26 16:07:52 -0800 |
| commit | 18df062a099811355cafc2024e30a7c2b68c7984 (patch) | |
| tree | 1de4c341b3111f7ccc6c0e74824b2bc6115d3401 /src/lib | |
| parent | 2a59047dc8fc10560a7fde614238ee821cfb6b1b (diff) | |
| download | coinos-ui-18df062a099811355cafc2024e30a7c2b68c7984.tar.gz coinos-ui-18df062a099811355cafc2024e30a7c2b68c7984.zip | |
client side password auth
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/deriveAuthKey.ts | 23 | ||||
| -rw-r--r-- | src/lib/utils.ts | 12 |
2 files changed, 35 insertions, 0 deletions
diff --git a/src/lib/deriveAuthKey.ts b/src/lib/deriveAuthKey.ts new file mode 100644 index 00000000..9215b515 --- /dev/null +++ b/src/lib/deriveAuthKey.ts @@ -0,0 +1,23 @@ +import { scryptAsync } from "@noble/hashes/scrypt.js"; +import { bytesToHex } from "@noble/hashes/utils.js"; +import { getPublicKey } from "nostr-tools"; +import { rememberPrfKey, defaultRememberForMs } from "$lib/passwordCache"; + +export async function deriveAuthKeypair(username: string, password: string) { + const salt = `coinos:auth:${username.toLowerCase().replace(/\s/g, "")}`; + const sk = await scryptAsync(password, salt, { N: 2 ** 16, r: 8, p: 1, dkLen: 32 }); + const pubkey = getPublicKey(sk); + return { sk, pubkey, skHex: bytesToHex(sk) }; +} + +export async function deriveWalletEntropy(sk: Uint8Array): Promise<ArrayBuffer> { + const { finalizeEvent } = await import("nostr-tools"); + const event = { kind: 1, created_at: 0, content: "coinos-wallet-key-derivation", tags: [] }; + const signed = finalizeEvent(event as any, sk); + const sigBytes = new Uint8Array(signed.sig.length / 2); + for (let i = 0; i < signed.sig.length; i += 2) + sigBytes[i / 2] = parseInt(signed.sig.slice(i, i + 2), 16); + const entropy = await crypto.subtle.digest("SHA-256", sigBytes); + rememberPrfKey(entropy, defaultRememberForMs); + return entropy; +} diff --git a/src/lib/utils.ts b/src/lib/utils.ts index 4bf96d6e..eee6903e 100644 --- a/src/lib/utils.ts +++ b/src/lib/utils.ts @@ -164,6 +164,7 @@ export const login = async ( token?: string; challenge?: string; recaptcha?: string; + authPubkey?: string; }, cookies, ip: string, @@ -509,6 +510,17 @@ export const register = async ( }; if (ip) headers["cf-connecting-ip"] = ip; + // Derive authPubkey if password provided + if (user.password && user.username) { + try { + const { deriveAuthKeypair } = await import("$lib/deriveAuthKey"); + const { pubkey: authPubkey } = await deriveAuthKeypair(user.username, user.password); + user.authPubkey = authPubkey; + } catch (e) { + console.log("Failed to derive authPubkey during registration", e); + } + } + let sk, token; try { ({ sk, token } = await post("/register", { user }, headers)); |
