mirror of
https://github.com/PR0M3TH3AN/Artstr-Studio.git
synced 2026-10-27 08:40:39 +00:00
Premium step 1 — soft-gate crypto primitive
First piece of PREMIUM_DESIGNS_FEATURE.md §6. Adds the static
client-side decryption layer for premium designs: HKDF-SHA256 over
an obfuscated per-epoch pepper + a per-design public salt, then
AES-256-GCM with the event coordinate as additional-authenticated-
data so ciphertext can't be copy-pasted to a different event.
noble bundle
- Add @noble/hashes/hkdf to the bundle entry; expose as
window.ArtstrNoble.hkdf and .hmac. Bundle size 14.0 KB → 16.5 KB.
Premium IIFE (new section in index.html)
- _softGatePepperParts — per-epoch lookup of 4x8-byte fragments
("palette seed I..IV"). For epoch 2026-05. Sub-strings don't
look like a "premium key"; reconstruction concats at use time.
Comment explicitly calls this obfuscation, not security, per
PREMIUM_DESIGNS_FEATURE.md §2 / §6.3.
- SUPPORTED_EPOCHS / CURRENT_EPOCH — adding a future epoch is
one entry in the parts table.
- pepperBytesForEpoch(epoch) — reconstructs the 32-byte pepper.
- deriveKey({ epoch, creatorPubkey, premiumAddress, schemaVersion,
publicDesignSalt, puzzleNonce }) -> 32 bytes via HKDF-SHA256
with the pepper as IKM, salt = publicDesignSalt, info =
"artstr-softgate-v1|<epoch>|<creator>|<addr>|v<schema>" (and an
optional "|p<nonce>" for the §6.7 CPU-puzzle hook).
- encodeAad(creatorPubkey, dTag) -> UTF-8 of
"30078:<creator>:<dTag>" so AES-GCM authenticates the
coordinate.
- encryptPayload(payloadObj, coord, { epoch? }) — random
32-byte salt + 12-byte IV; returns the spec §5.2 envelope
(base64 fields, softgate metadata, etc.).
- decryptPayload(envelope, coord) — reverses the above.
- Self-test runs on every load: round-trip a known payload AND
verify AAD/creator/schema mismatches all reject the decrypt
(event-coordinate binding). Single console.warn on failure.
Tested via CDP — all green:
- Round-trip with random keypair: ok
- AAD mismatch (different dTag) -> AES-GCM rejects: ok
- Creator pubkey mismatch -> KDF info changes -> rejects: ok
- Schema version mismatch -> KDF info changes -> rejects: ok
- KDF deterministic with identical inputs: ok
- Output length = 32 bytes (AES-256): ok
- Pepper reconstruction = 32 bytes: ok
- Envelope size for tiny payload = 577 bytes; ~63 KB headroom
under typical relay limits, plenty for an embedded preview
JPEG in step 2.
- Regression: NWC crypto self-test still passes; existing editor
still loads and renders layers.
Code only; nothing in the publish/feed flow uses this yet. Next
step (PREMIUM_DESIGNS_FEATURE.md §19 item 2) is the watermarked
preview pipeline.
Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
1 parent
7da0c9d97c
commit
a8c855fc5c
2 files changed
+175
-1
No files matched your search
Vendored
+1
-1
@@ -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;o<s;o++,c+=2){let f=bt(t.charCodeAt(c)),a=bt(t.charCodeAt(c+1));if(f===void 0||a===void 0)return b(e);r[o]=f*16+a}return r},yt=()=>globalThis?.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<n?t:b(s,RangeError),i=(t,e=v)=>{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: outsidLine truncated
|
||||
(()=>{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;o<s;o++,c+=2){let i=gt(t.charCodeAt(c)),a=gt(t.charCodeAt(c+1));if(i===void 0||a===void 0)return b(e);r[o]=i*16+a}return r},mt=()=>globalThis?.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<n?t:b(s,RangeError),f=(t,e=v)=>{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: outsLine truncated
|
||||
/*! Bundled license information:
|
||||
|
||||
@noble/secp256k1/index.js:
|
||||
|
||||
Reference in new issue
Block a user