1(()=>{2 let g = globalThis3 if (g.helium) return4 let P = 2n ** 256n - 0x1000003d1n, N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n5 let G = [0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n, 0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n]6 let mod = (a, m = P)=>(a %= m) < 0n ? a + m : a7 let inv = (a, m = P)=>{8 let [r0, r1, s0, s1] = [mod(a, m), m, 1n, 0n]9 while (r1){10 let q = r0 / r1;11 [r0, r1, s0, s1] = [r1, r0 - q * r1, s1, s0 - q * s1]12 }13 return mod(s0, m)14 }15 let pow = (b, e, r = 1n)=>{16 for (b = mod(b); e; e >>= 1n, b = b * b % P) if (e & 1n) r = r * b % P17 return r18 }19 let add = (p, q)=>{20 if (!p || !q) return p || q21 let [x1, y1] = p, [x2, y2] = q22 if (x1 == x2 && y1 != y2) return null23 let l = x1 == x2 ? 3n * x1 * x1 * inv(2n * y1) : (y2 - y1) * inv(x2 - x1), x3 = mod(l * l - x1 - x2)24 return [x3, mod(l * (x1 - x3) - y1)]25 }26 let mul = (k, p = G, r = null)=>{27 for (; k; k >>= 1n, p = add(p, p)) if (k & 1n) r = add(r, p)28 return r29 }30 let lift = (x)=>{31 let c = mod(x * x * x + 7n), y = pow(c, (P + 1n) / 4n)32 if (x >= P || y * y % P != c) throw Error("bad point")33 return [x, y & 1n ? P - y : y]34 }35 let hex = (b)=>[...b].map((x)=>x.toString(16).padStart(2, "0")).join("")36 let bytes = (h)=>Uint8Array.from(h.match(/../g), (x)=>parseInt(x, 16))37 let num = (b)=>BigInt("0x" + hex(b))38 let b32 = (n)=>bytes(n.toString(16).padStart(64, "0"))39 let cat = (...a)=>{40 let o = new Uint8Array(a.reduce((s, x)=>s + x.length, 0)), i = 041 for (let x of a) o.set(x, i), i += x.length42 return o43 }44 let te = new TextEncoder()45 let sha = async(...a)=>new Uint8Array(await crypto.subtle.digest("SHA-256", cat(...a)))46 let tagged = async(tag, ...a)=>{47 let t = await sha(te.encode(tag))48 return num(await sha(t, t, ...a))49 }50 let sign = async(m, sk, aux = crypto.getRandomValues(new Uint8Array(32)))=>{51 let d0 = num(sk)52 if (!d0 || d0 >= N) throw Error("bad key")53 let p = mul(d0), d = p[1] & 1n ? N - d0 : d0, px = b32(p[0])54 let k0 = mod(await tagged("BIP0340/nonce", b32(d ^ await tagged("BIP0340/aux", aux)), px, m), N)55 let R = mul(k0), k = R[1] & 1n ? N - k0 : k0, rx = b32(R[0])56 let e = mod(await tagged("BIP0340/challenge", rx, px, m), N)57 return cat(rx, b32(mod(k + e * d, N)))58 }59 let verify = async(sig, m, pk)=>{60 try {61 let r = num(sig.slice(0, 32)), s = num(sig.slice(32)), p = lift(num(pk))62 if (sig.length != 64 || r >= P || s >= N) return false63 let e = mod(await tagged("BIP0340/challenge", sig.slice(0, 32), pk, m), N)64 let R = add(mul(s), mul(N - e, p))65 return !!R && !(R[1] & 1n) && R[0] == r66 } catch { return false }67 }68 let generate = (k)=>{69 while (!k || num(k) >= N) k = crypto.getRandomValues(new Uint8Array(32))70 return hex(k)71 }72 let pub = (sk)=>hex(b32(mul(num(bytes(sk)))[0]))73 let shared = (sk, pk)=>hex(b32(mul(num(bytes(sk)), lift(num(bytes(pk))))[0]))74 let id = async(e)=>hex(await sha(te.encode(JSON.stringify([0, e.pubkey, e.created_at, e.kind, e.tags, e.content]))))75 let finish = async(e, sk)=>{76 e = {...e, pubkey:pub(sk)}77 e.id = await id(e)78 e.sig = hex(await sign(bytes(e.id), bytes(sk)))79 return e80 }81 let check = async(e)=>{82 try { return e.id == await id(e) && verify(bytes(e.sig), bytes(e.id), bytes(e.pubkey)) } catch { return false }83 }84 let key = (k)=>{85 let s = g.localStorage86 if (k !== undefined) k ? s["nhe:key"] = k : delete s["nhe:key"]87 return s["nhe:key"] ||= s["nkr:key"] || generate()88 }89 let signer = {getPublicKey:async()=>pub(key()), signEvent:(e)=>finish(e, key())}90 g.helium = {generate, pub, shared, id, sign, verify, finish, check, key, signer}91 g.document?.addEventListener("nhy:config", (evt)=>{92 let c = evt.detail.cfg93 if (c.event && (g.nheCfg?.local || !g.nostr)) c.sign = signer.signEvent94 if (c.filters && (g.nheCfg?.verify || c.elt?.closest("[nhe-verify]"))) c.verify = check95 })96})()