@gjsify/webcrypto 0.52.0 → 0.54.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ import"./_virtual/_rolldown/runtime.js";import{CryptoKey as e}from"./crypto-key.js";import{base64urlDecode as t,toUint8Array as n}from"./util.js";import{DOMException as r}from"@gjsify/dom-exception";const i={Ed25519:{public:[`verify`],private:[`sign`]},X25519:{public:[],private:[`deriveKey`,`deriveBits`]}},a={Ed25519:[48,42,48,5,6,3,43,101,112,3,33,0],X25519:[48,42,48,5,6,3,43,101,110,3,33,0]};function cfrgName(e){let t=e.toUpperCase();if(t===`ED25519`)return`Ed25519`;if(t===`X25519`)return`X25519`}function assertUsages(e,t){for(let n of e)if(!t.includes(n))throw new r(`Unsupported key usage: ${n}`,`SyntaxError`)}function toArrayBuffer(e){return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}function keyObjectOf(e){return e._handle.keyObject}function cfrgGenerateKey(t,n,a,o){assertUsages(o,[...i[n].public,...i[n].private]);let s=o.filter(e=>i[n].private.includes(e));if(s.length===0)throw new r(`Usages cannot be empty when creating a key.`,`SyntaxError`);let c=o.filter(e=>i[n].public.includes(e)),{publicKey:l,privateKey:u}=t.generateKeyPairSync(n.toLowerCase());return{publicKey:new e(`public`,!0,{name:n},c,{keyObject:l}),privateKey:new e(`private`,a,{name:n},s,{keyObject:u})}}function validateJwk(e,t,n,i){if(typeof e!=`object`||!e)throw new r(`Invalid keyData`,`DataError`);if(e.kty!==`OKP`)throw new r(`Invalid JWK "kty" Parameter`,`DataError`);if(e.crv!==t)throw new r(`JWK "crv" Parameter and algorithm name mismatch`,`DataError`);if(t===`Ed25519`&&e.alg!==void 0&&e.alg!==`Ed25519`&&e.alg!==`EdDSA`)throw new r(`JWK "alg" does not match the requested algorithm`,`DataError`);let a=t===`X25519`?`enc`:`sig`;if(i.length>0&&e.use!==void 0&&e.use!==a)throw new r(`Invalid JWK "use" Parameter`,`DataError`);if(e.key_ops!==void 0){if(!Array.isArray(e.key_ops))throw new r(`Invalid JWK "key_ops" Parameter`,`DataError`);for(let t of i)if(!e.key_ops.includes(t))throw new r(`Key operations and usage mismatch`,`DataError`)}if(e.ext===!1&&n)throw new r(`JWK "ext" Parameter and extractable mismatch`,`DataError`);if(typeof e.x!=`string`||e.d!==void 0&&typeof e.d!=`string`)throw new r(`Invalid keyData`,`DataError`)}function cfrgImportKey(o,s,c,l,u,d){let f,p,importOrDataError=e=>{try{return e()}catch(e){throw new r(`Invalid keyData: ${e.message}`,`DataError`)}};switch(s){case`raw`:{assertUsages(d,i[l].public);let e=n(c);if(e.length!==32)throw new r(`Invalid keyData`,`DataError`);let t=new Uint8Array(44);t.set(a[l],0),t.set(e,12),f=importOrDataError(()=>o.createPublicKey({key:t,format:`der`,type:`spki`})),p=`public`;break}case`spki`:{assertUsages(d,i[l].public);let e=n(c);f=importOrDataError(()=>o.createPublicKey({key:e,format:`der`,type:`spki`})),p=`public`;break}case`pkcs8`:{assertUsages(d,i[l].private);let e=n(c);f=importOrDataError(()=>o.createPrivateKey({key:e,format:`der`,type:`pkcs8`})),p=`private`;break}case`jwk`:{let e=c;if(validateJwk(e,l,u,d),p=e.d===void 0?`public`:`private`,assertUsages(d,i[l][p]),p===`private`){if(f=importOrDataError(()=>o.createPrivateKey({key:e,format:`jwk`})),o.createPublicKey(f).export({format:`jwk`}).x!==e.x)throw new r(`Invalid JWK: "x" does not match "d"`,`DataError`)}else{if(t(e.x).length!==32)throw new r(`Invalid keyData`,`DataError`);f=importOrDataError(()=>o.createPublicKey({key:e,format:`jwk`}))}break}default:throw new r(`Unsupported format: ${s}`,`NotSupportedError`)}if(f.asymmetricKeyType!==l.toLowerCase())throw new r(`Invalid key type`,`DataError`);if(p===`private`&&d.length===0)throw new r(`Usages cannot be empty when importing a private key.`,`SyntaxError`);return new e(p,u,{name:l},d,{keyObject:f})}function wrongKindForFormat(e,t){return new r(`Unable to export ${e.algorithm.name} ${e.type} key using ${t} format`,`InvalidAccessError`)}function cfrgExportKey(e,n){let i=keyObjectOf(n);switch(e){case`raw`:{if(n.type!==`public`)throw new r(`Unable to export ${n.algorithm.name} ${n.type} key using ${e} format`,`NotSupportedError`);let a=i.export({format:`jwk`}).x;return toArrayBuffer(t(a))}case`spki`:if(n.type!==`public`)throw wrongKindForFormat(n,e);return toArrayBuffer(i.export({format:`der`,type:`spki`}));case`pkcs8`:if(n.type!==`private`)throw wrongKindForFormat(n,e);return toArrayBuffer(i.export({format:`der`,type:`pkcs8`}));case`jwk`:{let e=i.export({format:`jwk`}),t={kty:`OKP`,crv:n.algorithm.name,x:e.x};return n.type===`private`&&(t.d=e.d),n.algorithm.name===`Ed25519`&&(t.alg=`Ed25519`),t.key_ops=[...n.usages],t.ext=n.extractable,t}default:throw new r(`Unsupported export format: ${e}`,`NotSupportedError`)}}function ed25519Sign(e,t,n){if(t.type!==`private`)throw new r(`Key must be a private key`,`InvalidAccessError`);return toArrayBuffer(e.sign(null,n,keyObjectOf(t)))}function ed25519Verify(e,t,n,i){if(t.type!==`public`)throw new r(`Key must be a public key`,`InvalidAccessError`);return e.verify(null,i,keyObjectOf(t),n)}function x25519DeriveBits(t,n,i,a){if(n.type!==`private`)throw new r(`baseKey must be a private key`,`InvalidAccessError`);if(!(i instanceof e)||i.type!==`public`)throw new r(`algorithm.public must be a public key`,`InvalidAccessError`);if(i.algorithm.name!==n.algorithm.name)throw new r(`The public and private keys must be of the same type`,`InvalidAccessError`);let o;try{o=new Uint8Array(t.diffieHellman({privateKey:keyObjectOf(n),publicKey:keyObjectOf(i)}))}catch(e){throw new r(`Deriving bits failed: ${e.message}`,`OperationError`)}if(a==null)return toArrayBuffer(o);if(a>o.length*8)throw new r(`derived bit length is too small`,`OperationError`);let s=o.slice(0,Math.ceil(a/8));return a%8!=0&&(s[s.length-1]&=255<<8-a%8),toArrayBuffer(s)}export{cfrgExportKey,cfrgGenerateKey,cfrgImportKey,cfrgName,ed25519Sign,ed25519Verify,x25519DeriveBits};
package/lib/esm/subtle.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{aesKeyUnwrap as e,aesKeyWrap as t}from"./aes-kw.js";import{CryptoKey as n}from"./crypto-key.js";import{base64urlDecode as r,base64urlEncode as i,checkUsage as a,hashSize as o,normalizeAlgorithm as s,toNodeCurveName as c,toNodeHashName as l,toUint8Array as u,validateUsages as d}from"./util.js";let f=!1,p,m,h,g,_,v,y,b,x,S,C,w,T,E,D,O;async function loadCrypto(){if(f)return;let e=await import(`node:crypto`);p=e.createHash,m=e.createHmac,h=e.createCipheriv,g=e.createDecipheriv,_=e.createSign,v=e.createVerify,y=e.pbkdf2Sync,b=e.hkdfSync,x=e.createECDH,S=e.randomBytes,e.publicEncrypt,e.privateDecrypt,e.createPublicKey,e.createPrivateKey,C=e.ecdsaSign,w=e.ecdsaVerify,T=e.rsaPssSign,E=e.rsaPssVerify,D=e.rsaOaepEncrypt,O=e.rsaOaepDecrypt,f=!0}const k=loadCrypto();var SubtleCrypto=class{async digest(e,t){await k;let n=l(s(e).name),r=u(t),i=p(n);i.update(r);let a=i.digest();return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}async generateKey(e,t,r){await k;let i=s(e);switch(i.name.toUpperCase()){case`AES-CBC`:case`AES-CTR`:case`AES-GCM`:{let a=e.length;if(![128,192,256].includes(a))throw new DOMException(`Invalid AES key length: ${a}`,`OperationError`);d(r,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]);let o=S(a/8);return new n(`secret`,t,{name:i.name,length:a},r,new Uint8Array(o))}case`AES-KW`:{let i=e.length;if(![128,192,256].includes(i))throw new DOMException(`Invalid AES key length: ${i}`,`OperationError`);d(r,[`wrapKey`,`unwrapKey`]);let a=S(i/8);return new n(`secret`,t,{name:`AES-KW`,length:i},r,new Uint8Array(a))}case`HMAC`:{let i=e,a=s(i.hash),c=i.length||o(a.name)*8;d(r,[`sign`,`verify`]);let l=S(Math.ceil(c/8));return new n(`secret`,t,{name:`HMAC`,hash:{name:a.name},length:c},r,new Uint8Array(l))}case`ECDH`:{let i=e.namedCurve,a=c(i);d(r,[`deriveKey`,`deriveBits`]);let o=x(a);o.generateKeys();let s=new Uint8Array(o.getPublicKey()),l=new Uint8Array(o.getPrivateKey());return{publicKey:new n(`public`,!0,{name:`ECDH`,namedCurve:i},[],s),privateKey:new n(`private`,t,{name:`ECDH`,namedCurve:i},r,{pub:s,priv:l})}}case`ECDSA`:{let i=e.namedCurve,a=c(i);d(r,[`sign`,`verify`]);let o=x(a);o.generateKeys();let s=new Uint8Array(o.getPublicKey()),l=new Uint8Array(o.getPrivateKey());return{publicKey:new n(`public`,!0,{name:`ECDSA`,namedCurve:i},[`verify`],s),privateKey:new n(`private`,t,{name:`ECDSA`,namedCurve:i},[`sign`],{pub:s,priv:l})}}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async importKey(e,t,i,a,o){await k;let c=s(i),l=c.name.toUpperCase();switch(l){case`AES-CBC`:case`AES-CTR`:case`AES-GCM`:if(e===`raw`){let e=u(t);if(![16,24,32].includes(e.length))throw new DOMException(`Invalid AES key length: ${e.length*8}`,`DataError`);return d(o,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:c.name,length:e.length*8},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);let i=r(e.k);if(![16,24,32].includes(i.length))throw new DOMException(`Invalid AES key length: ${i.length*8}`,`DataError`);return d(o,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:c.name,length:i.length*8},o,i)}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`AES-KW`:{let i;if(e===`raw`)i=u(t);else if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);i=r(e.k)}else throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);if(![16,24,32].includes(i.length))throw new DOMException(`Invalid AES key length: ${i.length*8}`,`DataError`);return d(o,[`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:`AES-KW`,length:i.length*8},o,new Uint8Array(i))}case`HMAC`:{let c=s(i.hash);if(e===`raw`){let e=u(t);return d(o,[`sign`,`verify`]),new n(`secret`,a,{name:`HMAC`,hash:{name:c.name},length:e.length*8},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);let i=r(e.k);return d(o,[`sign`,`verify`]),new n(`secret`,a,{name:`HMAC`,hash:{name:c.name},length:i.length*8},o,i)}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`)}case`PBKDF2`:if(e===`raw`){let e=u(t);return d(o,[`deriveKey`,`deriveBits`]),new n(`secret`,!1,{name:`PBKDF2`},o,new Uint8Array(e))}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`HKDF`:if(e===`raw`){let e=u(t);return d(o,[`deriveKey`,`deriveBits`]),new n(`secret`,!1,{name:`HKDF`},o,new Uint8Array(e))}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`ECDH`:case`ECDSA`:{let s=i.namedCurve;if(e===`raw`){let e=u(t);return l===`ECDH`?o.length>0&&d(o,[`deriveKey`,`deriveBits`]):d(o,[`verify`]),new n(`public`,a,{name:c.name,namedCurve:s},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`EC`)throw new DOMException(`JWK kty must be "EC"`,`DataError`);if(e.d){let t=r(e.d),i=r(e.x),u=r(e.y),f=new Uint8Array(1+i.length+u.length);return f[0]=4,f.set(i,1),f.set(u,1+i.length),d(o,l===`ECDH`?[`deriveKey`,`deriveBits`]:[`sign`]),new n(`private`,a,{name:c.name,namedCurve:s},o,{pub:f,priv:t})}else{let t=r(e.x),i=r(e.y),u=new Uint8Array(1+t.length+i.length);return u[0]=4,u.set(t,1),u.set(i,1+t.length),l===`ECDH`?o.length>0&&d(o,[`deriveKey`,`deriveBits`]):d(o,[`verify`]),new n(`public`,a,{name:c.name,namedCurve:s},o,u)}}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`)}default:throw new DOMException(`Unsupported algorithm: ${c.name}`,`NotSupportedError`)}}async exportKey(e,t){if(!t.extractable)throw new DOMException(`Key is not extractable`,`InvalidAccessError`);let n=t.algorithm.name.toUpperCase();if(e===`raw`){if(t.type===`secret`){let e=t._handle;return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}if(t.type===`public`&&(n===`ECDH`||n===`ECDSA`)){let e=t._handle;return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}throw new DOMException(`Cannot export in raw format`,`InvalidAccessError`)}if(e===`jwk`){if(t.type===`secret`){let e=t._handle,r={kty:`oct`,k:i(e),ext:t.extractable,key_ops:[...t.usages]};return n.startsWith(`AES-`)?r.alg=`A${t.algorithm.length}${n.replace(`AES-`,``)}`:n===`HMAC`&&(r.alg=`HS${t.algorithm.hash.name.replace(`SHA-`,``)}`),r}if((n===`ECDH`||n===`ECDSA`)&&(t.type===`public`||t.type===`private`)){let e=t.algorithm.namedCurve,n;n=t.type===`public`?t._handle:t._handle.pub;let r=(n.length-1)/2,a=n.slice(1,1+r),o=n.slice(1+r),s={kty:`EC`,crv:e,x:i(a),y:i(o),ext:t.extractable,key_ops:[...t.usages]};return t.type===`private`&&(s.d=i(t._handle.priv)),s}throw new DOMException(`JWK export not supported for ${n} ${t.type}`,`NotSupportedError`)}throw new DOMException(`Unsupported export format: ${e}`,`NotSupportedError`)}async encrypt(e,t,n){return await k,a(t,`encrypt`),this._encryptImpl(e,t,n)}async _encryptImpl(e,n,r){let i=s(e),a=i.name.toUpperCase(),o=u(r);switch(a){case`AES-CBC`:{let t=u(e.iv),r=n._handle,i=r.length*8,a=h(`aes-${i}-cbc`,r,t),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-CTR`:{let t=u(e.counter),r=n._handle,i=r.length*8,a=h(`aes-${i}-ctr`,r,t),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-GCM`:{let t=e,r=u(t.iv),i=t.additionalData?u(t.additionalData):void 0,a=n._handle,s=a.length*8,c=h(`aes-${s}-gcm`,a,r);i&&c.setAAD(i);let l=c.update(o),d=c.final(),f=c.getAuthTag(),p=new Uint8Array(l.length+d.length+f.length);return p.set(new Uint8Array(l),0),p.set(new Uint8Array(d),l.length),p.set(new Uint8Array(f),l.length+d.length),p.buffer}case`RSA-OAEP`:{let t=n.algorithm.hash.name,r=l(t),i=n._handle,a=e,s=a.label?u(a.label):void 0,c=D(r,i.pem,o,s);return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}case`AES-KW`:{let e=n._handle;return t(o,t=>this._aesEcbBlock(e,t,!0)).buffer}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async decrypt(e,t,n){return await k,a(t,`decrypt`),this._decryptImpl(e,t,n)}async _decryptImpl(t,n,r){let i=s(t),a=i.name.toUpperCase(),o=u(r);switch(a){case`AES-CBC`:{let e=u(t.iv),r=n._handle,i=r.length*8,a=g(`aes-${i}-cbc`,r,e),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-CTR`:{let e=u(t.counter),r=n._handle,i=r.length*8,a=g(`aes-${i}-ctr`,r,e),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-GCM`:{let e=t,r=u(e.iv),i=(e.tagLength||128)/8,a=e.additionalData?u(e.additionalData):void 0,s=n._handle,c=s.length*8,l=o.slice(0,o.length-i),d=o.slice(o.length-i),f=g(`aes-${c}-gcm`,s,r);f.setAuthTag(d),a&&f.setAAD(a);let p=f.update(l),m=f.final(),h=new Uint8Array(p.length+m.length);return h.set(new Uint8Array(p),0),h.set(new Uint8Array(m),p.length),h.buffer}case`RSA-OAEP`:{let e=n.algorithm.hash.name,r=l(e),i=n._handle,a=t,s=a.label?u(a.label):void 0,c=O(r,i.pem,o,s);return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}case`AES-KW`:{let t=n._handle;return e(o,e=>this._aesEcbBlock(t,e,!1)).buffer}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}_aesEcbBlock(e,t,n){let r=`aes-${e.length*8}-ecb`,i=new Uint8Array,a=n?h(r,e,i):g(r,e,i);a.setAutoPadding?.(!1);let o=a.update(t),s=a.final();if(s.length===0)return o;let c=new Uint8Array(o.length+s.length);return c.set(o,0),c.set(s,o.length),c}async sign(e,t,n){await k,a(t,`sign`);let r=s(e),i=r.name.toUpperCase(),c=u(n);switch(i){case`HMAC`:{let e=t.algorithm.hash.name,n=l(e),r=t._handle,i=m(n,r);i.update(c);let a=i.digest();return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}case`RSASSA-PKCS1-V1_5`:{let e=t.algorithm.hash.name,n=l(e),r=t._handle,i=_(n);i.update(c);let a=i.sign(r.pem);return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}case`ECDSA`:{let n=e,r=l(typeof n.hash==`string`?n.hash:n.hash.name),i=t.algorithm.namedCurve,a=t._handle,o=C(r,a.priv,c,i);return o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength)}case`RSA-PSS`:{let n=t.algorithm.hash.name,r=l(n),i=t._handle,a=e.saltLength??o(n),s=T(r,i.pem,c,a);return s.buffer.slice(s.byteOffset,s.byteOffset+s.byteLength)}default:throw new DOMException(`Unsupported algorithm: ${r.name}`,`NotSupportedError`)}}async verify(e,t,n,r){await k,a(t,`verify`);let i=s(e),c=i.name.toUpperCase(),d=u(r),f=u(n);switch(c){case`HMAC`:{let e=t.algorithm.hash.name,n=l(e),r=t._handle,i=m(n,r);i.update(d);let a=new Uint8Array(i.digest());if(a.length!==f.length)return!1;let o=0;for(let e=0;e<a.length;e++)o|=a[e]^f[e];return o===0}case`RSASSA-PKCS1-V1_5`:{let e=t.algorithm.hash.name,n=l(e),r=t._handle,i=v(n);return i.update(d),i.verify(r.pem,f)}case`ECDSA`:{let n=e,r=l(typeof n.hash==`string`?n.hash:n.hash.name),i=t.algorithm.namedCurve,a=t._handle;return w(r,a,f,d,i)}case`RSA-PSS`:{let n=t.algorithm.hash.name,r=l(n),i=t._handle,a=e.saltLength??o(n);return E(r,i.pem,f,d,a)}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async _deriveBitsInternal(e,t,n){await k;let r=s(e);switch(r.name.toUpperCase()){case`PBKDF2`:{let r=e,i=l(s(r.hash).name),a=u(r.salt),o=r.iterations,c=t._handle,d=y(c,a,o,n/8,i);return d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)}case`HKDF`:{let r=e,i=l(s(r.hash).name),a=u(r.salt),o=u(r.info),c=t._handle;return b(i,c,a,o,n/8)}case`ECDH`:{let r=e.public,i=t.algorithm.namedCurve,a=c(i),o=x(a),s=t._handle;o.setPrivateKey(s.priv);let l=r._handle instanceof Uint8Array?r._handle:r._handle.pub,u=o.computeSecret(l),d=new Uint8Array(u);return n?d.buffer.slice(0,n/8):d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)}default:throw new DOMException(`Unsupported algorithm: ${r.name}`,`NotSupportedError`)}}async deriveBits(e,t,n){return a(t,`deriveBits`),this._deriveBitsInternal(e,t,n)}async deriveKey(e,t,n,r,i){a(t,`deriveKey`);let c=s(n),l,u=c.name.toUpperCase();if(u===`AES-CBC`||u===`AES-CTR`||u===`AES-GCM`)l=n.length;else if(u===`HMAC`){let e=n,t=s(e.hash);l=e.length||o(t.name)*8}else throw new DOMException(`Unsupported derived key algorithm: ${c.name}`,`NotSupportedError`);let d=await this._deriveBitsInternal(e,t,l);return this.importKey(`raw`,d,n,r,i)}async wrapKey(e,t,n,r){await k,a(n,`wrapKey`);let i=await this.exportKey(e,t),o=e===`jwk`?new TextEncoder().encode(JSON.stringify(i)):i;return this._encryptImpl(r,n,o)}async unwrapKey(e,t,n,r,i,o,s){await k,a(n,`unwrapKey`);let c=await this._decryptImpl(r,n,t),l=e===`jwk`?JSON.parse(new TextDecoder().decode(new Uint8Array(c))):c;return this.importKey(e,l,i,o,s)}};export{SubtleCrypto};
1
+ import"./_virtual/_rolldown/runtime.js";import{aesKeyUnwrap as e,aesKeyWrap as t}from"./aes-kw.js";import{CryptoKey as n}from"./crypto-key.js";import{base64urlDecode as r,base64urlEncode as i,checkAlgorithmMatch as a,checkUsage as o,hashSize as s,normalizeAlgorithm as c,toNodeCurveName as l,toNodeHashName as u,toUint8Array as d,validateUsages as f}from"./util.js";import{cfrgExportKey as p,cfrgGenerateKey as m,cfrgImportKey as h,cfrgName as g,ed25519Sign as _,ed25519Verify as v,x25519DeriveBits as y}from"./cfrg.js";let b=!1,x,S,C,w,T,E,D,O,k,A,j,M,N,P,F,I,L;async function loadCrypto(){if(b)return;let e=await import(`node:crypto`);x=e.createHash,S=e.createHmac,C=e.createCipheriv,w=e.createDecipheriv,T=e.createSign,E=e.createVerify,D=e.pbkdf2Sync,O=e.hkdfSync,k=e.createECDH,A=e.randomBytes,e.publicEncrypt,e.privateDecrypt,e.createPublicKey,e.createPrivateKey,j=e.ecdsaSign,M=e.ecdsaVerify,N=e.rsaPssSign,P=e.rsaPssVerify,F=e.rsaOaepEncrypt,I=e.rsaOaepDecrypt,L={generateKeyPairSync:e.generateKeyPairSync,sign:e.sign,verify:e.verify,diffieHellman:e.diffieHellman,createPrivateKey:e.createPrivateKey,createPublicKey:e.createPublicKey},b=!0}const R=loadCrypto();var SubtleCrypto=class{async digest(e,t){await R;let n=u(c(e).name),r=d(t),i=x(n);i.update(r);let a=i.digest();return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}async generateKey(e,t,r){await R;let i=c(e),a=i.name.toUpperCase(),o=g(i.name);if(o)return m(L,o,t,r);switch(a){case`AES-CBC`:case`AES-CTR`:case`AES-GCM`:{let a=e.length;if(![128,192,256].includes(a))throw new DOMException(`Invalid AES key length: ${a}`,`OperationError`);f(r,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]);let o=A(a/8);return new n(`secret`,t,{name:i.name,length:a},r,new Uint8Array(o))}case`AES-KW`:{let i=e.length;if(![128,192,256].includes(i))throw new DOMException(`Invalid AES key length: ${i}`,`OperationError`);f(r,[`wrapKey`,`unwrapKey`]);let a=A(i/8);return new n(`secret`,t,{name:`AES-KW`,length:i},r,new Uint8Array(a))}case`HMAC`:{let i=e,a=c(i.hash),o=i.length||s(a.name)*8;f(r,[`sign`,`verify`]);let l=A(Math.ceil(o/8));return new n(`secret`,t,{name:`HMAC`,hash:{name:a.name},length:o},r,new Uint8Array(l))}case`ECDH`:{let i=e.namedCurve,a=l(i);f(r,[`deriveKey`,`deriveBits`]);let o=k(a);o.generateKeys();let s=new Uint8Array(o.getPublicKey()),c=new Uint8Array(o.getPrivateKey());return{publicKey:new n(`public`,!0,{name:`ECDH`,namedCurve:i},[],s),privateKey:new n(`private`,t,{name:`ECDH`,namedCurve:i},r,{pub:s,priv:c})}}case`ECDSA`:{let i=e.namedCurve,a=l(i);f(r,[`sign`,`verify`]);let o=k(a);o.generateKeys();let s=new Uint8Array(o.getPublicKey()),c=new Uint8Array(o.getPrivateKey());return{publicKey:new n(`public`,!0,{name:`ECDSA`,namedCurve:i},[`verify`],s),privateKey:new n(`private`,t,{name:`ECDSA`,namedCurve:i},[`sign`],{pub:s,priv:c})}}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async importKey(e,t,i,a,o){await R;let s=c(i),l=s.name.toUpperCase(),u=g(s.name);if(u)return h(L,e,t,u,a,o);switch(l){case`AES-CBC`:case`AES-CTR`:case`AES-GCM`:if(e===`raw`){let e=d(t);if(![16,24,32].includes(e.length))throw new DOMException(`Invalid AES key length: ${e.length*8}`,`DataError`);return f(o,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:s.name,length:e.length*8},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);let i=r(e.k);if(![16,24,32].includes(i.length))throw new DOMException(`Invalid AES key length: ${i.length*8}`,`DataError`);return f(o,[`encrypt`,`decrypt`,`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:s.name,length:i.length*8},o,i)}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`AES-KW`:{let i;if(e===`raw`)i=d(t);else if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);i=r(e.k)}else throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);if(![16,24,32].includes(i.length))throw new DOMException(`Invalid AES key length: ${i.length*8}`,`DataError`);return f(o,[`wrapKey`,`unwrapKey`]),new n(`secret`,a,{name:`AES-KW`,length:i.length*8},o,new Uint8Array(i))}case`HMAC`:{let s=c(i.hash);if(e===`raw`){let e=d(t);return f(o,[`sign`,`verify`]),new n(`secret`,a,{name:`HMAC`,hash:{name:s.name},length:e.length*8},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`oct`)throw new DOMException(`JWK kty must be "oct"`,`DataError`);let i=r(e.k);return f(o,[`sign`,`verify`]),new n(`secret`,a,{name:`HMAC`,hash:{name:s.name},length:i.length*8},o,i)}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`)}case`PBKDF2`:if(e===`raw`){let e=d(t);return f(o,[`deriveKey`,`deriveBits`]),new n(`secret`,!1,{name:`PBKDF2`},o,new Uint8Array(e))}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`HKDF`:if(e===`raw`){let e=d(t);return f(o,[`deriveKey`,`deriveBits`]),new n(`secret`,!1,{name:`HKDF`},o,new Uint8Array(e))}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`);case`ECDH`:case`ECDSA`:{let c=i.namedCurve;if(e===`raw`){let e=d(t);return l===`ECDH`?o.length>0&&f(o,[`deriveKey`,`deriveBits`]):f(o,[`verify`]),new n(`public`,a,{name:s.name,namedCurve:c},o,new Uint8Array(e))}if(e===`jwk`){let e=t;if(e.kty!==`EC`)throw new DOMException(`JWK kty must be "EC"`,`DataError`);if(e.d){let t=r(e.d),i=r(e.x),u=r(e.y),d=new Uint8Array(1+i.length+u.length);return d[0]=4,d.set(i,1),d.set(u,1+i.length),f(o,l===`ECDH`?[`deriveKey`,`deriveBits`]:[`sign`]),new n(`private`,a,{name:s.name,namedCurve:c},o,{pub:d,priv:t})}else{let t=r(e.x),i=r(e.y),u=new Uint8Array(1+t.length+i.length);return u[0]=4,u.set(t,1),u.set(i,1+t.length),l===`ECDH`?o.length>0&&f(o,[`deriveKey`,`deriveBits`]):f(o,[`verify`]),new n(`public`,a,{name:s.name,namedCurve:c},o,u)}}throw new DOMException(`Unsupported format: ${e}`,`NotSupportedError`)}default:throw new DOMException(`Unsupported algorithm: ${s.name}`,`NotSupportedError`)}}async exportKey(e,t){if(!t.extractable)throw new DOMException(`Key is not extractable`,`InvalidAccessError`);if(g(t.algorithm.name))return p(e,t);let n=t.algorithm.name.toUpperCase();if(e===`raw`){if(t.type===`secret`){let e=t._handle;return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}if(t.type===`public`&&(n===`ECDH`||n===`ECDSA`)){let e=t._handle;return e.buffer.slice(e.byteOffset,e.byteOffset+e.byteLength)}throw new DOMException(`Cannot export in raw format`,`InvalidAccessError`)}if(e===`jwk`){if(t.type===`secret`){let e=t._handle,r={kty:`oct`,k:i(e),ext:t.extractable,key_ops:[...t.usages]};return n.startsWith(`AES-`)?r.alg=`A${t.algorithm.length}${n.replace(`AES-`,``)}`:n===`HMAC`&&(r.alg=`HS${t.algorithm.hash.name.replace(`SHA-`,``)}`),r}if((n===`ECDH`||n===`ECDSA`)&&(t.type===`public`||t.type===`private`)){let e=t.algorithm.namedCurve,n;n=t.type===`public`?t._handle:t._handle.pub;let r=(n.length-1)/2,a=n.slice(1,1+r),o=n.slice(1+r),s={kty:`EC`,crv:e,x:i(a),y:i(o),ext:t.extractable,key_ops:[...t.usages]};return t.type===`private`&&(s.d=i(t._handle.priv)),s}throw new DOMException(`JWK export not supported for ${n} ${t.type}`,`NotSupportedError`)}throw new DOMException(`Unsupported export format: ${e}`,`NotSupportedError`)}async encrypt(e,t,n){return await R,o(t,`encrypt`),this._encryptImpl(e,t,n)}async _encryptImpl(e,n,r){let i=c(e),a=i.name.toUpperCase(),o=d(r);switch(a){case`AES-CBC`:{let t=d(e.iv),r=n._handle,i=r.length*8,a=C(`aes-${i}-cbc`,r,t),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-CTR`:{let t=d(e.counter),r=n._handle,i=r.length*8,a=C(`aes-${i}-ctr`,r,t),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-GCM`:{let t=e,r=d(t.iv),i=t.additionalData?d(t.additionalData):void 0,a=n._handle,s=a.length*8,c=C(`aes-${s}-gcm`,a,r);i&&c.setAAD(i);let l=c.update(o),u=c.final(),f=c.getAuthTag(),p=new Uint8Array(l.length+u.length+f.length);return p.set(new Uint8Array(l),0),p.set(new Uint8Array(u),l.length),p.set(new Uint8Array(f),l.length+u.length),p.buffer}case`RSA-OAEP`:{let t=n.algorithm.hash.name,r=u(t),i=n._handle,a=e,s=a.label?d(a.label):void 0,c=F(r,i.pem,o,s);return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}case`AES-KW`:{let e=n._handle;return t(o,t=>this._aesEcbBlock(e,t,!0)).buffer}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async decrypt(e,t,n){return await R,o(t,`decrypt`),this._decryptImpl(e,t,n)}async _decryptImpl(t,n,r){let i=c(t),a=i.name.toUpperCase(),o=d(r);switch(a){case`AES-CBC`:{let e=d(t.iv),r=n._handle,i=r.length*8,a=w(`aes-${i}-cbc`,r,e),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-CTR`:{let e=d(t.counter),r=n._handle,i=r.length*8,a=w(`aes-${i}-ctr`,r,e),s=a.update(o),c=a.final(),l=new Uint8Array(s.length+c.length);return l.set(new Uint8Array(s),0),l.set(new Uint8Array(c),s.length),l.buffer}case`AES-GCM`:{let e=t,r=d(e.iv),i=(e.tagLength||128)/8,a=e.additionalData?d(e.additionalData):void 0,s=n._handle,c=s.length*8,l=o.slice(0,o.length-i),u=o.slice(o.length-i),f=w(`aes-${c}-gcm`,s,r);f.setAuthTag(u),a&&f.setAAD(a);let p=f.update(l),m=f.final(),h=new Uint8Array(p.length+m.length);return h.set(new Uint8Array(p),0),h.set(new Uint8Array(m),p.length),h.buffer}case`RSA-OAEP`:{let e=n.algorithm.hash.name,r=u(e),i=n._handle,a=t,s=a.label?d(a.label):void 0,c=I(r,i.pem,o,s);return c.buffer.slice(c.byteOffset,c.byteOffset+c.byteLength)}case`AES-KW`:{let t=n._handle;return e(o,e=>this._aesEcbBlock(t,e,!1)).buffer}default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}_aesEcbBlock(e,t,n){let r=`aes-${e.length*8}-ecb`,i=new Uint8Array,a=n?C(r,e,i):w(r,e,i);a.setAutoPadding?.(!1);let o=a.update(t),s=a.final();if(s.length===0)return o;let c=new Uint8Array(o.length+s.length);return c.set(o,0),c.set(s,o.length),c}async sign(e,t,n){await R;let r=c(e);a(t,r.name),o(t,`sign`);let i=r.name.toUpperCase(),l=d(n);switch(i){case`HMAC`:{let e=t.algorithm.hash.name,n=u(e),r=t._handle,i=S(n,r);i.update(l);let a=i.digest();return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}case`RSASSA-PKCS1-V1_5`:{let e=t.algorithm.hash.name,n=u(e),r=t._handle,i=T(n);i.update(l);let a=i.sign(r.pem);return a.buffer.slice(a.byteOffset,a.byteOffset+a.byteLength)}case`ECDSA`:{let n=e,r=u(typeof n.hash==`string`?n.hash:n.hash.name),i=t.algorithm.namedCurve,a=t._handle,o=j(r,a.priv,l,i);return o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength)}case`RSA-PSS`:{let n=t.algorithm.hash.name,r=u(n),i=t._handle,a=e.saltLength??s(n),o=N(r,i.pem,l,a);return o.buffer.slice(o.byteOffset,o.byteOffset+o.byteLength)}case`ED25519`:return _(L,t,l);default:throw new DOMException(`Unsupported algorithm: ${r.name}`,`NotSupportedError`)}}async verify(e,t,n,r){await R;let i=c(e);a(t,i.name),o(t,`verify`);let l=i.name.toUpperCase(),f=d(r),p=d(n);switch(l){case`HMAC`:{let e=t.algorithm.hash.name,n=u(e),r=t._handle,i=S(n,r);i.update(f);let a=new Uint8Array(i.digest());if(a.length!==p.length)return!1;let o=0;for(let e=0;e<a.length;e++)o|=a[e]^p[e];return o===0}case`RSASSA-PKCS1-V1_5`:{let e=t.algorithm.hash.name,n=u(e),r=t._handle,i=E(n);return i.update(f),i.verify(r.pem,p)}case`ECDSA`:{let n=e,r=u(typeof n.hash==`string`?n.hash:n.hash.name),i=t.algorithm.namedCurve,a=t._handle;return M(r,a,p,f,i)}case`RSA-PSS`:{let n=t.algorithm.hash.name,r=u(n),i=t._handle,a=e.saltLength??s(n);return P(r,i.pem,p,f,a)}case`ED25519`:return v(L,t,p,f);default:throw new DOMException(`Unsupported algorithm: ${i.name}`,`NotSupportedError`)}}async _deriveBitsInternal(e,t,n){await R;let r=c(e);switch(a(t,r.name),r.name.toUpperCase()){case`PBKDF2`:{let r=e,i=u(c(r.hash).name),a=d(r.salt),o=r.iterations,s=t._handle,l=D(s,a,o,n/8,i);return l.buffer.slice(l.byteOffset,l.byteOffset+l.byteLength)}case`HKDF`:{let r=e,i=u(c(r.hash).name),a=d(r.salt),o=d(r.info),s=t._handle;return O(i,s,a,o,n/8)}case`ECDH`:{let r=e.public,i=t.algorithm.namedCurve,a=l(i),o=k(a),s=t._handle;o.setPrivateKey(s.priv);let c=r._handle instanceof Uint8Array?r._handle:r._handle.pub,u=o.computeSecret(c),d=new Uint8Array(u);return n?d.buffer.slice(0,n/8):d.buffer.slice(d.byteOffset,d.byteOffset+d.byteLength)}case`X25519`:return y(L,t,e.public,n);default:throw new DOMException(`Unsupported algorithm: ${r.name}`,`NotSupportedError`)}}async deriveBits(e,t,n=null){return o(t,`deriveBits`),this._deriveBitsInternal(e,t,n)}async deriveKey(e,t,n,r,i){o(t,`deriveKey`);let a=c(n),l,u=a.name.toUpperCase();if(u===`AES-CBC`||u===`AES-CTR`||u===`AES-GCM`)l=n.length;else if(u===`HMAC`){let e=n,t=c(e.hash);l=e.length||s(t.name)*8}else throw new DOMException(`Unsupported derived key algorithm: ${a.name}`,`NotSupportedError`);let d=await this._deriveBitsInternal(e,t,l);return this.importKey(`raw`,d,n,r,i)}async wrapKey(e,t,n,r){await R,o(n,`wrapKey`);let i=await this.exportKey(e,t),a=e===`jwk`?new TextEncoder().encode(JSON.stringify(i)):i;return this._encryptImpl(r,n,a)}async unwrapKey(e,t,n,r,i,a,s){await R,o(n,`unwrapKey`);let c=await this._decryptImpl(r,n,t),l=e===`jwk`?JSON.parse(new TextDecoder().decode(new Uint8Array(c))):c;return this.importKey(e,l,i,a,s)}};export{SubtleCrypto};
package/lib/esm/util.js CHANGED
@@ -1 +1 @@
1
- import"./_virtual/_rolldown/runtime.js";import{DOMException as e}from"@gjsify/dom-exception";function normalizeAlgorithm(e){if(typeof e==`string`)return{name:e};if(!e||typeof e.name!=`string`)throw TypeError(`Algorithm must have a name property`);return e}const t={"SHA-1":`sha1`,"SHA-256":`sha256`,"SHA-384":`sha384`,"SHA-512":`sha512`};function toNodeHashName(n){let r=t[n.toUpperCase()]||t[n];if(!r)throw new e(`Unrecognized hash name: ${n}`,`NotSupportedError`);return r}function toWebCryptoHashName(n){let r=n.toUpperCase().replace(/[^A-Z0-9]/g,``);for(let[e,i]of Object.entries(t))if(i===n||r===e.replace(`-`,``))return e;throw new e(`Unrecognized hash name: ${n}`,`NotSupportedError`)}const n={"P-256":`prime256v1`,"P-384":`secp384r1`,"P-521":`secp521r1`};function toNodeCurveName(t){let r=n[t];if(!r)throw new e(`Unrecognized curve name: ${t}`,`NotSupportedError`);return r}function hashSize(t){switch(toNodeHashName(t)){case`sha1`:return 20;case`sha256`:return 32;case`sha384`:return 48;case`sha512`:return 64;default:throw new e(`Unsupported hash: ${t}`,`NotSupportedError`)}}function validateUsages(t,n){for(let r of t)if(!n.includes(r))throw new e(`Invalid key usage: ${r}`,`SyntaxError`);if(t.length===0)throw new e(`Key usages must not be empty`,`SyntaxError`)}function checkUsage(t,n){if(!t.usages.includes(n))throw new e(`Key does not support the '${n}' usage`,`InvalidAccessError`)}const r=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`,i=new Uint8Array(128);for(let e=0;e<64;e++)i[r.charCodeAt(e)]=e;function bytesToBase64(e){let t=``,n=e.length;for(let i=0;i<n;i+=3){let a=e[i],o=i+1<n?e[i+1]:0,s=i+2<n?e[i+2]:0;t+=r[a>>2&63],t+=r[(a<<4|o>>4)&63],t+=i+1<n?r[(o<<2|s>>6)&63]:`=`,t+=i+2<n?r[s&63]:`=`}return t}function base64ToBytes(e){let t=e;for(;t.endsWith(`=`);)t=t.slice(0,-1);let n=[],r=0,a=0;for(let e=0;e<t.length;e++)a=a<<6|i[t.charCodeAt(e)],r+=6,r>=8&&(r-=8,n.push(a>>r&255));return new Uint8Array(n)}function base64urlEncode(e){return bytesToBase64(e).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function base64urlDecode(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);for(;t.length%4;)t+=`=`;return base64ToBytes(t)}function toUint8Array(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw TypeError(`Expected BufferSource`)}export{base64urlDecode,base64urlEncode,checkUsage,hashSize,normalizeAlgorithm,toNodeCurveName,toNodeHashName,toUint8Array,toWebCryptoHashName,validateUsages};
1
+ import"./_virtual/_rolldown/runtime.js";import{DOMException as e}from"@gjsify/dom-exception";function normalizeAlgorithm(e){if(typeof e==`string`)return{name:e};if(!e||typeof e.name!=`string`)throw TypeError(`Algorithm must have a name property`);return e}const t={"SHA-1":`sha1`,"SHA-256":`sha256`,"SHA-384":`sha384`,"SHA-512":`sha512`};function toNodeHashName(n){let r=t[n.toUpperCase()]||t[n];if(!r)throw new e(`Unrecognized hash name: ${n}`,`NotSupportedError`);return r}function toWebCryptoHashName(n){let r=n.toUpperCase().replace(/[^A-Z0-9]/g,``);for(let[e,i]of Object.entries(t))if(i===n||r===e.replace(`-`,``))return e;throw new e(`Unrecognized hash name: ${n}`,`NotSupportedError`)}const n={"P-256":`prime256v1`,"P-384":`secp384r1`,"P-521":`secp521r1`};function toNodeCurveName(t){let r=n[t];if(!r)throw new e(`Unrecognized curve name: ${t}`,`NotSupportedError`);return r}function hashSize(t){switch(toNodeHashName(t)){case`sha1`:return 20;case`sha256`:return 32;case`sha384`:return 48;case`sha512`:return 64;default:throw new e(`Unsupported hash: ${t}`,`NotSupportedError`)}}function validateUsages(t,n){for(let r of t)if(!n.includes(r))throw new e(`Invalid key usage: ${r}`,`SyntaxError`);if(t.length===0)throw new e(`Key usages must not be empty`,`SyntaxError`)}function checkUsage(t,n){if(!t.usages.includes(n))throw new e(`Key does not support the '${n}' usage`,`InvalidAccessError`)}const r=`ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/`,i=new Uint8Array(128);for(let e=0;e<64;e++)i[r.charCodeAt(e)]=e;function bytesToBase64(e){let t=``,n=e.length;for(let i=0;i<n;i+=3){let a=e[i],o=i+1<n?e[i+1]:0,s=i+2<n?e[i+2]:0;t+=r[a>>2&63],t+=r[(a<<4|o>>4)&63],t+=i+1<n?r[(o<<2|s>>6)&63]:`=`,t+=i+2<n?r[s&63]:`=`}return t}function base64ToBytes(e){let t=e;for(;t.endsWith(`=`);)t=t.slice(0,-1);let n=[],r=0,a=0;for(let e=0;e<t.length;e++)a=a<<6|i[t.charCodeAt(e)],r+=6,r>=8&&(r-=8,n.push(a>>r&255));return new Uint8Array(n)}function base64urlEncode(e){return bytesToBase64(e).replace(/\+/g,`-`).replace(/\//g,`_`).replace(/=+$/,``)}function base64urlDecode(e){let t=e.replace(/-/g,`+`).replace(/_/g,`/`);for(;t.length%4;)t+=`=`;return base64ToBytes(t)}function toUint8Array(e){if(e instanceof Uint8Array)return e;if(e instanceof ArrayBuffer)return new Uint8Array(e);if(ArrayBuffer.isView(e))return new Uint8Array(e.buffer,e.byteOffset,e.byteLength);throw TypeError(`Expected BufferSource`)}function checkAlgorithmMatch(t,n){if(t.algorithm.name.toUpperCase()!==n.toUpperCase())throw new e(`Key algorithm mismatch`,`InvalidAccessError`)}export{base64urlDecode,base64urlEncode,checkAlgorithmMatch,checkUsage,hashSize,normalizeAlgorithm,toNodeCurveName,toNodeHashName,toUint8Array,toWebCryptoHashName,validateUsages};
@@ -0,0 +1,42 @@
1
+ import { CryptoKey, type CryptoKeyPair, type KeyUsage } from './crypto-key.js';
2
+ export type CfrgName = 'Ed25519' | 'X25519';
3
+ /** The slice of a node:crypto KeyObject this module drives. */
4
+ export interface KeyObjectLike {
5
+ readonly type: 'public' | 'private' | 'secret';
6
+ readonly asymmetricKeyType?: string;
7
+ export(options: {
8
+ format: string;
9
+ type?: string;
10
+ }): Uint8Array | string | Record<string, unknown>;
11
+ }
12
+ /** The node:crypto functions this module needs, handed in by subtle.ts's lazy loader. */
13
+ export interface CfrgCrypto {
14
+ generateKeyPairSync(type: string): {
15
+ publicKey: KeyObjectLike;
16
+ privateKey: KeyObjectLike;
17
+ };
18
+ sign(algorithm: null, data: Uint8Array, key: KeyObjectLike): Uint8Array;
19
+ verify(algorithm: null, data: Uint8Array, key: KeyObjectLike, signature: Uint8Array): boolean;
20
+ diffieHellman(options: {
21
+ privateKey: KeyObjectLike;
22
+ publicKey: KeyObjectLike;
23
+ }): Uint8Array;
24
+ createPrivateKey(input: unknown): KeyObjectLike;
25
+ createPublicKey(input: unknown): KeyObjectLike;
26
+ }
27
+ /** CryptoKey handle of an Ed25519 / X25519 key. */
28
+ export interface CfrgHandle {
29
+ keyObject: KeyObjectLike;
30
+ }
31
+ export declare function cfrgName(name: string): CfrgName | undefined;
32
+ export declare function cfrgGenerateKey(c: CfrgCrypto, name: CfrgName, extractable: boolean, usages: KeyUsage[]): CryptoKeyPair;
33
+ export declare function cfrgImportKey(c: CfrgCrypto, format: string, keyData: BufferSource | JsonWebKey, name: CfrgName, extractable: boolean, usages: KeyUsage[]): CryptoKey;
34
+ export declare function cfrgExportKey(format: string, key: CryptoKey): ArrayBuffer | JsonWebKey;
35
+ export declare function ed25519Sign(c: CfrgCrypto, key: CryptoKey, data: Uint8Array): ArrayBuffer;
36
+ export declare function ed25519Verify(c: CfrgCrypto, key: CryptoKey, signature: Uint8Array, data: Uint8Array): boolean;
37
+ /**
38
+ * X25519 deriveBits: the full 32-byte secret for a null length, else its
39
+ * first `length` bits. The all-zero secret of a low-order peer key is an
40
+ * OperationError per spec, which node:crypto's refusal maps onto.
41
+ */
42
+ export declare function x25519DeriveBits(c: CfrgCrypto, baseKey: CryptoKey, publicKey: CryptoKey, length: number | null | undefined): ArrayBuffer;
@@ -0,0 +1,2 @@
1
+ declare const _default: () => Promise<void>;
2
+ export default _default;
@@ -11,7 +11,7 @@ declare class CryptoPolyfill {
11
11
  randomUUID(): `${string}-${string}-${string}-${string}-${string}`;
12
12
  }
13
13
  declare const cryptoInstance: Crypto | CryptoPolyfill;
14
- declare const subtleInstance: SubtleCrypto | globalThis.SubtleCrypto;
14
+ declare const subtleInstance: globalThis.SubtleCrypto | SubtleCrypto;
15
15
  export { CryptoKey, SubtleCrypto, CryptoPolyfill as Crypto };
16
16
  export { subtleInstance as subtle, cryptoInstance as crypto };
17
17
  export default cryptoInstance;
@@ -30,7 +30,7 @@ export declare class SubtleCrypto {
30
30
  verify(algorithm: AlgorithmIdentifier, key: CryptoKey, signature: BufferSource, data: BufferSource): Promise<boolean>;
31
31
  /** Internal deriveBits without usage check (used by deriveKey) */
32
32
  private _deriveBitsInternal;
33
- deriveBits(algorithm: AlgorithmIdentifier, baseKey: CryptoKey, length: number): Promise<ArrayBuffer>;
33
+ deriveBits(algorithm: AlgorithmIdentifier, baseKey: CryptoKey, length?: number | null): Promise<ArrayBuffer>;
34
34
  deriveKey(algorithm: AlgorithmIdentifier, baseKey: CryptoKey, derivedKeyAlgorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
35
35
  wrapKey(format: 'raw' | 'jwk' | 'pkcs8' | 'spki', key: CryptoKey, wrappingKey: CryptoKey, wrapAlgorithm: AlgorithmIdentifier): Promise<ArrayBuffer>;
36
36
  unwrapKey(format: 'raw' | 'jwk' | 'pkcs8' | 'spki', wrappedKey: BufferSource, unwrappingKey: CryptoKey, unwrapAlgorithm: AlgorithmIdentifier, unwrappedKeyAlgorithm: AlgorithmIdentifier, extractable: boolean, keyUsages: KeyUsage[]): Promise<CryptoKey>;
@@ -24,3 +24,13 @@ export declare function base64urlEncode(data: Uint8Array): string;
24
24
  export declare function base64urlDecode(str: string): Uint8Array;
25
25
  /** Convert ArrayBuffer or view to Uint8Array */
26
26
  export declare function toUint8Array(data: BufferSource): Uint8Array;
27
+ /**
28
+ * WebCrypto § sign/verify/deriveBits step "if the name member of normalizedAlgorithm is not
29
+ * equal to the name of key's [[algorithm]], throw InvalidAccessError" — without it a key of
30
+ * one algorithm reaches another algorithm's implementation and fails on its handle shape.
31
+ */
32
+ export declare function checkAlgorithmMatch(key: {
33
+ algorithm: {
34
+ name: string;
35
+ };
36
+ }, requested: string): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gjsify/webcrypto",
3
- "version": "0.52.0",
3
+ "version": "0.54.0",
4
4
  "description": "W3C WebCrypto API (SubtleCrypto) for GJS using @gjsify/crypto primitives",
5
5
  "type": "module",
6
6
  "module": "lib/esm/index.js",
@@ -49,11 +49,11 @@
49
49
  "crypto"
50
50
  ],
51
51
  "dependencies": {
52
- "@gjsify/dom-exception": "^0.52.0"
52
+ "@gjsify/dom-exception": "^0.54.0"
53
53
  },
54
54
  "devDependencies": {
55
- "@gjsify/cli": "^0.52.0",
56
- "@gjsify/unit": "^0.52.0",
55
+ "@gjsify/cli": "^0.54.0",
56
+ "@gjsify/unit": "^0.54.0",
57
57
  "@types/node": "^25.9.2",
58
58
  "typescript": "^6.0.3"
59
59
  },