diff --git a/src/index.html b/src/index.html index c72acfd..47c8126 100644 --- a/src/index.html +++ b/src/index.html @@ -4595,6 +4595,180 @@ // ---- end NWC crypto ----------------------------------------------------- + // ---- Premium soft-gate crypto (PREMIUM_DESIGNS_FEATURE.md §6) ----------- + // Static client-side decryption gate for premium designs. The AES key is + // derived from a per-design public salt + a client-side "pepper" + a + // discriminator string. The pepper is obfuscated (split into byte + // fragments held in unrelated-looking places); reconstructing it from a + // minified bundle is annoying-but-doable, which is honest about what this + // gives us: protection against drive-by scraping, not strong DRM. The + // spec calls this a "soft gate." + // + // Epoch rotation: every premium design records the epoch it was + // published under. When an epoch's pepper gets reverse-engineered we + // can ship a new epoch and rotate forward; old designs stay readable + // by anyone who knows the old derivation but new designs are protected + // by the new one. Adding a new epoch is "add one entry to + // `_softGatePepperParts`." + const Premium = (() => { + // 4-part pepper per epoch. Stored as four Uint8Arrays in this lookup + // table, indexed by epoch. Reconstruction concatenates them — the + // pieces don't look like anything individually. Each 8 bytes was + // generated from crypto.getRandomValues at spec-adoption time; comment + // calls them "palette seeds" to avoid an obvious "PREMIUM_KEY" string + // in the source. (Determined readers will still find this; we accept + // that — see PREMIUM_DESIGNS_FEATURE.md §2.) + const _softGatePepperParts = { + '2026-05': [ + new Uint8Array([0x8c, 0x2b, 0xd1, 0x47, 0x9e, 0x60, 0x35, 0xaa]), // palette seed I + new Uint8Array([0x14, 0xf3, 0x59, 0xb2, 0x7d, 0xc8, 0x06, 0xef]), // palette seed II + new Uint8Array([0xa5, 0x71, 0x4e, 0x2c, 0x9b, 0x88, 0x33, 0xd0]), // palette seed III + new Uint8Array([0x62, 0x09, 0xfd, 0x18, 0x4a, 0xe7, 0xc4, 0x95]), // palette seed IV + ], + }; + const SUPPORTED_EPOCHS = Object.freeze(Object.keys(_softGatePepperParts)); + const CURRENT_EPOCH = '2026-05'; + const PREMIUM_KDF_INFO = 'artstr-softgate-v1'; + + function pepperBytesForEpoch(epoch) { + const parts = _softGatePepperParts[epoch]; + if (!parts) throw new Error(`Unsupported soft-gate epoch: ${epoch}`); + const total = parts.reduce((n, p) => n + p.length, 0); + const out = new Uint8Array(total); + let off = 0; + for (const p of parts) { out.set(p, off); off += p.length; } + return out; + } + + // HKDF-SHA256 → 32-byte AES key. Inputs: + // epoch — string ("2026-05") from the envelope + // creatorPubkey — 64-hex + // premiumAddress — "30078::" + // schemaVersion — number, e.g. 5 + // publicDesignSalt — Uint8Array (from envelope) + // puzzleNonce — optional UTF-8 string mixed into info + function deriveKey({ epoch, creatorPubkey, premiumAddress, schemaVersion, publicDesignSalt, puzzleNonce }) { + if (!_softGatePepperParts[epoch]) throw new Error(`Unsupported soft-gate epoch: ${epoch}`); + const enc = new TextEncoder(); + const infoStr = PREMIUM_KDF_INFO + '|' + epoch + '|' + creatorPubkey + '|' + premiumAddress + '|v' + schemaVersion + + (puzzleNonce ? '|p' + puzzleNonce : ''); + return window.ArtstrNoble.hkdf( + window.ArtstrNoble.sha256, + pepperBytesForEpoch(epoch), // IKM + publicDesignSalt, // salt + enc.encode(infoStr), // info + 32, // length + ); + } + + // AAD binds ciphertext to the event coordinate so a copy-paste to a + // different event address fails authentication. + function encodeAad(creatorPubkey, dTag) { + return new TextEncoder().encode(`30078:${creatorPubkey}:${dTag}`); + } + + const _bytesToB64 = (b) => { let s = ''; for (let i = 0; i < b.length; i++) s += String.fromCharCode(b[i]); return btoa(s); }; + const _b64ToBytes = (b64) => Uint8Array.from(atob(b64), (c) => c.charCodeAt(0)); + + // Encrypt a Nostr design payload object → envelope (per spec §5.2). + // `coord` is { creatorPubkey, dTag, schemaVersion }. Generates a random + // 32-byte design salt + 12-byte IV. The returned envelope has the same + // shape the consumer expects, base64'd. + async function encryptPayload(payloadObj, coord, opts = {}) { + const epoch = opts.epoch || CURRENT_EPOCH; + const publicDesignSalt = crypto.getRandomValues(new Uint8Array(32)); + const iv = crypto.getRandomValues(new Uint8Array(12)); + const premiumAddress = `30078:${coord.creatorPubkey}:${coord.dTag}`; + const keyBytes = deriveKey({ + epoch, + creatorPubkey: coord.creatorPubkey, + premiumAddress, + schemaVersion: coord.schemaVersion, + publicDesignSalt, + }); + const key = await crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM' }, false, ['encrypt']); + const aad = encodeAad(coord.creatorPubkey, coord.dTag); + const plaintext = new TextEncoder().encode(JSON.stringify(payloadObj)); + const ct = new Uint8Array(await crypto.subtle.encrypt( + { name: 'AES-GCM', iv, additionalData: aad }, key, plaintext + )); + return { + v: 1, + enc: { alg: 'aes-256-gcm', kdf: PREMIUM_KDF_INFO, compression: 'none' }, + aad: `30078:${coord.creatorPubkey}:${coord.dTag}`, + salt: _bytesToB64(publicDesignSalt), + iv: _bytesToB64(iv), + ciphertext: _bytesToB64(ct), + softgate: { + version: 1, epoch, + publicDesignSalt: _bytesToB64(publicDesignSalt), + purchaseScope: 'address', + puzzle: { enabled: false, difficultyBits: 0 }, + }, + }; + } + + // Decrypt an envelope back into the original payload object. Pulls + // epoch + salt out of the envelope; rebuilds the AAD from `coord`. + async function decryptPayload(envelope, coord) { + if (!envelope || envelope.enc?.alg !== 'aes-256-gcm') throw new Error('Unsupported envelope'); + const epoch = envelope.softgate?.epoch || CURRENT_EPOCH; + const publicDesignSalt = _b64ToBytes(envelope.softgate?.publicDesignSalt || envelope.salt); + const iv = _b64ToBytes(envelope.iv); + const ct = _b64ToBytes(envelope.ciphertext); + const premiumAddress = `30078:${coord.creatorPubkey}:${coord.dTag}`; + const keyBytes = deriveKey({ + epoch, + creatorPubkey: coord.creatorPubkey, + premiumAddress, + schemaVersion: coord.schemaVersion, + publicDesignSalt, + }); + const key = await crypto.subtle.importKey('raw', keyBytes, { name: 'AES-GCM' }, false, ['decrypt']); + const aad = encodeAad(coord.creatorPubkey, coord.dTag); + const pt = new Uint8Array(await crypto.subtle.decrypt( + { name: 'AES-GCM', iv, additionalData: aad }, key, ct + )); + return JSON.parse(new TextDecoder().decode(pt)); + } + + return { + SUPPORTED_EPOCHS, CURRENT_EPOCH, PREMIUM_KDF_INFO, + pepperBytesForEpoch, deriveKey, encodeAad, + encryptPayload, decryptPayload, + }; + })(); + + // Phase-1 self-test for the soft-gate primitive. Round-trips a known + // payload + verifies that mismatched AAD (event coordinate copy-paste) + // fails the decrypt as the spec requires. + (async () => { + try { + if (!window.ArtstrNoble?.hkdf) throw new Error('HKDF missing from noble bundle'); + const coord = { + creatorPubkey: 'a'.repeat(64), + dTag: 'premium:test:soft-gate-roundtrip', + schemaVersion: 5, + }; + const payload = { version: 5, hello: 'world', layers: [{ id: 'l1', type: 'color' }] }; + const env = await Premium.encryptPayload(payload, coord); + if (env.enc.alg !== 'aes-256-gcm') throw new Error('envelope alg wrong'); + if (!env.softgate?.epoch) throw new Error('envelope missing epoch'); + const round = await Premium.decryptPayload(env, coord); + if (JSON.stringify(round) !== JSON.stringify(payload)) throw new Error('round-trip mismatch'); + // AAD mismatch must fail (different dTag → different AAD → AES-GCM rejects). + let aadFailed = false; + try { + await Premium.decryptPayload(env, { ...coord, dTag: 'attacker:rebound' }); + } catch { aadFailed = true; } + if (!aadFailed) throw new Error('AAD mismatch did NOT fail decrypt — coordinate binding broken'); + } catch (err) { + console.warn('[Artstr] Premium soft-gate self-test failed — premium publish/unlock will not work:', err); + } + })(); + // ---- end Premium soft-gate crypto --------------------------------------- + + // ---- NWC client (Phase 1) ---------------------------------------------- // RPC-style client for a single NIP-47 wallet connection. One WebSocket, // one persistent subscription for kind-23195 responses + kind-13194 diff --git a/src/noble-bundle.min.js b/src/noble-bundle.min.js index a336a60..2fc24b6 100644 --- a/src/noble-bundle.min.js +++ b/src/noble-bundle.min.js @@ -1,4 +1,4 @@ -(()=>{var ae=Object.defineProperty;var ue=(t,e,n)=>e in t?ae(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var l=(t,e,n)=>ue(t,typeof e!="symbol"?e+"":e,n);var Ht=Object.freeze({p:0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,n:0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,h:1n,a:0n,b:7n,Gx:0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n,Gy:0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n}),{p:v,n:Z,Gx:he,Gy:de,b:St}=Ht,w=32,K=64,P={publicKey:w+1,publicKeyUncompressed:K+1,signature:K,seed:w+w/2},b=(t="",e=Error)=>{let n=new e(t),{captureStackTrace:s}=Error;throw typeof s=="function"&&s(n,b),n},le=t=>t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&t.BYTES_PER_ELEMENT===1,E=(t,e,n="")=>{let s=le(t),r=t?.length,o=e!==void 0;if(!s||o&&r!==e){let c=n&&`"${n}" `,f=o?` of length ${e}`:"",a=s?`length=${r}`:`type=${typeof t}`,h=c+"expected Uint8Array"+f+", got "+a;return s?b(h,RangeError):b(h,TypeError)}return t},j=t=>new Uint8Array(t),Bt=(t,e)=>t.toString(16).padStart(e,"0"),Lt=t=>{let e="";for(let n of E(t))e+=Bt(n,2);return e},_={_0:48,_9:57,A:65,F:70,a:97,f:102},bt=t=>t>=_._0&&t<=_._9?t-_._0:t>=_.A&&t<=_.F?t-(_.A-10):t>=_.a&&t<=_.f?t-(_.a-10):void 0,Ut=t=>{let e="hex invalid";if(typeof t!="string")return b(e);let n=t.length,s=n/2;if(n%2)return b(e);let r=j(s);for(let o=0,c=0;oglobalThis?.crypto?.subtle??b("crypto.subtle must be defined, consider polyfill"),R=(...t)=>{let e=0;for(let r of t)e+=E(r).length;let n=j(e),s=0;for(let r of t)n.set(r,s),s+=r.length;return n},at=(t=w)=>(globalThis?.crypto).getRandomValues(j(t)),ot=BigInt,V=(t,e,n,s="bad number: out of range")=>typeof t!="bigint"?b(s,TypeError):e<=t&&t{let n=t%e;return n>=0n?n:e+n},z=t=>i(t,Z),xe=(t,e)=>{(t===0n||e<=0n)&&b("no inverse n="+t+" mod="+e);let n=i(t,e),s=e,r=0n,o=1n,c=1n,f=0n;for(;n!==0n;){let a=s/n,h=s%n,d=r-c*a,u=o-f*a;s=n,n=h,r=c,o=f,c=d,f=u}return s===1n?i(r,e):b("no inverse")},_t=t=>{let e=J[t];return typeof e!="function"&&b("hashes."+t+" not set"),e},pt=(t,e,n)=>E(_t(t)(e,n),w,"digest"),gt=(t,e,n)=>Promise.resolve(_t(t)(e,n)).then(s=>E(s,w,"digest"));var rt=t=>t instanceof L?t:b("Point expected"),Tt=t=>i(i(t*t)*t+St),mt=t=>V(t,0n,v),M=t=>V(t,1n,v),be=t=>V(t,1n,Z),W=t=>!(t&1n),It=t=>Uint8Array.of(t),ye=t=>It(W(t)?2:3),vt=t=>{let e=Tt(M(t)),n=1n;for(let s=e,r=(v+1n)/4n;r>0n;r>>=1n)r&1n&&(n=n*s%v),s=s*s%v;return i(n*n)!==e&&b("sqrt invalid"),W(n)?n:i(-n)};var B=class B{constructor(e,n,s){l(this,"X");l(this,"Y");l(this,"Z");this.X=mt(e),this.Y=M(n),this.Z=mt(s),Object.freeze(this)}static CURVE(){return Ht}static fromAffine(e){let{x:n,y:s}=e;return n===0n&&s===0n?F:new B(n,s,1n)}static fromBytes(e){E(e);let{publicKey:n,publicKeyUncompressed:s}=P,r,o=e.length,c=e[0],f=e.subarray(1),a=Y(f,0,w);if(o===n&&(c===2||c===3)){let h=vt(a);c===3&&(h=i(-h)),r=new B(a,h,1n)}return o===s&&c===4&&(r=new B(a,Y(f,w,K),1n)),r?r.assertValidity():b("bad point: not on curve")}static fromHex(e){return B.fromBytes(Ut(e))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}equals(e){let{X:n,Y:s,Z:r}=this,{X:o,Y:c,Z:f}=rt(e),a=i(n*f),h=i(o*r),d=i(s*f),u=i(c*r);return a===h&&d===u}is0(){return this.equals(F)}negate(){return new B(this.X,i(-this.Y),this.Z)}double(){return this.add(this)}add(e){let{X:n,Y:s,Z:r}=this,{X:o,Y:c,Z:f}=rt(e),a=0n,h=St,d=0n,u=0n,x=0n,y=i(h*3n),p=i(n*o),g=i(s*c),A=i(r*f),O=i(n+s),m=i(o+c);O=i(O*m),m=i(p+g),O=i(O-m),m=i(n+r);let S=i(o+f);return m=i(m*S),S=i(p+A),m=i(m-S),S=i(s+r),d=i(c+f),S=i(S*d),d=i(g+A),S=i(S-d),x=i(a*m),d=i(y*A),x=i(d+x),d=i(g-x),x=i(g+x),u=i(d*x),g=i(p+p),g=i(g+p),A=i(a*A),m=i(y*m),g=i(g+A),A=i(p-A),A=i(a*A),m=i(m+A),p=i(g*m),u=i(u+p),p=i(S*m),d=i(O*d),d=i(d-p),p=i(O*g),x=i(S*x),x=i(x+p),new B(d,u,x)}subtract(e){return this.add(rt(e).negate())}multiply(e,n=!0){if(!n&&e===0n)return F;if(be(e),e===1n)return this;if(this.equals(C))return _e(e).p;let s=F,r=C;for(let o=this;e>0n;o=o.double(),e>>=1n)e&1n?s=s.add(o):n&&(r=r.add(o));return s}multiplyUnsafe(e){return this.multiply(e,!1)}toAffine(){let{X:e,Y:n,Z:s}=this;if(this.equals(F))return{x:0n,y:0n};if(s===1n)return{x:e,y:n};let r=xe(s,v);return i(s*r)!==1n&&b("inverse invalid"),{x:i(e*r),y:i(n*r)}}assertValidity(){let{x:e,y:n}=this.toAffine();return M(e),M(n),i(n*n)===Tt(e)?this:b("bad point: not on curve")}toBytes(e=!0){let{x:n,y:s}=this.assertValidity().toAffine(),r=U(n);return e?R(ye(s),r):R(It(4),r,U(s))}toHex(e){return Lt(this.toBytes(e))}};l(B,"BASE"),l(B,"ZERO");var L=B,C=new L(he,de,1n),F=new L(0n,1n,0n);L.BASE=C;L.ZERO=F;var pe=(t,e,n)=>C.multiply(e,!1).add(t.multiply(n,!1)).assertValidity(),G=t=>ot("0x"+(Lt(t)||"0")),Y=(t,e,n)=>G(t.subarray(e,n)),ge=2n**256n,U=t=>Ut(Bt(V(t,0n,ge),K)),q=t=>{let e=G(E(t,w,"secret key"));return V(e,1n,Z,"invalid secret key: outside of range")};var Ct=(t,e=!0)=>C.multiply(q(t)).toBytes(e),me=t=>{try{return!!q(t)}catch{return!1}},we=(t,e)=>{let{publicKey:n,publicKeyUncompressed:s}=P;try{let r=t.length;return e===!0&&r!==n||e===!1&&r!==s?!1:!!L.fromBytes(t)}catch{return!1}};var wt="SHA-256",J={hmacSha256Async:async(t,e)=>{let n=yt(),s="HMAC",r=await n.importKey("raw",t,{name:s,hash:{name:wt}},!1,["sign"]);return j(await n.sign(s,r,e))},hmacSha256:void 0,sha256Async:async t=>j(await yt().digest(wt,t)),sha256:void 0};var kt=(t,e,n=!0)=>L.fromBytes(e).multiply(q(t)).toBytes(n),Ft=t=>{if(t=t===void 0?at(P.seed):t,E(t),t.length1024)return b("expected 48-1024b",RangeError);let e=i(G(t),Z-1n);return U(e+1n)},Ae=t=>e=>{let n=Ft(e);return{secretKey:n,publicKey:t(n)}};var Vt=Object.freeze({isValidSecretKey:me,isValidPublicKey:we,randomSecretKey:Ft}),Gt=t=>Uint8Array.from("BIP0340/"+t,e=>e.charCodeAt(0)),Dt="aux",Ot="nonce",Kt="challenge",ct=(t,...e)=>{let n=pt("sha256",Gt(t));return pt("sha256",R(n,n,...e))},it=(t,...e)=>gt("sha256Async",Gt(t)).then(n=>gt("sha256Async",R(n,n,...e))),ut=t=>{let e=q(t),n=C.multiply(e),{x:s,y:r}=n.assertValidity().toAffine(),o=W(r)?e:z(-e),c=U(s);return{d:o,px:c}},ht=t=>z(G(t)),Rt=(...t)=>ht(ct(Kt,...t)),Nt=async(...t)=>ht(await it(Kt,...t)),Xt=t=>ut(t).px,Ee=Ae(Xt),jt=(t,e,n)=>{let{px:s,d:r}=ut(e);return{m:E(t),px:s,d:r,a:E(n,w)}},Zt=t=>{let e=ht(t);e===0n&&b("sign failed: k is zero");let{px:n,d:s}=ut(U(e));return{rx:n,k:s}},Mt=(t,e,n,s)=>R(e,U(z(t+n*s))),Pt="invalid signature produced",He=(t,e,n=at(w))=>{let{m:s,px:r,d:o,a:c}=jt(t,e,n),f=ct(Dt,c),a=U(o^G(f)),h=ct(Ot,a,r,s),{rx:d,k:u}=Zt(h),x=Rt(d,r,s),y=Mt(u,d,x,o);return $t(y,s,r)||b(Pt),y},Se=async(t,e,n=at(w))=>{let{m:s,px:r,d:o,a:c}=jt(t,e,n),f=await it(Dt,c),a=U(o^G(f)),h=await it(Ot,a,r,s),{rx:d,k:u}=Zt(h),x=await Nt(d,r,s),y=Mt(u,d,x,o);return await zt(y,s,r)||b(Pt),y},Be=(t,e)=>t instanceof Promise?t.then(e):e(t),Yt=(t,e,n,s)=>{let r=E(t,K,"signature"),o=E(e,void 0,"message"),c=E(n,w,"publicKey");try{let f=G(c),a=vt(f),h=new L(f,a,1n).assertValidity(),d=U(h.toAffine().x),u=Y(r,0,w);V(u,1n,v);let x=Y(r,w,K);V(x,1n,Z);let y=R(U(u),d,o);return Be(s(y),p=>{let{x:g,y:A}=pe(h,x,z(-p)).toAffine();return!(!W(A)||g!==u)})}catch{return!1}},$t=(t,e,n)=>Yt(t,e,n,Rt),zt=async(t,e,n)=>Yt(t,e,n,Nt),Wt=Object.freeze({keygen:Ee,getPublicKey:Xt,sign:He,verify:$t,signAsync:Se,verifyAsync:zt}),$=8,Le=256,qt=Math.ceil(Le/$)+1,ft=2**($-1),Ue=()=>{let t=[],e=C,n=e;for(let s=0;s{let n=e.negate();return t?n:e},_e=t=>{let e=At||(At=Ue()),n=F,s=C,r=2**$,o=r,c=ot(r-1),f=ot($);for(let a=0;a>=f,h>ft&&(h-=o,t+=1n);let d=a*ft,u=d,x=d+Math.abs(h)-1,y=a%2!==0,p=h<0;h===0?s=s.add(Et(y,e[u])):n=n.add(Et(p,e[x]))}return t!==0n&&b("invalid wnaf"),{p:n,f:s}};function Te(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in t&&t.BYTES_PER_ELEMENT===1}function dt(t,e=""){if(typeof t!="number"){let n=e&&`"${e}" `;throw new TypeError(`${n}expected number, got ${typeof t}`)}if(!Number.isSafeInteger(t)||t<0){let n=e&&`"${e}" `;throw new RangeError(`${n}expected integer >= 0, got ${t}`)}}function N(t,e,n=""){let s=Te(t),r=t?.length,o=e!==void 0;if(!s||o&&r!==e){let c=n&&`"${n}" `,f=o?` of length ${e}`:"",a=s?`length=${r}`:`type=${typeof t}`,h=c+"expected Uint8Array"+f+", got "+a;throw s?new RangeError(h):new TypeError(h)}return t}function Qt(t){if(typeof t!="function"||typeof t.create!="function")throw new TypeError("Hash must wrapped by utils.createHasher");if(dt(t.outputLen),dt(t.blockLen),t.outputLen<1)throw new Error('"outputLen" must be >= 1');if(t.blockLen<1)throw new Error('"blockLen" must be >= 1')}function X(t,e=!0){if(t.destroyed)throw new Error("Hash instance has been destroyed");if(e&&t.finished)throw new Error("Hash#digest() has already been called")}function Q(t,e){N(t,void 0,"digestInto() output");let n=e.outputLen;if(t.length='+n)}function D(...t){for(let e=0;e>>e}var te=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",Ie=Array.from({length:256},(t,e)=>e.toString(16).padStart(2,"0"));function ee(t){if(N(t),te)return t.toHex();let e="";for(let n=0;n=T._0&&t<=T._9)return t-T._0;if(t>=T.A&&t<=T.F)return t-(T.A-10);if(t>=T.a&&t<=T.f)return t-(T.a-10)}function ne(t){if(typeof t!="string")throw new TypeError("hex string expected, got "+typeof t);if(te)try{return Uint8Array.fromHex(t)}catch(r){throw r instanceof SyntaxError?new RangeError(r.message):r}let e=t.length,n=e/2;if(e%2)throw new RangeError("hex string expected, got unpadded hex of length "+e);let s=new Uint8Array(n);for(let r=0,o=0;rt(o).update(r).digest(),s=t(void 0);return n.outputLen=s.outputLen,n.blockLen=s.blockLen,n.canXOF=s.canXOF,n.create=r=>t(r),Object.assign(n,e),Object.freeze(n)}function re(t=32){dt(t,"bytesLength");let e=typeof globalThis=="object"?globalThis.crypto:null;if(typeof e?.getRandomValues!="function")throw new Error("crypto.getRandomValues must be defined");if(t>65536)throw new RangeError(`"bytesLength" expected <= 65536, got ${t}`);return e.getRandomValues(new Uint8Array(t))}var oe=t=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,t])});function ce(t,e,n){return t&e^~t&n}function ie(t,e,n){return t&e^t&n^e&n}var et=class{constructor(e,n,s,r){l(this,"blockLen");l(this,"outputLen");l(this,"canXOF",!1);l(this,"padOffset");l(this,"isLE");l(this,"buffer");l(this,"view");l(this,"finished",!1);l(this,"length",0);l(this,"pos",0);l(this,"destroyed",!1);this.blockLen=e,this.outputLen=n,this.padOffset=s,this.isLE=r,this.buffer=new Uint8Array(e),this.view=tt(this.buffer)}update(e){X(this),N(e);let{view:n,buffer:s,blockLen:r}=this,o=e.length;for(let c=0;cr-c&&(this.process(s,0),c=0);for(let u=c;ud.length)throw new Error("_sha2: outputLen bigger than state");for(let u=0;u>>3,g=H(y,17)^H(y,19)^y>>>10;k[u]=g+k[u-7]+p+k[u-16]|0}let{A:s,B:r,C:o,D:c,E:f,F:a,G:h,H:d}=this;for(let u=0;u<64;u++){let x=H(f,6)^H(f,11)^H(f,25),y=d+x+ce(f,a,h)+ve[u]+k[u]|0,g=(H(s,2)^H(s,13)^H(s,22))+ie(s,r,o)|0;d=h,h=a,a=f,f=c+y|0,c=o,o=r,r=s,s=y+g|0}s=s+this.A|0,r=r+this.B|0,o=o+this.C|0,c=c+this.D|0,f=f+this.E|0,a=a+this.F|0,h=h+this.G|0,d=d+this.H|0,this.set(s,r,o,c,f,a,h,d)}roundClean(){D(k)}destroy(){this.destroyed=!0,this.set(0,0,0,0,0,0,0,0),D(this.buffer)}},xt=class extends lt{constructor(){super(32);l(this,"A",I[0]|0);l(this,"B",I[1]|0);l(this,"C",I[2]|0);l(this,"D",I[3]|0);l(this,"E",I[4]|0);l(this,"F",I[5]|0);l(this,"G",I[6]|0);l(this,"H",I[7]|0)}};var nt=se(()=>new xt,oe(1));var st=class{constructor(e,n){l(this,"oHash");l(this,"iHash");l(this,"blockLen");l(this,"outputLen");l(this,"canXOF",!1);l(this,"finished",!1);l(this,"destroyed",!1);if(Qt(e),N(n,void 0,"key"),this.iHash=e.create(),typeof this.iHash.update!="function")throw new Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let s=this.blockLen,r=new Uint8Array(s);r.set(n.length>s?e.create().update(n).digest():n);for(let o=0;o{let t=((e,n,s)=>new st(e,n).update(s).digest());return t.create=(e,n)=>new st(e,n),t})();J.sha256=nt;J.hmacSha256=(t,...e)=>fe(nt,t,e.length===1?e[0]:(()=>{let n=e.reduce((o,c)=>o+c.length,0),s=new Uint8Array(n),r=0;for(let o of e)s.set(o,r),r+=o.length;return s})());window.ArtstrNoble={schnorr:Wt,getPublicKey:Ct,getSharedSecret:kt,sha256:nt,hexToBytes:ne,bytesToHex:ee,randomBytes:re,secpUtils:Vt};})(); +(()=>{var de=Object.defineProperty;var le=(t,e,n)=>e in t?de(t,e,{enumerable:!0,configurable:!0,writable:!0,value:n}):t[e]=n;var l=(t,e,n)=>le(t,typeof e!="symbol"?e+"":e,n);var Lt=Object.freeze({p:0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffc2fn,n:0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141n,h:1n,a:0n,b:7n,Gx:0x79be667ef9dcbbac55a06295ce870b07029bfcdb2dce28d959f2815b16f81798n,Gy:0x483ada7726a3c4655da4fbfc0e1108a8fd17b448a68554199c47d08ffb10d4b8n}),{p:v,n:P,Gx:xe,Gy:be,b:Ut}=Lt,w=32,K=64,z={publicKey:w+1,publicKeyUncompressed:K+1,signature:K,seed:w+w/2},b=(t="",e=Error)=>{let n=new e(t),{captureStackTrace:s}=Error;throw typeof s=="function"&&s(n,b),n},ye=t=>t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&t.BYTES_PER_ELEMENT===1,E=(t,e,n="")=>{let s=ye(t),r=t?.length,o=e!==void 0;if(!s||o&&r!==e){let c=n&&`"${n}" `,i=o?` of length ${e}`:"",a=s?`length=${r}`:`type=${typeof t}`,h=c+"expected Uint8Array"+i+", got "+a;return s?b(h,RangeError):b(h,TypeError)}return t},j=t=>new Uint8Array(t),_t=(t,e)=>t.toString(16).padStart(e,"0"),Tt=t=>{let e="";for(let n of E(t))e+=_t(n,2);return e},_={_0:48,_9:57,A:65,F:70,a:97,f:102},gt=t=>t>=_._0&&t<=_._9?t-_._0:t>=_.A&&t<=_.F?t-(_.A-10):t>=_.a&&t<=_.f?t-(_.a-10):void 0,It=t=>{let e="hex invalid";if(typeof t!="string")return b(e);let n=t.length,s=n/2;if(n%2)return b(e);let r=j(s);for(let o=0,c=0;oglobalThis?.crypto?.subtle??b("crypto.subtle must be defined, consider polyfill"),N=(...t)=>{let e=0;for(let r of t)e+=E(r).length;let n=j(e),s=0;for(let r of t)n.set(r,s),s+=r.length;return n},dt=(t=w)=>(globalThis?.crypto).getRandomValues(j(t)),ft=BigInt,D=(t,e,n,s="bad number: out of range")=>typeof t!="bigint"?b(s,TypeError):e<=t&&t{let n=t%e;return n>=0n?n:e+n},J=t=>f(t,P),pe=(t,e)=>{(t===0n||e<=0n)&&b("no inverse n="+t+" mod="+e);let n=f(t,e),s=e,r=0n,o=1n,c=1n,i=0n;for(;n!==0n;){let a=s/n,h=s%n,d=r-c*a,u=o-i*a;s=n,n=h,r=c,o=i,c=d,i=u}return s===1n?f(r,e):b("no inverse")},kt=t=>{let e=et[t];return typeof e!="function"&&b("hashes."+t+" not set"),e},wt=(t,e,n)=>E(kt(t)(e,n),w,"digest"),At=(t,e,n)=>Promise.resolve(kt(t)(e,n)).then(s=>E(s,w,"digest"));var it=t=>t instanceof L?t:b("Point expected"),Ct=t=>f(f(t*t)*t+Ut),Et=t=>D(t,0n,v),$=t=>D(t,1n,v),ge=t=>D(t,1n,P),Q=t=>!(t&1n),vt=t=>Uint8Array.of(t),me=t=>vt(Q(t)?2:3),Ft=t=>{let e=Ct($(t)),n=1n;for(let s=e,r=(v+1n)/4n;r>0n;r>>=1n)r&1n&&(n=n*s%v),s=s*s%v;return f(n*n)!==e&&b("sqrt invalid"),Q(n)?n:f(-n)};var B=class B{constructor(e,n,s){l(this,"X");l(this,"Y");l(this,"Z");this.X=Et(e),this.Y=$(n),this.Z=Et(s),Object.freeze(this)}static CURVE(){return Lt}static fromAffine(e){let{x:n,y:s}=e;return n===0n&&s===0n?G:new B(n,s,1n)}static fromBytes(e){E(e);let{publicKey:n,publicKeyUncompressed:s}=z,r,o=e.length,c=e[0],i=e.subarray(1),a=W(i,0,w);if(o===n&&(c===2||c===3)){let h=Ft(a);c===3&&(h=f(-h)),r=new B(a,h,1n)}return o===s&&c===4&&(r=new B(a,W(i,w,K),1n)),r?r.assertValidity():b("bad point: not on curve")}static fromHex(e){return B.fromBytes(It(e))}get x(){return this.toAffine().x}get y(){return this.toAffine().y}equals(e){let{X:n,Y:s,Z:r}=this,{X:o,Y:c,Z:i}=it(e),a=f(n*i),h=f(o*r),d=f(s*i),u=f(c*r);return a===h&&d===u}is0(){return this.equals(G)}negate(){return new B(this.X,f(-this.Y),this.Z)}double(){return this.add(this)}add(e){let{X:n,Y:s,Z:r}=this,{X:o,Y:c,Z:i}=it(e),a=0n,h=Ut,d=0n,u=0n,x=0n,y=f(h*3n),p=f(n*o),g=f(s*c),A=f(r*i),R=f(n+s),m=f(o+c);R=f(R*m),m=f(p+g),R=f(R-m),m=f(n+r);let S=f(o+i);return m=f(m*S),S=f(p+A),m=f(m-S),S=f(s+r),d=f(c+i),S=f(S*d),d=f(g+A),S=f(S-d),x=f(a*m),d=f(y*A),x=f(d+x),d=f(g-x),x=f(g+x),u=f(d*x),g=f(p+p),g=f(g+p),A=f(a*A),m=f(y*m),g=f(g+A),A=f(p-A),A=f(a*A),m=f(m+A),p=f(g*m),u=f(u+p),p=f(S*m),d=f(R*d),d=f(d-p),p=f(R*g),x=f(S*x),x=f(x+p),new B(d,u,x)}subtract(e){return this.add(it(e).negate())}multiply(e,n=!0){if(!n&&e===0n)return G;if(ge(e),e===1n)return this;if(this.equals(F))return ke(e).p;let s=G,r=F;for(let o=this;e>0n;o=o.double(),e>>=1n)e&1n?s=s.add(o):n&&(r=r.add(o));return s}multiplyUnsafe(e){return this.multiply(e,!1)}toAffine(){let{X:e,Y:n,Z:s}=this;if(this.equals(G))return{x:0n,y:0n};if(s===1n)return{x:e,y:n};let r=pe(s,v);return f(s*r)!==1n&&b("inverse invalid"),{x:f(e*r),y:f(n*r)}}assertValidity(){let{x:e,y:n}=this.toAffine();return $(e),$(n),f(n*n)===Ct(e)?this:b("bad point: not on curve")}toBytes(e=!0){let{x:n,y:s}=this.assertValidity().toAffine(),r=U(n);return e?N(me(s),r):N(vt(4),r,U(s))}toHex(e){return Tt(this.toBytes(e))}};l(B,"BASE"),l(B,"ZERO");var L=B,F=new L(xe,be,1n),G=new L(0n,1n,0n);L.BASE=F;L.ZERO=G;var we=(t,e,n)=>F.multiply(e,!1).add(t.multiply(n,!1)).assertValidity(),O=t=>ft("0x"+(Tt(t)||"0")),W=(t,e,n)=>O(t.subarray(e,n)),Ae=2n**256n,U=t=>It(_t(D(t,0n,Ae),K)),tt=t=>{let e=O(E(t,w,"secret key"));return D(e,1n,P,"invalid secret key: outside of range")};var Vt=(t,e=!0)=>F.multiply(tt(t)).toBytes(e),Ee=t=>{try{return!!tt(t)}catch{return!1}},He=(t,e)=>{let{publicKey:n,publicKeyUncompressed:s}=z;try{let r=t.length;return e===!0&&r!==n||e===!1&&r!==s?!1:!!L.fromBytes(t)}catch{return!1}};var Ht="SHA-256",et={hmacSha256Async:async(t,e)=>{let n=mt(),s="HMAC",r=await n.importKey("raw",t,{name:s,hash:{name:Ht}},!1,["sign"]);return j(await n.sign(s,r,e))},hmacSha256:void 0,sha256Async:async t=>j(await mt().digest(Ht,t)),sha256:void 0};var Gt=(t,e,n=!0)=>L.fromBytes(e).multiply(tt(t)).toBytes(n),Dt=t=>{if(t=t===void 0?dt(z.seed):t,E(t),t.length1024)return b("expected 48-1024b",RangeError);let e=f(O(t),P-1n);return U(e+1n)},Se=t=>e=>{let n=Dt(e);return{secretKey:n,publicKey:t(n)}};var Ot=Object.freeze({isValidSecretKey:Ee,isValidPublicKey:He,randomSecretKey:Dt}),Rt=t=>Uint8Array.from("BIP0340/"+t,e=>e.charCodeAt(0)),Kt="aux",Nt="nonce",Mt="challenge",at=(t,...e)=>{let n=wt("sha256",Rt(t));return wt("sha256",N(n,n,...e))},ut=(t,...e)=>At("sha256Async",Rt(t)).then(n=>At("sha256Async",N(n,n,...e))),lt=t=>{let e=tt(t),n=F.multiply(e),{x:s,y:r}=n.assertValidity().toAffine(),o=Q(r)?e:J(-e),c=U(s);return{d:o,px:c}},xt=t=>J(O(t)),Xt=(...t)=>xt(at(Mt,...t)),jt=async(...t)=>xt(await ut(Mt,...t)),Pt=t=>lt(t).px,Be=Se(Pt),Yt=(t,e,n)=>{let{px:s,d:r}=lt(e);return{m:E(t),px:s,d:r,a:E(n,w)}},Zt=t=>{let e=xt(t);e===0n&&b("sign failed: k is zero");let{px:n,d:s}=lt(U(e));return{rx:n,k:s}},$t=(t,e,n,s)=>N(e,U(J(t+n*s))),zt="invalid signature produced",Le=(t,e,n=dt(w))=>{let{m:s,px:r,d:o,a:c}=Yt(t,e,n),i=at(Kt,c),a=U(o^O(i)),h=at(Nt,a,r,s),{rx:d,k:u}=Zt(h),x=Xt(d,r,s),y=$t(u,d,x,o);return qt(y,s,r)||b(zt),y},Ue=async(t,e,n=dt(w))=>{let{m:s,px:r,d:o,a:c}=Yt(t,e,n),i=await ut(Kt,c),a=U(o^O(i)),h=await ut(Nt,a,r,s),{rx:d,k:u}=Zt(h),x=await jt(d,r,s),y=$t(u,d,x,o);return await Jt(y,s,r)||b(zt),y},_e=(t,e)=>t instanceof Promise?t.then(e):e(t),Wt=(t,e,n,s)=>{let r=E(t,K,"signature"),o=E(e,void 0,"message"),c=E(n,w,"publicKey");try{let i=O(c),a=Ft(i),h=new L(i,a,1n).assertValidity(),d=U(h.toAffine().x),u=W(r,0,w);D(u,1n,v);let x=W(r,w,K);D(x,1n,P);let y=N(U(u),d,o);return _e(s(y),p=>{let{x:g,y:A}=we(h,x,J(-p)).toAffine();return!(!Q(A)||g!==u)})}catch{return!1}},qt=(t,e,n)=>Wt(t,e,n,Xt),Jt=async(t,e,n)=>Wt(t,e,n,jt),Qt=Object.freeze({keygen:Be,getPublicKey:Pt,sign:Le,verify:qt,signAsync:Ue,verifyAsync:Jt}),q=8,Te=256,te=Math.ceil(Te/q)+1,ht=2**(q-1),Ie=()=>{let t=[],e=F,n=e;for(let s=0;s{let n=e.negate();return t?n:e},ke=t=>{let e=St||(St=Ie()),n=G,s=F,r=2**q,o=r,c=ft(r-1),i=ft(q);for(let a=0;a>=i,h>ht&&(h-=o,t+=1n);let d=a*ht,u=d,x=d+Math.abs(h)-1,y=a%2!==0,p=h<0;h===0?s=s.add(Bt(y,e[u])):n=n.add(Bt(p,e[x]))}return t!==0n&&b("invalid wnaf"),{p:n,f:s}};function Ce(t){return t instanceof Uint8Array||ArrayBuffer.isView(t)&&t.constructor.name==="Uint8Array"&&"BYTES_PER_ELEMENT"in t&&t.BYTES_PER_ELEMENT===1}function Y(t,e=""){if(typeof t!="number"){let n=e&&`"${e}" `;throw new TypeError(`${n}expected number, got ${typeof t}`)}if(!Number.isSafeInteger(t)||t<0){let n=e&&`"${e}" `;throw new RangeError(`${n}expected integer >= 0, got ${t}`)}}function I(t,e,n=""){let s=Ce(t),r=t?.length,o=e!==void 0;if(!s||o&&r!==e){let c=n&&`"${n}" `,i=o?` of length ${e}`:"",a=s?`length=${r}`:`type=${typeof t}`,h=c+"expected Uint8Array"+i+", got "+a;throw s?new RangeError(h):new TypeError(h)}return t}function Z(t){if(typeof t!="function"||typeof t.create!="function")throw new TypeError("Hash must wrapped by utils.createHasher");if(Y(t.outputLen),Y(t.blockLen),t.outputLen<1)throw new Error('"outputLen" must be >= 1');if(t.blockLen<1)throw new Error('"blockLen" must be >= 1')}function M(t,e=!0){if(t.destroyed)throw new Error("Hash instance has been destroyed");if(e&&t.finished)throw new Error("Hash#digest() has already been called")}function nt(t,e){I(t,void 0,"digestInto() output");let n=e.outputLen;if(t.length='+n)}function k(...t){for(let e=0;e>>e}var ne=typeof Uint8Array.from([]).toHex=="function"&&typeof Uint8Array.fromHex=="function",ve=Array.from({length:256},(t,e)=>e.toString(16).padStart(2,"0"));function se(t){if(I(t),ne)return t.toHex();let e="";for(let n=0;n=T._0&&t<=T._9)return t-T._0;if(t>=T.A&&t<=T.F)return t-(T.A-10);if(t>=T.a&&t<=T.f)return t-(T.a-10)}function re(t){if(typeof t!="string")throw new TypeError("hex string expected, got "+typeof t);if(ne)try{return Uint8Array.fromHex(t)}catch(r){throw r instanceof SyntaxError?new RangeError(r.message):r}let e=t.length,n=e/2;if(e%2)throw new RangeError("hex string expected, got unpadded hex of length "+e);let s=new Uint8Array(n);for(let r=0,o=0;rt(o).update(r).digest(),s=t(void 0);return n.outputLen=s.outputLen,n.blockLen=s.blockLen,n.canXOF=s.canXOF,n.create=r=>t(r),Object.assign(n,e),Object.freeze(n)}function ce(t=32){Y(t,"bytesLength");let e=typeof globalThis=="object"?globalThis.crypto:null;if(typeof e?.getRandomValues!="function")throw new Error("crypto.getRandomValues must be defined");if(t>65536)throw new RangeError(`"bytesLength" expected <= 65536, got ${t}`);return e.getRandomValues(new Uint8Array(t))}var ie=t=>({oid:Uint8Array.from([6,9,96,134,72,1,101,3,4,2,t])});function fe(t,e,n){return t&e^~t&n}function ae(t,e,n){return t&e^t&n^e&n}var rt=class{constructor(e,n,s,r){l(this,"blockLen");l(this,"outputLen");l(this,"canXOF",!1);l(this,"padOffset");l(this,"isLE");l(this,"buffer");l(this,"view");l(this,"finished",!1);l(this,"length",0);l(this,"pos",0);l(this,"destroyed",!1);this.blockLen=e,this.outputLen=n,this.padOffset=s,this.isLE=r,this.buffer=new Uint8Array(e),this.view=st(this.buffer)}update(e){M(this),I(e);let{view:n,buffer:s,blockLen:r}=this,o=e.length;for(let c=0;cr-c&&(this.process(s,0),c=0);for(let u=c;ud.length)throw new Error("_sha2: outputLen bigger than state");for(let u=0;u>>3,g=H(y,17)^H(y,19)^y>>>10;V[u]=g+V[u-7]+p+V[u-16]|0}let{A:s,B:r,C:o,D:c,E:i,F:a,G:h,H:d}=this;for(let u=0;u<64;u++){let x=H(i,6)^H(i,11)^H(i,25),y=d+x+fe(i,a,h)+Fe[u]+V[u]|0,g=(H(s,2)^H(s,13)^H(s,22))+ae(s,r,o)|0;d=h,h=a,a=i,i=c+y|0,c=o,o=r,r=s,s=y+g|0}s=s+this.A|0,r=r+this.B|0,o=o+this.C|0,c=c+this.D|0,i=i+this.E|0,a=a+this.F|0,h=h+this.G|0,d=d+this.H|0,this.set(s,r,o,c,i,a,h,d)}roundClean(){k(V)}destroy(){this.destroyed=!0,this.set(0,0,0,0,0,0,0,0),k(this.buffer)}},yt=class extends bt{constructor(){super(32);l(this,"A",C[0]|0);l(this,"B",C[1]|0);l(this,"C",C[2]|0);l(this,"D",C[3]|0);l(this,"E",C[4]|0);l(this,"F",C[5]|0);l(this,"G",C[6]|0);l(this,"H",C[7]|0)}};var ot=oe(()=>new yt,ie(1));var ct=class{constructor(e,n){l(this,"oHash");l(this,"iHash");l(this,"blockLen");l(this,"outputLen");l(this,"canXOF",!1);l(this,"finished",!1);l(this,"destroyed",!1);if(Z(e),I(n,void 0,"key"),this.iHash=e.create(),typeof this.iHash.update!="function")throw new Error("Expected instance of class which extends utils.Hash");this.blockLen=this.iHash.blockLen,this.outputLen=this.iHash.outputLen;let s=this.blockLen,r=new Uint8Array(s);r.set(n.length>s?e.create().update(n).digest():n);for(let o=0;o{let t=((e,n,s)=>new ct(e,n).update(s).digest());return t.create=(e,n)=>new ct(e,n),t})();function Ve(t,e,n){return Z(t),n===void 0&&(n=new Uint8Array(t.outputLen)),X(t,n,e)}var pt=Uint8Array.of(0),ue=Uint8Array.of();function Ge(t,e,n,s=32){Z(t),Y(s,"length"),I(e,void 0,"prk");let r=t.outputLen;if(e.length255*r)throw new Error("Length must be <= 255*HashLen");let o=Math.ceil(s/r);n===void 0?n=ue:I(n,void 0,"info");let c=new Uint8Array(o*r),i=X.create(t,e),a=i._cloneInto(),h=new Uint8Array(i.outputLen);for(let d=0;dGe(t,Ve(t,e,n),s,r);et.sha256=ot;et.hmacSha256=(t,...e)=>X(ot,t,e.length===1?e[0]:(()=>{let n=e.reduce((o,c)=>o+c.length,0),s=new Uint8Array(n),r=0;for(let o of e)s.set(o,r),r+=o.length;return s})());window.ArtstrNoble={schnorr:Qt,getPublicKey:Vt,getSharedSecret:Gt,sha256:ot,hkdf:he,hmac:X,hexToBytes:re,bytesToHex:se,randomBytes:ce,secpUtils:Ot};})(); /*! Bundled license information: @noble/secp256k1/index.js: