@stacksjs/security 0.70.23 → 0.70.25
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.
- package/README.md +1 -1
- package/dist/index.js +1 -1
- package/dist/src/crypt.d.ts +3 -0
- package/dist/src/hash.d.ts +112 -0
- package/dist/src/index.d.ts +4 -0
- package/dist/src/key.d.ts +1 -0
- package/dist/src/webhook.d.ts +96 -0
- package/package.json +25 -11
- package/dist/crypt.d.ts +0 -4
- package/dist/hash.d.ts +0 -58
- package/dist/index.d.ts +0 -3
- package/dist/key.d.ts +0 -1
package/README.md
CHANGED
|
@@ -24,7 +24,7 @@ import { base64Encode, base64Verify, bcryptEncode, bcryptVerify, decrypt, encryp
|
|
|
24
24
|
// and more...
|
|
25
25
|
```
|
|
26
26
|
|
|
27
|
-
To view the full documentation, please visit [https://stacksjs.
|
|
27
|
+
To view the full documentation, please visit [<https://stacksjs.com/securit>y](https://stacksjs.com/security).
|
|
28
28
|
|
|
29
29
|
## 🧪 Testing
|
|
30
30
|
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
1
|
// @bun
|
|
2
|
-
var sY=Object.create;var{getPrototypeOf:tY,defineProperty:JY,getOwnPropertyNames:eY}=Object;var Yq=Object.prototype.hasOwnProperty;var d=(Y,$,v)=>{v=Y!=null?sY(tY(Y)):{};let H=$||!Y||!Y.__esModule?JY(v,"default",{value:Y,enumerable:!0}):v;for(let g of eY(Y))if(!Yq.call(H,g))JY(H,g,{get:()=>Y[g],enumerable:!0});return H};var p=(Y,$)=>()=>($||Y(($={exports:{}}).exports,$),$.exports);var FY=import.meta.require;var h=p((c,zY)=>{(function(Y,$){if(typeof c==="object")zY.exports=c=$();else if(typeof define==="function"&&define.amd)define([],$);else Y.CryptoJS=$()})(c,function(){var Y=Y||function($,v){var H;if(typeof window!=="undefined"&&window.crypto)H=window.crypto;if(typeof self!=="undefined"&&self.crypto)H=self.crypto;if(typeof globalThis!=="undefined"&&globalThis.crypto)H=globalThis.crypto;if(!H&&typeof window!=="undefined"&&window.msCrypto)H=window.msCrypto;if(!H&&typeof global!=="undefined"&&global.crypto)H=global.crypto;if(!H)try{H=FY("node:crypto")}catch(q){}var g=function(){if(H){if(typeof H.getRandomValues==="function")try{return H.getRandomValues(new Uint32Array(1))[0]}catch(q){}if(typeof H.randomBytes==="function")try{return H.randomBytes(4).readInt32LE()}catch(q){}}throw new Error("Native crypto module could not be used to get secure random number.")},I=Object.create||function(){function q(){}return function(E){var j;return q.prototype=E,j=new q,q.prototype=null,j}}(),C={},Q=C.lib={},U=Q.Base=function(){return{extend:function(q){var E=I(this);if(q)E.mixIn(q);if(!E.hasOwnProperty("init")||this.init===E.init)E.init=function(){E.$super.init.apply(this,arguments)};return E.init.prototype=E,E.$super=this,E},create:function(){var q=this.extend();return q.init.apply(q,arguments),q},init:function(){},mixIn:function(q){for(var E in q)if(q.hasOwnProperty(E))this[E]=q[E];if(q.hasOwnProperty("toString"))this.toString=q.toString},clone:function(){return this.init.prototype.extend(this)}}}(),O=Q.WordArray=U.extend({init:function(q,E){if(q=this.words=q||[],E!=v)this.sigBytes=E;else this.sigBytes=q.length*4},toString:function(q){return(q||R).stringify(this)},concat:function(q){var E=this.words,j=q.words,G=this.sigBytes,X=q.sigBytes;if(this.clamp(),G%4)for(var w=0;w<X;w++){var B=j[w>>>2]>>>24-w%4*8&255;E[G+w>>>2]|=B<<24-(G+w)%4*8}else for(var T=0;T<X;T+=4)E[G+T>>>2]=j[T>>>2];return this.sigBytes+=X,this},clamp:function(){var q=this.words,E=this.sigBytes;q[E>>>2]&=4294967295<<32-E%4*8,q.length=$.ceil(E/4)},clone:function(){var q=U.clone.call(this);return q.words=this.words.slice(0),q},random:function(q){var E=[];for(var j=0;j<q;j+=4)E.push(g());return new O.init(E,q)}}),J=C.enc={},R=J.Hex={stringify:function(q){var{words:E,sigBytes:j}=q,G=[];for(var X=0;X<j;X++){var w=E[X>>>2]>>>24-X%4*8&255;G.push((w>>>4).toString(16)),G.push((w&15).toString(16))}return G.join("")},parse:function(q){var E=q.length,j=[];for(var G=0;G<E;G+=2)j[G>>>3]|=parseInt(q.substr(G,2),16)<<24-G%8*4;return new O.init(j,E/2)}},F=J.Latin1={stringify:function(q){var{words:E,sigBytes:j}=q,G=[];for(var X=0;X<j;X++){var w=E[X>>>2]>>>24-X%4*8&255;G.push(String.fromCharCode(w))}return G.join("")},parse:function(q){var E=q.length,j=[];for(var G=0;G<E;G++)j[G>>>2]|=(q.charCodeAt(G)&255)<<24-G%4*8;return new O.init(j,E)}},z=J.Utf8={stringify:function(q){try{return decodeURIComponent(escape(F.stringify(q)))}catch(E){throw new Error("Malformed UTF-8 data")}},parse:function(q){return F.parse(unescape(encodeURIComponent(q)))}},W=Q.BufferedBlockAlgorithm=U.extend({reset:function(){this._data=new O.init,this._nDataBytes=0},_append:function(q){if(typeof q=="string")q=z.parse(q);this._data.concat(q),this._nDataBytes+=q.sigBytes},_process:function(q){var E,j=this._data,G=j.words,X=j.sigBytes,w=this.blockSize,B=w*4,T=X/B;if(q)T=$.ceil(T);else T=$.max((T|0)-this._minBufferSize,0);var k=T*w,M=$.min(k*4,X);if(k){for(var Z=0;Z<k;Z+=w)this._doProcessBlock(G,Z);E=G.splice(0,k),j.sigBytes-=M}return new O.init(E,M)},clone:function(){var q=U.clone.call(this);return q._data=this._data.clone(),q},_minBufferSize:0}),n=Q.Hasher=W.extend({cfg:U.extend(),init:function(q){this.cfg=this.cfg.extend(q),this.reset()},reset:function(){W.reset.call(this),this._doReset()},update:function(q){return this._append(q),this._process(),this},finalize:function(q){if(q)this._append(q);var E=this._doFinalize();return E},blockSize:16,_createHelper:function(q){return function(E,j){return new q.init(j).finalize(E)}},_createHmacHelper:function(q){return function(E,j){return new u.HMAC.init(q,j).finalize(E)}}}),u=C.algo={};return C}(Math);return Y})});var QY=p((o,OY)=>{(function(Y,$){if(typeof o==="object")OY.exports=o=$(h());else if(typeof define==="function"&&define.amd)define(["./core"],$);else $(Y.CryptoJS)})(o,function(Y){return function(){var $=Y,v=$.lib,H=v.WordArray,g=$.enc,I=g.Base64={stringify:function(Q){var{words:U,sigBytes:O}=Q,J=this._map;Q.clamp();var R=[];for(var F=0;F<O;F+=3){var z=U[F>>>2]>>>24-F%4*8&255,W=U[F+1>>>2]>>>24-(F+1)%4*8&255,n=U[F+2>>>2]>>>24-(F+2)%4*8&255,u=z<<16|W<<8|n;for(var q=0;q<4&&F+q*0.75<O;q++)R.push(J.charAt(u>>>6*(3-q)&63))}var E=J.charAt(64);if(E)while(R.length%4)R.push(E);return R.join("")},parse:function(Q){var U=Q.length,O=this._map,J=this._reverseMap;if(!J){J=this._reverseMap=[];for(var R=0;R<O.length;R++)J[O.charCodeAt(R)]=R}var F=O.charAt(64);if(F){var z=Q.indexOf(F);if(z!==-1)U=z}return C(Q,U,J)},_map:"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="};function C(Q,U,O){var J=[],R=0;for(var F=0;F<U;F++)if(F%4){var z=O[Q.charCodeAt(F-1)]<<F%4*2,W=O[Q.charCodeAt(F)]>>>6-F%4*2,n=z|W;J[R>>>2]|=n<<24-R%4*8,R++}return H.create(J,R)}}(),Y.enc.Base64})});var ZY=p((r,WY)=>{(function(Y,$){if(typeof r==="object")WY.exports=r=$(h());else if(typeof define==="function"&&define.amd)define(["./core"],$);else $(Y.CryptoJS)})(r,function(Y){return function($){var v=Y,H=v.lib,g=H.WordArray,I=H.Hasher,C=v.algo,Q=[];(function(){for(var z=0;z<64;z++)Q[z]=$.abs($.sin(z+1))*4294967296|0})();var U=C.MD5=I.extend({_doReset:function(){this._hash=new g.init([1732584193,4023233417,2562383102,271733878])},_doProcessBlock:function(z,W){for(var n=0;n<16;n++){var u=W+n,q=z[u];z[u]=(q<<8|q>>>24)&16711935|(q<<24|q>>>8)&4278255360}var E=this._hash.words,j=z[W+0],G=z[W+1],X=z[W+2],w=z[W+3],B=z[W+4],T=z[W+5],k=z[W+6],M=z[W+7],Z=z[W+8],K=z[W+9],A=z[W+10],D=z[W+11],m=z[W+12],x=z[W+13],l=z[W+14],S=z[W+15],V=E[0],P=E[1],N=E[2],L=E[3];V=O(V,P,N,L,j,7,Q[0]),L=O(L,V,P,N,G,12,Q[1]),N=O(N,L,V,P,X,17,Q[2]),P=O(P,N,L,V,w,22,Q[3]),V=O(V,P,N,L,B,7,Q[4]),L=O(L,V,P,N,T,12,Q[5]),N=O(N,L,V,P,k,17,Q[6]),P=O(P,N,L,V,M,22,Q[7]),V=O(V,P,N,L,Z,7,Q[8]),L=O(L,V,P,N,K,12,Q[9]),N=O(N,L,V,P,A,17,Q[10]),P=O(P,N,L,V,D,22,Q[11]),V=O(V,P,N,L,m,7,Q[12]),L=O(L,V,P,N,x,12,Q[13]),N=O(N,L,V,P,l,17,Q[14]),P=O(P,N,L,V,S,22,Q[15]),V=J(V,P,N,L,G,5,Q[16]),L=J(L,V,P,N,k,9,Q[17]),N=J(N,L,V,P,D,14,Q[18]),P=J(P,N,L,V,j,20,Q[19]),V=J(V,P,N,L,T,5,Q[20]),L=J(L,V,P,N,A,9,Q[21]),N=J(N,L,V,P,S,14,Q[22]),P=J(P,N,L,V,B,20,Q[23]),V=J(V,P,N,L,K,5,Q[24]),L=J(L,V,P,N,l,9,Q[25]),N=J(N,L,V,P,w,14,Q[26]),P=J(P,N,L,V,Z,20,Q[27]),V=J(V,P,N,L,x,5,Q[28]),L=J(L,V,P,N,X,9,Q[29]),N=J(N,L,V,P,M,14,Q[30]),P=J(P,N,L,V,m,20,Q[31]),V=R(V,P,N,L,T,4,Q[32]),L=R(L,V,P,N,Z,11,Q[33]),N=R(N,L,V,P,D,16,Q[34]),P=R(P,N,L,V,l,23,Q[35]),V=R(V,P,N,L,G,4,Q[36]),L=R(L,V,P,N,B,11,Q[37]),N=R(N,L,V,P,M,16,Q[38]),P=R(P,N,L,V,A,23,Q[39]),V=R(V,P,N,L,x,4,Q[40]),L=R(L,V,P,N,j,11,Q[41]),N=R(N,L,V,P,w,16,Q[42]),P=R(P,N,L,V,k,23,Q[43]),V=R(V,P,N,L,K,4,Q[44]),L=R(L,V,P,N,m,11,Q[45]),N=R(N,L,V,P,S,16,Q[46]),P=R(P,N,L,V,X,23,Q[47]),V=F(V,P,N,L,j,6,Q[48]),L=F(L,V,P,N,M,10,Q[49]),N=F(N,L,V,P,l,15,Q[50]),P=F(P,N,L,V,T,21,Q[51]),V=F(V,P,N,L,m,6,Q[52]),L=F(L,V,P,N,w,10,Q[53]),N=F(N,L,V,P,A,15,Q[54]),P=F(P,N,L,V,G,21,Q[55]),V=F(V,P,N,L,Z,6,Q[56]),L=F(L,V,P,N,S,10,Q[57]),N=F(N,L,V,P,k,15,Q[58]),P=F(P,N,L,V,x,21,Q[59]),V=F(V,P,N,L,B,6,Q[60]),L=F(L,V,P,N,D,10,Q[61]),N=F(N,L,V,P,X,15,Q[62]),P=F(P,N,L,V,K,21,Q[63]),E[0]=E[0]+V|0,E[1]=E[1]+P|0,E[2]=E[2]+N|0,E[3]=E[3]+L|0},_doFinalize:function(){var z=this._data,W=z.words,n=this._nDataBytes*8,u=z.sigBytes*8;W[u>>>5]|=128<<24-u%32;var q=$.floor(n/4294967296),E=n;W[(u+64>>>9<<4)+15]=(q<<8|q>>>24)&16711935|(q<<24|q>>>8)&4278255360,W[(u+64>>>9<<4)+14]=(E<<8|E>>>24)&16711935|(E<<24|E>>>8)&4278255360,z.sigBytes=(W.length+1)*4,this._process();var j=this._hash,G=j.words;for(var X=0;X<4;X++){var w=G[X];G[X]=(w<<8|w>>>24)&16711935|(w<<24|w>>>8)&4278255360}return j},clone:function(){var z=I.clone.call(this);return z._hash=this._hash.clone(),z}});function O(z,W,n,u,q,E,j){var G=z+(W&n|~W&u)+q+j;return(G<<E|G>>>32-E)+W}function J(z,W,n,u,q,E,j){var G=z+(W&u|n&~u)+q+j;return(G<<E|G>>>32-E)+W}function R(z,W,n,u,q,E,j){var G=z+(W^n^u)+q+j;return(G<<E|G>>>32-E)+W}function F(z,W,n,u,q,E,j){var G=z+(n^(W|~u))+q+j;return(G<<E|G>>>32-E)+W}v.MD5=I._createHelper(U),v.HmacMD5=I._createHmacHelper(U)}(Math),Y.MD5})});var AY=p((a,RY)=>{(function(Y,$){if(typeof a==="object")RY.exports=a=$(h());else if(typeof define==="function"&&define.amd)define(["./core"],$);else $(Y.CryptoJS)})(a,function(Y){return function(){var $=Y,v=$.lib,H=v.WordArray,g=v.Hasher,I=$.algo,C=[],Q=I.SHA1=g.extend({_doReset:function(){this._hash=new H.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(U,O){var J=this._hash.words,R=J[0],F=J[1],z=J[2],W=J[3],n=J[4];for(var u=0;u<80;u++){if(u<16)C[u]=U[O+u]|0;else{var q=C[u-3]^C[u-8]^C[u-14]^C[u-16];C[u]=q<<1|q>>>31}var E=(R<<5|R>>>27)+n+C[u];if(u<20)E+=(F&z|~F&W)+1518500249;else if(u<40)E+=(F^z^W)+1859775393;else if(u<60)E+=(F&z|F&W|z&W)-1894007588;else E+=(F^z^W)-899497514;n=W,W=z,z=F<<30|F>>>2,F=R,R=E}J[0]=J[0]+R|0,J[1]=J[1]+F|0,J[2]=J[2]+z|0,J[3]=J[3]+W|0,J[4]=J[4]+n|0},_doFinalize:function(){var U=this._data,O=U.words,J=this._nDataBytes*8,R=U.sigBytes*8;return O[R>>>5]|=128<<24-R%32,O[(R+64>>>9<<4)+14]=Math.floor(J/4294967296),O[(R+64>>>9<<4)+15]=J,U.sigBytes=O.length*4,this._process(),this._hash},clone:function(){var U=g.clone.call(this);return U._hash=this._hash.clone(),U}});$.SHA1=g._createHelper(Q),$.HmacSHA1=g._createHmacHelper(Q)}(),Y.SHA1})});var HY=p((s,vY)=>{(function(Y,$){if(typeof s==="object")vY.exports=s=$(h());else if(typeof define==="function"&&define.amd)define(["./core"],$);else $(Y.CryptoJS)})(s,function(Y){(function(){var $=Y,v=$.lib,H=v.Base,g=$.enc,I=g.Utf8,C=$.algo,Q=C.HMAC=H.extend({init:function(U,O){if(U=this._hasher=new U.init,typeof O=="string")O=I.parse(O);var J=U.blockSize,R=J*4;if(O.sigBytes>R)O=U.finalize(O);O.clamp();var F=this._oKey=O.clone(),z=this._iKey=O.clone(),W=F.words,n=z.words;for(var u=0;u<J;u++)W[u]^=1549556828,n[u]^=909522486;F.sigBytes=z.sigBytes=R,this.reset()},reset:function(){var U=this._hasher;U.reset(),U.update(this._iKey)},update:function(U){return this._hasher.update(U),this},finalize:function(U){var O=this._hasher,J=O.finalize(U);O.reset();var R=O.finalize(this._oKey.clone().concat(J));return R}})})()})});var VY=p((t,TY)=>{(function(Y,$,v){if(typeof t==="object")TY.exports=t=$(h(),AY(),HY());else if(typeof define==="function"&&define.amd)define(["./core","./sha1","./hmac"],$);else $(Y.CryptoJS)})(t,function(Y){return function(){var $=Y,v=$.lib,H=v.Base,g=v.WordArray,I=$.algo,C=I.MD5,Q=I.EvpKDF=H.extend({cfg:H.extend({keySize:4,hasher:C,iterations:1}),init:function(U){this.cfg=this.cfg.extend(U)},compute:function(U,O){var J,R=this.cfg,F=R.hasher.create(),z=g.create(),W=z.words,n=R.keySize,u=R.iterations;while(W.length<n){if(J)F.update(J);J=F.update(U).finalize(O),F.reset();for(var q=1;q<u;q++)J=F.finalize(J),F.reset();z.concat(J)}return z.sigBytes=n*4,z}});$.EvpKDF=function(U,O,J){return Q.create(J).compute(U,O)}}(),Y.EvpKDF})});var XY=p((e,UY)=>{(function(Y,$,v){if(typeof e==="object")UY.exports=e=$(h(),VY());else if(typeof define==="function"&&define.amd)define(["./core","./evpkdf"],$);else $(Y.CryptoJS)})(e,function(Y){Y.lib.Cipher||function($){var v=Y,H=v.lib,g=H.Base,I=H.WordArray,C=H.BufferedBlockAlgorithm,Q=v.enc,U=Q.Utf8,O=Q.Base64,J=v.algo,R=J.EvpKDF,F=H.Cipher=C.extend({cfg:g.extend(),createEncryptor:function(Z,K){return this.create(this._ENC_XFORM_MODE,Z,K)},createDecryptor:function(Z,K){return this.create(this._DEC_XFORM_MODE,Z,K)},init:function(Z,K,A){this.cfg=this.cfg.extend(A),this._xformMode=Z,this._key=K,this.reset()},reset:function(){C.reset.call(this),this._doReset()},process:function(Z){return this._append(Z),this._process()},finalize:function(Z){if(Z)this._append(Z);var K=this._doFinalize();return K},keySize:4,ivSize:4,_ENC_XFORM_MODE:1,_DEC_XFORM_MODE:2,_createHelper:function(){function Z(K){if(typeof K=="string")return M;else return B}return function(K){return{encrypt:function(A,D,m){return Z(D).encrypt(K,A,D,m)},decrypt:function(A,D,m){return Z(D).decrypt(K,A,D,m)}}}}()}),z=H.StreamCipher=F.extend({_doFinalize:function(){var Z=this._process(!0);return Z},blockSize:1}),W=v.mode={},n=H.BlockCipherMode=g.extend({createEncryptor:function(Z,K){return this.Encryptor.create(Z,K)},createDecryptor:function(Z,K){return this.Decryptor.create(Z,K)},init:function(Z,K){this._cipher=Z,this._iv=K}}),u=W.CBC=function(){var Z=n.extend();Z.Encryptor=Z.extend({processBlock:function(A,D){var m=this._cipher,x=m.blockSize;K.call(this,A,D,x),m.encryptBlock(A,D),this._prevBlock=A.slice(D,D+x)}}),Z.Decryptor=Z.extend({processBlock:function(A,D){var m=this._cipher,x=m.blockSize,l=A.slice(D,D+x);m.decryptBlock(A,D),K.call(this,A,D,x),this._prevBlock=l}});function K(A,D,m){var x,l=this._iv;if(l)x=l,this._iv=$;else x=this._prevBlock;for(var S=0;S<m;S++)A[D+S]^=x[S]}return Z}(),q=v.pad={},E=q.Pkcs7={pad:function(Z,K){var A=K*4,D=A-Z.sigBytes%A,m=D<<24|D<<16|D<<8|D,x=[];for(var l=0;l<D;l+=4)x.push(m);var S=I.create(x,D);Z.concat(S)},unpad:function(Z){var K=Z.words[Z.sigBytes-1>>>2]&255;Z.sigBytes-=K}},j=H.BlockCipher=F.extend({cfg:F.cfg.extend({mode:u,padding:E}),reset:function(){var Z;F.reset.call(this);var K=this.cfg,A=K.iv,D=K.mode;if(this._xformMode==this._ENC_XFORM_MODE)Z=D.createEncryptor;else Z=D.createDecryptor,this._minBufferSize=1;if(this._mode&&this._mode.__creator==Z)this._mode.init(this,A&&A.words);else this._mode=Z.call(D,this,A&&A.words),this._mode.__creator=Z},_doProcessBlock:function(Z,K){this._mode.processBlock(Z,K)},_doFinalize:function(){var Z,K=this.cfg.padding;if(this._xformMode==this._ENC_XFORM_MODE)K.pad(this._data,this.blockSize),Z=this._process(!0);else Z=this._process(!0),K.unpad(Z);return Z},blockSize:4}),G=H.CipherParams=g.extend({init:function(Z){this.mixIn(Z)},toString:function(Z){return(Z||this.formatter).stringify(this)}}),X=v.format={},w=X.OpenSSL={stringify:function(Z){var K,A=Z.ciphertext,D=Z.salt;if(D)K=I.create([1398893684,1701076831]).concat(D).concat(A);else K=A;return K.toString(O)},parse:function(Z){var K,A=O.parse(Z),D=A.words;if(D[0]==1398893684&&D[1]==1701076831)K=I.create(D.slice(2,4)),D.splice(0,4),A.sigBytes-=16;return G.create({ciphertext:A,salt:K})}},B=H.SerializableCipher=g.extend({cfg:g.extend({format:w}),encrypt:function(Z,K,A,D){D=this.cfg.extend(D);var m=Z.createEncryptor(A,D),x=m.finalize(K),l=m.cfg;return G.create({ciphertext:x,key:A,iv:l.iv,algorithm:Z,mode:l.mode,padding:l.padding,blockSize:Z.blockSize,formatter:D.format})},decrypt:function(Z,K,A,D){D=this.cfg.extend(D),K=this._parse(K,D.format);var m=Z.createDecryptor(A,D).finalize(K.ciphertext);return m},_parse:function(Z,K){if(typeof Z=="string")return K.parse(Z,this);else return Z}}),T=v.kdf={},k=T.OpenSSL={execute:function(Z,K,A,D,m){if(!D)D=I.random(8);if(!m)var x=R.create({keySize:K+A}).compute(Z,D);else var x=R.create({keySize:K+A,hasher:m}).compute(Z,D);var l=I.create(x.words.slice(K),A*4);return x.sigBytes=K*4,G.create({key:x,iv:l,salt:D})}},M=H.PasswordBasedCipher=B.extend({cfg:B.cfg.extend({kdf:k}),encrypt:function(Z,K,A,D){D=this.cfg.extend(D);var m=D.kdf.execute(A,Z.keySize,Z.ivSize,D.salt,D.hasher);D.iv=m.iv;var x=B.encrypt.call(this,Z,K,m.key,D);return x.mixIn(m),x},decrypt:function(Z,K,A,D){D=this.cfg.extend(D),K=this._parse(K,D.format);var m=D.kdf.execute(A,Z.keySize,Z.ivSize,K.salt,D.hasher);D.iv=m.iv;var x=B.decrypt.call(this,Z,K,m.key,D);return x}})}()})});var IY=p((YY,uY)=>{(function(Y,$,v){if(typeof YY==="object")uY.exports=YY=$(h(),QY(),ZY(),VY(),XY());else if(typeof define==="function"&&define.amd)define(["./core","./enc-base64","./md5","./evpkdf","./cipher-core"],$);else $(Y.CryptoJS)})(YY,function(Y){return function(){var $=Y,v=$.lib,H=v.BlockCipher,g=$.algo,I=[],C=[],Q=[],U=[],O=[],J=[],R=[],F=[],z=[],W=[];(function(){var q=[];for(var E=0;E<256;E++)if(E<128)q[E]=E<<1;else q[E]=E<<1^283;var j=0,G=0;for(var E=0;E<256;E++){var X=G^G<<1^G<<2^G<<3^G<<4;X=X>>>8^X&255^99,I[j]=X,C[X]=j;var w=q[j],B=q[w],T=q[B],k=q[X]*257^X*16843008;Q[j]=k<<24|k>>>8,U[j]=k<<16|k>>>16,O[j]=k<<8|k>>>24,J[j]=k;var k=T*16843009^B*65537^w*257^j*16843008;if(R[X]=k<<24|k>>>8,F[X]=k<<16|k>>>16,z[X]=k<<8|k>>>24,W[X]=k,!j)j=G=1;else j=w^q[q[q[T^w]]],G^=q[q[G]]}})();var n=[0,1,2,4,8,16,32,64,128,27,54],u=g.AES=H.extend({_doReset:function(){var q;if(this._nRounds&&this._keyPriorReset===this._key)return;var E=this._keyPriorReset=this._key,j=E.words,G=E.sigBytes/4,X=this._nRounds=G+6,w=(X+1)*4,B=this._keySchedule=[];for(var T=0;T<w;T++)if(T<G)B[T]=j[T];else{if(q=B[T-1],!(T%G))q=q<<8|q>>>24,q=I[q>>>24]<<24|I[q>>>16&255]<<16|I[q>>>8&255]<<8|I[q&255],q^=n[T/G|0]<<24;else if(G>6&&T%G==4)q=I[q>>>24]<<24|I[q>>>16&255]<<16|I[q>>>8&255]<<8|I[q&255];B[T]=B[T-G]^q}var k=this._invKeySchedule=[];for(var M=0;M<w;M++){var T=w-M;if(M%4)var q=B[T];else var q=B[T-4];if(M<4||T<=4)k[M]=q;else k[M]=R[I[q>>>24]]^F[I[q>>>16&255]]^z[I[q>>>8&255]]^W[I[q&255]]}},encryptBlock:function(q,E){this._doCryptBlock(q,E,this._keySchedule,Q,U,O,J,I)},decryptBlock:function(q,E){var j=q[E+1];q[E+1]=q[E+3],q[E+3]=j,this._doCryptBlock(q,E,this._invKeySchedule,R,F,z,W,C);var j=q[E+1];q[E+1]=q[E+3],q[E+3]=j},_doCryptBlock:function(q,E,j,G,X,w,B,T){var k=this._nRounds,M=q[E]^j[0],Z=q[E+1]^j[1],K=q[E+2]^j[2],A=q[E+3]^j[3],D=4;for(var m=1;m<k;m++){var x=G[M>>>24]^X[Z>>>16&255]^w[K>>>8&255]^B[A&255]^j[D++],l=G[Z>>>24]^X[K>>>16&255]^w[A>>>8&255]^B[M&255]^j[D++],S=G[K>>>24]^X[A>>>16&255]^w[M>>>8&255]^B[Z&255]^j[D++],V=G[A>>>24]^X[M>>>16&255]^w[Z>>>8&255]^B[K&255]^j[D++];M=x,Z=l,K=S,A=V}var x=(T[M>>>24]<<24|T[Z>>>16&255]<<16|T[K>>>8&255]<<8|T[A&255])^j[D++],l=(T[Z>>>24]<<24|T[K>>>16&255]<<16|T[A>>>8&255]<<8|T[M&255])^j[D++],S=(T[K>>>24]<<24|T[A>>>16&255]<<16|T[M>>>8&255]<<8|T[Z&255])^j[D++],V=(T[A>>>24]<<24|T[M>>>16&255]<<16|T[Z>>>8&255]<<8|T[K&255])^j[D++];q[E]=x,q[E+1]=l,q[E+2]=S,q[E+3]=V},keySize:8});$.AES=H._createHelper(u)}(),Y.AES})});var DY=p((qY,wY)=>{(function(Y,$){if(typeof qY==="object")wY.exports=qY=$(h());else if(typeof define==="function"&&define.amd)define(["./core"],$);else $(Y.CryptoJS)})(qY,function(Y){return Y.enc.Utf8})});var PY=d(IY(),1),gY=d(DY(),1);import{env as mY}from"@stacksjs/env";function Rq(Y){let $=mY.APP_KEY;if(!$)throw new Error("APP_KEY is not defined");return PY.default.encrypt(Y,$).toString()}function Aq(Y){let $=mY.APP_KEY;if(!$)throw new Error("APP_KEY is not defined");return PY.default.decrypt(Y,$).toString(gY.default)}var oY=d(ZY(),1);import{hashing as i}from"@stacksjs/config";var _=typeof Buffer==="function",xY=typeof TextDecoder==="function"?new TextDecoder:void 0,nY=typeof TextEncoder==="function"?new TextEncoder:void 0;var f=Array.prototype.slice.call("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="),$Y=((Y)=>{let $={};return Y.forEach((v,H)=>$[v]=H),$})(f),qq=/^(?:[A-Za-z\d+\/]{4})*?(?:[A-Za-z\d+\/]{2}(?:==)?|[A-Za-z\d+\/]{3}=?)?$/,b=String.fromCharCode.bind(String),kY=typeof Uint8Array.from==="function"?Uint8Array.from.bind(Uint8Array):(Y)=>new Uint8Array(Array.prototype.slice.call(Y,0)),MY=(Y)=>Y.replace(/=/g,"").replace(/[+\/]/g,($)=>$=="+"?"-":"_"),lY=(Y)=>Y.replace(/[^A-Za-z0-9\+\/]/g,""),bY=(Y)=>{let $,v,H,g,I="",C=Y.length%3;for(let Q=0;Q<Y.length;){if((v=Y.charCodeAt(Q++))>255||(H=Y.charCodeAt(Q++))>255||(g=Y.charCodeAt(Q++))>255)throw new TypeError("invalid character found");$=v<<16|H<<8|g,I+=f[$>>18&63]+f[$>>12&63]+f[$>>6&63]+f[$&63]}return C?I.slice(0,C-3)+"===".substring(C):I},KY=typeof btoa==="function"?(Y)=>btoa(Y):_?(Y)=>Buffer.from(Y,"binary").toString("base64"):bY,NY=_?(Y)=>Buffer.from(Y).toString("base64"):(Y)=>{let v=[];for(let H=0,g=Y.length;H<g;H+=4096)v.push(b.apply(null,Y.subarray(H,H+4096)));return KY(v.join(""))},EY=(Y,$=!1)=>$?MY(NY(Y)):NY(Y),$q=(Y)=>{if(Y.length<2){var $=Y.charCodeAt(0);return $<128?Y:$<2048?b(192|$>>>6)+b(128|$&63):b(224|$>>>12&15)+b(128|$>>>6&63)+b(128|$&63)}else{var $=65536+(Y.charCodeAt(0)-55296)*1024+(Y.charCodeAt(1)-56320);return b(240|$>>>18&7)+b(128|$>>>12&63)+b(128|$>>>6&63)+b(128|$&63)}},Eq=/[\uD800-\uDBFF][\uDC00-\uDFFFF]|[^\x00-\x7F]/g,SY=(Y)=>Y.replace(Eq,$q),CY=_?(Y)=>Buffer.from(Y,"utf8").toString("base64"):nY?(Y)=>NY(nY.encode(Y)):(Y)=>KY(SY(Y)),y=(Y,$=!1)=>$?MY(CY(Y)):CY(Y),BY=(Y)=>y(Y,!0),Qq=/[\xC0-\xDF][\x80-\xBF]|[\xE0-\xEF][\x80-\xBF]{2}|[\xF0-\xF7][\x80-\xBF]{3}/g,Zq=(Y)=>{switch(Y.length){case 4:var $=(7&Y.charCodeAt(0))<<18|(63&Y.charCodeAt(1))<<12|(63&Y.charCodeAt(2))<<6|63&Y.charCodeAt(3),v=$-65536;return b((v>>>10)+55296)+b((v&1023)+56320);case 3:return b((15&Y.charCodeAt(0))<<12|(63&Y.charCodeAt(1))<<6|63&Y.charCodeAt(2));default:return b((31&Y.charCodeAt(0))<<6|63&Y.charCodeAt(1))}},pY=(Y)=>Y.replace(Qq,Zq),hY=(Y)=>{if(Y=Y.replace(/\s+/g,""),!qq.test(Y))throw new TypeError("malformed base64.");Y+="==".slice(2-(Y.length&3));let $,v="",H,g;for(let I=0;I<Y.length;)$=$Y[Y.charAt(I++)]<<18|$Y[Y.charAt(I++)]<<12|(H=$Y[Y.charAt(I++)])<<6|(g=$Y[Y.charAt(I++)]),v+=H===64?b($>>16&255):g===64?b($>>16&255,$>>8&255):b($>>16&255,$>>8&255,$&255);return v},jY=typeof atob==="function"?(Y)=>atob(lY(Y)):_?(Y)=>Buffer.from(Y,"base64").toString("binary"):hY,yY=_?(Y)=>kY(Buffer.from(Y,"base64")):(Y)=>kY(jY(Y).split("").map(($)=>$.charCodeAt(0))),_Y=(Y)=>yY(dY(Y)),Vq=_?(Y)=>Buffer.from(Y,"base64").toString("utf8"):xY?(Y)=>xY.decode(yY(Y)):(Y)=>pY(jY(Y)),dY=(Y)=>lY(Y.replace(/[-_]/g,($)=>$=="-"?"+":"/")),LY=(Y)=>Vq(dY(Y)),Dq=(Y)=>{if(typeof Y!=="string")return!1;let $=Y.replace(/\s+/g,"").replace(/={0,2}$/,"");return!/[^\s0-9a-zA-Z\+/]/.test($)||!/[^\s0-9a-zA-Z\-_]/.test($)},fY=(Y)=>{return{value:Y,enumerable:!1,writable:!0,configurable:!0}},iY=function(){let Y=($,v)=>Object.defineProperty(String.prototype,$,fY(v));Y("fromBase64",function(){return LY(this)}),Y("toBase64",function($){return y(this,$)}),Y("toBase64URI",function(){return y(this,!0)}),Y("toBase64URL",function(){return y(this,!0)}),Y("toUint8Array",function(){return _Y(this)})},cY=function(){let Y=($,v)=>Object.defineProperty(Uint8Array.prototype,$,fY(v));Y("toBase64",function($){return EY(this,$)}),Y("toBase64URI",function(){return EY(this,!0)}),Y("toBase64URL",function(){return EY(this,!0)})},Pq=()=>{iY(),cY()},GY={version:"3.7.7",VERSION:"3.7.7",atob:jY,atobPolyfill:hY,btoa:KY,btoaPolyfill:bY,fromBase64:LY,toBase64:y,encode:y,encodeURI:BY,encodeURL:BY,utob:SY,btou:pY,decode:LY,isValid:Dq,fromUint8Array:EY,toUint8Array:_Y,extendString:iY,extendUint8Array:cY,extendBuiltins:Pq};async function Xq(Y,$){if($?.algorithm==="argon2")return await Lq(Y,{type:"argon2id"});if($?.algorithm==="bcrypt")return await Nq(Y);if($?.algorithm==="base64")return Gq(Y);throw new Error("Unsupported algorithm")}async function uq(Y,$,v){if(v==="argon2")return await Kq(Y,$);if(v==="bcrypt")return await jq(Y,$);if(v==="base64")return Jq(Y,$);throw new Error("Unsupported algorithm")}async function Nq(Y){if(!i.bcrypt)throw new Error("Bcrypt hashing is not configured");return await Bun.password.hash(Y,{algorithm:"bcrypt",cost:i.bcrypt.cost})}async function Lq(Y,$){if(!i.argon2)throw new Error("Argon2 hashing is not configured");return await Bun.password.hash(Y,{algorithm:$?.type||"argon2id",memoryCost:i.argon2.memory,timeCost:i.argon2.time})}async function Kq(Y,$){return await Bun.password.verify(Y,$)}async function jq(Y,$){return await Bun.password.verify(Y,$)}function Gq(Y){return GY.encode(Y)}function Jq(Y,$){return GY.decode($)===Y}function Iq(Y){return oY.default(Y)}var rY=d(QY(),1),aY=d(DY(),1);import{getRandomValues as Fq}from"node:crypto";function gq(){let Y=Fq(new Uint8Array(32)),$=aY.default.parse(Y.toString());return`base64:${rY.default.stringify($)}`}export{uq as verifyHash,Iq as md5Encode,Xq as makeHash,gq as generateAppKey,Rq as encrypt,Aq as decrypt,jq as bcryptVerify,Nq as bcryptEncode,Jq as base64Verify,Gq as base64Encode,Kq as argon2Verify,Lq as argon2Encode};
|
|
2
|
+
var T=import.meta.require;import{config as Z}from"@stacksjs/config";async function N(n,y,c=256){let t=new TextEncoder,r=await crypto.subtle.importKey("raw",t.encode(n),{name:"PBKDF2"},!1,["deriveKey"]);return await crypto.subtle.deriveKey({name:"PBKDF2",salt:y,iterations:1e5,hash:"SHA-256"},r,{name:"AES-GCM",length:c},!1,["encrypt","decrypt"])}async function $(n,y,c){let t=c?.algorithm||"AES-GCM",r=c?.keyLength||256,w=c?.iv||crypto.getRandomValues(new Uint8Array(12)),B=crypto.getRandomValues(new Uint8Array(16)),U=await N(y,B,r),K=new TextEncoder,V=await crypto.subtle.encrypt({name:t,iv:w},U,K.encode(n)),A=new Uint8Array(B.length+w.length+V.byteLength);return A.set(B,0),A.set(w,B.length),A.set(new Uint8Array(V),B.length+w.length),{encrypted:Buffer.from(A).toString("base64"),iv:Buffer.from(w).toString("base64"),algorithm:t}}async function J(n,y,c="AES-GCM"){let t=Buffer.from(n,"base64"),r=t.slice(0,16),w=t.slice(16,28),B=t.slice(28),U=await N(y,r),K=await crypto.subtle.decrypt({name:c,iv:w},U,B);return new TextDecoder().decode(K)}function _(n){return Buffer.from(n,"utf-8").toString("base64")}function O(n){return Buffer.from(n,"base64").toString("utf-8")}function C(n,y){let c=y?.algorithm||"sha256",t=y?.encoding||"hex",r=new Bun.CryptoHasher(c);return r.update(n),r.digest(t)}function Q(n,y="hex"){return C(n,{algorithm:"md5",encoding:y})}async function E(n,y){let c=y?.algorithm||"bcrypt";if(c==="bcrypt")return await Bun.password.hash(n,{algorithm:"bcrypt",cost:y?.cost||10});return await Bun.password.hash(n,{algorithm:c,memoryCost:y?.memoryCost||65536,timeCost:y?.timeCost||3})}async function P(n,y){return await Bun.password.verify(n,y)}function X(n=32){let y=crypto.getRandomValues(new Uint8Array(n));return`base64:${Buffer.from(y).toString("base64")}`}async function v(n,y){if(!n&&n!=="")throw Error("encrypt() requires a string message");let c=y||Z.app.key;if(!c)throw Error("APP_KEY is not defined");return(await $(n,c)).encrypted}async function d(n,y){if(!n)throw Error("decrypt() requires a non-empty encrypted string");let c=y||Z.app.key;if(!c)throw Error("APP_KEY is not defined");return await J(n,c)}import{timingSafeEqual as F}from"crypto";var D=null;function R(){if(D)return D;try{let{hashing:n}=T("@stacksjs/config");return D=n||{},D}catch{return console.warn("[Security] Failed to load hashing config, using defaults"),D={driver:"bcrypt",bcrypt:{rounds:12},argon2:{memory:65536,time:2}},D}}function j(n){if(!n||typeof n!=="string")return"unknown";if(n.startsWith("$2a$")||n.startsWith("$2b$")||n.startsWith("$2y$"))return"bcrypt";if(n.startsWith("$argon2id$"))return"argon2id";if(n.startsWith("$argon2i$"))return"argon2i";if(n.startsWith("$argon2d$"))return"argon2d";return"unknown"}function M(n){let y=j(n),c={};if(y==="bcrypt"){let t=n.match(/^\$2[aby]\$(\d{2})\$/);if(t&&t[1]!==void 0)c.rounds=Number.parseInt(t[1],10)}else if(y==="argon2id"||y==="argon2i"||y==="argon2d"){let t=n.match(/v=(\d+)/),r=n.match(/m=(\d+)/),w=n.match(/t=(\d+)/),B=n.match(/p=(\d+)/);if(t&&t[1]!==void 0)c.version=Number.parseInt(t[1],10);if(r&&r[1]!==void 0)c.memory=Number.parseInt(r[1],10);if(w&&w[1]!==void 0)c.rounds=Number.parseInt(w[1],10);if(B&&B[1]!==void 0)c.parallelism=Number.parseInt(B[1],10)}return{algorithm:y,options:c}}function s(n,y){let c=M(n),t=R(),r=y?.algorithm||t.driver||"bcrypt",w=(K)=>{if(K==="argon2")return"argon2id";return K},B=w(c.algorithm),U=w(r);if(B!==U)return!0;if(B==="bcrypt"){let K=y?.rounds||t.bcrypt?.rounds||10;if(c.options.rounds!==K)return!0}if(B.startsWith("argon2")){let K=y?.memory||t.argon2?.memory||65536,V=y?.time||t.argon2?.time||2;if(c.options.memory!==K||c.options.rounds!==V)return!0}return!1}async function i(n,y){let c=R(),t=y?.algorithm||c.driver||"bcrypt";if(t==="bcrypt")return await q(n,y?.rounds);if(t==="argon2"||t==="argon2id"||t==="argon2i"||t==="argon2d")return await m(n,{type:t==="argon2"?"argon2id":t,memory:y?.memory,time:y?.time});throw Error(`Unsupported hashing algorithm: ${t}`)}async function h(n,y){if(!n||!y)return!1;if(j(y)==="unknown")try{return await P(n,y)}catch{return!1}return await P(n,y)}async function q(n,y){let c=R(),t=y||c.bcrypt?.rounds||12;return await E(n,{algorithm:"bcrypt",cost:t})}async function m(n,y){let c=R(),t=y?.type||"argon2id",r=y?.memory||c.argon2?.memory||65536,w=y?.time||c.argon2?.time||2;return await E(n,{algorithm:t,memoryCost:r,timeCost:w})}async function a(n,y){return await P(n,y)}async function nn(n,y){return await P(n,y)}function yn(n,y){let c=O(y),t=Buffer.from(c),r=Buffer.from(n);if(t.length!==r.length)return!1;return F(t,r)}function cn(n){return Q(n)}function tn(n,y){let c=Buffer.from(n),t=Buffer.from(y);if(c.length!==t.length)return F(c,c),!1;return F(c,t)}function Bn(){return X(32)}import{createHmac as u,timingSafeEqual as z}from"crypto";class f extends Error{reason;constructor(n,y="mismatch"){super(n);this.name="InvalidWebhookSignature",this.reason=y}}function G(n){if(!/^[0-9a-f]*$/i.test(n)||n.length%2!==0)throw new f("Signature is not valid hex","malformed");return Buffer.from(n,"hex")}function L(n,y){if(n.length!==y.length)return z(n,n),!1;return z(n,y)}function Y(n,y,c){return u(c,n).update(y).digest()}function H(n){let y=n.split(","),c=Number.NaN,t=[];for(let r of y){let w=r.indexOf("=");if(w===-1)continue;let B=r.slice(0,w).trim(),U=r.slice(w+1).trim();if(B==="t")c=Number.parseInt(U,10);else if(B==="v1")t.push(U)}if(!Number.isFinite(c)||t.length===0)throw new f("Stripe-Signature header is malformed","malformed");return{timestamp:c,signatures:t}}function p(n,y,c,t={}){if(!n)throw new f("Stripe webhook secret is empty","missing");if(!y)throw new f("Stripe-Signature header is missing","missing");let{timestamp:r,signatures:w}=H(y),B=t.toleranceSeconds??300;if(Math.floor((t.now??Date.now())/1000)-r>B)throw new f("Stripe webhook timestamp is outside tolerance window","expired");let K=typeof c==="string"?c:c.toString("utf8"),V=Y(n,`${r}.${K}`,"sha256");for(let A of w){let x;try{x=G(A)}catch{continue}if(L(V,x))return!0}throw new f("Stripe webhook signature did not match","mismatch")}function S(n,y,c){if(!n)throw new f("GitHub webhook secret is empty","missing");if(!y)throw new f("X-Hub-Signature-256 header is missing","missing");let t="sha256=";if(!y.startsWith(t))throw new f("X-Hub-Signature-256 has wrong algorithm prefix","malformed");let r=G(y.slice(t.length)),w=Y(n,c,"sha256");if(!L(w,r))throw new f("GitHub webhook signature did not match","mismatch");return!0}function W(n,y,c,t="sha256"){if(!n)throw new f("HMAC secret is empty","missing");if(!c)throw new f("Signature header is missing","missing");let r=c.indexOf("="),w=r!==-1&&/^[a-z0-9]+$/i.test(c.slice(0,r))?c.slice(r+1):c,B=G(w),U=Y(n,y,t);if(!L(U,B))throw new f("HMAC signature did not match","mismatch");return!0}function Un(n,y,c,t,r={}){switch(n){case"stripe":return p(y,c,t,r);case"github":return S(y,c,t);case"generic":return W(y,t,c,r.algorithm??"sha256");default:throw new f(`Unknown webhook provider: ${String(n)}`,"malformed")}}export{Un as verifyWebhook,p as verifyStripe,W as verifyHmac,h as verifyHash,S as verifyGithub,tn as timingSafeEqualString,s as needsRehash,cn as md5Encode,i as makeHash,i as make,M as info,s as hashNeedsRehash,i as hashMake,M as hashInfo,j as hashDetectAlgorithm,h as hashCheck,Bn as generateAppKey,v as encrypt,j as detectAlgorithm,d as decrypt,h as check,nn as bcryptVerify,q as bcryptEncode,yn as base64Verify,_ as base64Encode,a as argon2Verify,m as argon2Encode,f as InvalidWebhookSignature};
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import { base64Encode } from 'ts-security-crypto';
|
|
2
|
+
/**
|
|
3
|
+
* Detect the hashing algorithm from a hash string
|
|
4
|
+
* Laravel-compatible hash detection
|
|
5
|
+
*/
|
|
6
|
+
export declare function detectAlgorithm(hash: string): HashAlgorithm | 'unknown';
|
|
7
|
+
/**
|
|
8
|
+
* Extract information from a hash string
|
|
9
|
+
* Similar to Laravel's Hash::info()
|
|
10
|
+
*/
|
|
11
|
+
export declare function info(hash: string): HashInfo;
|
|
12
|
+
/**
|
|
13
|
+
* Check if a hash needs to be rehashed
|
|
14
|
+
* Similar to Laravel's Hash::needsRehash()
|
|
15
|
+
*
|
|
16
|
+
* Returns true if:
|
|
17
|
+
* - The algorithm doesn't match the configured default
|
|
18
|
+
* - The cost/rounds don't match the configured values
|
|
19
|
+
*/
|
|
20
|
+
export declare function needsRehash(hash: string, options?: HashMakeOptions): boolean;
|
|
21
|
+
/**
|
|
22
|
+
* Hash a value using the configured or specified algorithm
|
|
23
|
+
* Similar to Laravel's Hash::make()
|
|
24
|
+
*/
|
|
25
|
+
export declare function make(value: string, options?: HashMakeOptions): Promise<string>;
|
|
26
|
+
/**
|
|
27
|
+
* Verify a value against a hash
|
|
28
|
+
* Similar to Laravel's Hash::check()
|
|
29
|
+
*
|
|
30
|
+
* Auto-detects the algorithm from the hash format
|
|
31
|
+
*/
|
|
32
|
+
export declare function check(value: string, hash: string): Promise<boolean>;
|
|
33
|
+
/**
|
|
34
|
+
* Encode a password using bcrypt
|
|
35
|
+
* Laravel uses $2y$ prefix, rounds 10-12 by default
|
|
36
|
+
*/
|
|
37
|
+
export declare function bcryptEncode(password: string, rounds?: number): Promise<string>;
|
|
38
|
+
/**
|
|
39
|
+
* Encode a password using Argon2
|
|
40
|
+
*/
|
|
41
|
+
export declare function argon2Encode(password: string, options?: {
|
|
42
|
+
type?: 'argon2id' | 'argon2i' | 'argon2d'
|
|
43
|
+
memory?: number
|
|
44
|
+
time?: number
|
|
45
|
+
}): Promise<string>;
|
|
46
|
+
/**
|
|
47
|
+
* Verify a password against an Argon2 hash
|
|
48
|
+
* @deprecated Use check() instead which auto-detects the algorithm
|
|
49
|
+
*/
|
|
50
|
+
export declare function argon2Verify(password: string, hash: string): Promise<boolean>;
|
|
51
|
+
/**
|
|
52
|
+
* Verify a password against a bcrypt hash
|
|
53
|
+
* @deprecated Use check() instead which auto-detects the algorithm
|
|
54
|
+
*/
|
|
55
|
+
export declare function bcryptVerify(password: string, hash: string): Promise<boolean>;
|
|
56
|
+
/**
|
|
57
|
+
* Verify a password against a base64 encoded string
|
|
58
|
+
* Note: base64 is NOT a secure password hash - only for legacy support
|
|
59
|
+
*/
|
|
60
|
+
export declare function base64Verify(password: string, hash: string): boolean;
|
|
61
|
+
/**
|
|
62
|
+
* Create an MD5 hash (NOT secure for passwords)
|
|
63
|
+
*/
|
|
64
|
+
export declare function md5Encode(password: string): string;
|
|
65
|
+
/**
|
|
66
|
+
* Constant-time string comparison.
|
|
67
|
+
*
|
|
68
|
+
* Use this to compare opaque tokens (CSRF tokens, signed URL signatures,
|
|
69
|
+
* webhook HMACs, API keys). A naive `a === b` compares character-by-
|
|
70
|
+
* character and short-circuits on the first mismatch, so the time the
|
|
71
|
+
* comparison takes leaks information about how many leading characters
|
|
72
|
+
* matched — enough for a remote attacker to brute-force the rest.
|
|
73
|
+
*
|
|
74
|
+
* Strings of different lengths are reported as unequal in constant time
|
|
75
|
+
* so length itself doesn't leak.
|
|
76
|
+
*/
|
|
77
|
+
export declare function timingSafeEqualString(a: string, b: string): boolean;
|
|
78
|
+
/**
|
|
79
|
+
* Options for creating a hash
|
|
80
|
+
*/
|
|
81
|
+
export declare interface HashMakeOptions {
|
|
82
|
+
algorithm?: HashAlgorithm
|
|
83
|
+
rounds?: number
|
|
84
|
+
memory?: number
|
|
85
|
+
time?: number
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* Information about a hashed value
|
|
89
|
+
*/
|
|
90
|
+
export declare interface HashInfo {
|
|
91
|
+
algorithm: HashAlgorithm | 'unknown'
|
|
92
|
+
options: {
|
|
93
|
+
rounds?: number
|
|
94
|
+
memory?: number
|
|
95
|
+
parallelism?: number
|
|
96
|
+
version?: number
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Supported hashing algorithms
|
|
101
|
+
*/
|
|
102
|
+
export type HashAlgorithm = 'bcrypt' | 'argon2' | 'argon2id' | 'argon2i' | 'argon2d';
|
|
103
|
+
// Function-based exports (preferred API)
|
|
104
|
+
export {
|
|
105
|
+
make as hashMake,
|
|
106
|
+
check as hashCheck,
|
|
107
|
+
needsRehash as hashNeedsRehash,
|
|
108
|
+
info as hashInfo,
|
|
109
|
+
detectAlgorithm as hashDetectAlgorithm,
|
|
110
|
+
};
|
|
111
|
+
// Legacy exports for backwards compatibility
|
|
112
|
+
export { make as makeHash, check as verifyHash, base64Encode };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function generateAppKey(): string;
|
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verify a Stripe webhook signature.
|
|
3
|
+
*
|
|
4
|
+
* Stripe signs the concatenation `${timestamp}.${rawBody}` with HMAC-SHA256
|
|
5
|
+
* and includes both the timestamp and signature in the `Stripe-Signature`
|
|
6
|
+
* header. Verification:
|
|
7
|
+
* 1. Parse `t` and `v1=` from the header.
|
|
8
|
+
* 2. Compute HMAC-SHA256(`${t}.${body}`, secret).
|
|
9
|
+
* 3. Compare in constant time against any v1 entry.
|
|
10
|
+
* 4. Reject if `t` is older than `toleranceSeconds` to thwart replay.
|
|
11
|
+
*
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* verifyStripe(secret, request.headers.get('stripe-signature')!, rawBody)
|
|
15
|
+
* ```
|
|
16
|
+
*/
|
|
17
|
+
export declare function verifyStripe(secret: string, signatureHeader: string, body: string | Buffer, options?: VerifyWebhookOptions): true;
|
|
18
|
+
/**
|
|
19
|
+
* Verify a GitHub webhook signature.
|
|
20
|
+
*
|
|
21
|
+
* GitHub's `X-Hub-Signature-256` header is `sha256=<hex>` where the hex value
|
|
22
|
+
* is HMAC-SHA256(rawBody, secret). No timestamp is included — replay
|
|
23
|
+
* protection requires application-level idempotency keys (e.g. `X-GitHub-Delivery`).
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* verifyGithub(secret, request.headers.get('x-hub-signature-256')!, rawBody)
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export declare function verifyGithub(secret: string, signatureHeader: string, body: string | Buffer): true;
|
|
31
|
+
/**
|
|
32
|
+
* Verify a generic HMAC signature where the header is just the hex digest.
|
|
33
|
+
*
|
|
34
|
+
* Useful for custom providers that don't bundle a timestamp or scheme prefix.
|
|
35
|
+
* The signature header may optionally start with the algorithm name and `=`
|
|
36
|
+
* (e.g. `sha256=abc...`) — that prefix is stripped if present.
|
|
37
|
+
*
|
|
38
|
+
* @example
|
|
39
|
+
* ```ts
|
|
40
|
+
* verifyHmac(secret, rawBody, request.headers.get('x-signature')!)
|
|
41
|
+
* verifyHmac(secret, rawBody, sig, 'sha512')
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
export declare function verifyHmac(secret: string, body: string | Buffer, signatureHeader: string, algorithm?: 'sha256' | 'sha512' | 'sha1'): true;
|
|
45
|
+
/**
|
|
46
|
+
* Verify a webhook signature against the named provider.
|
|
47
|
+
*
|
|
48
|
+
* Dispatches to provider-specific helpers — see {@link verifyStripe},
|
|
49
|
+
* {@link verifyGithub}, and {@link verifyHmac}. Throws
|
|
50
|
+
* {@link InvalidWebhookSignature} on any failure (malformed header, expired
|
|
51
|
+
* timestamp, mismatched HMAC, or missing input).
|
|
52
|
+
*
|
|
53
|
+
* @param provider 'stripe' | 'github' | 'generic'
|
|
54
|
+
* @param secret Provider's signing secret (`whsec_...` for Stripe, etc.)
|
|
55
|
+
* @param signature Raw header value as received from the request
|
|
56
|
+
* @param body Raw request body — must be the bytes-on-the-wire, not parsed JSON
|
|
57
|
+
* @param options See {@link VerifyWebhookOptions}
|
|
58
|
+
*
|
|
59
|
+
* @example
|
|
60
|
+
* ```ts
|
|
61
|
+
* import { verifyWebhook, InvalidWebhookSignature } from '@stacksjs/security'
|
|
62
|
+
*
|
|
63
|
+
* try {
|
|
64
|
+
* verifyWebhook('stripe', secret, req.headers.get('stripe-signature')!, rawBody)
|
|
65
|
+
* }
|
|
66
|
+
* catch (e) {
|
|
67
|
+
* if (e instanceof InvalidWebhookSignature)
|
|
68
|
+
* return new Response('Invalid signature', { status: 400 })
|
|
69
|
+
* throw e
|
|
70
|
+
* }
|
|
71
|
+
* ```
|
|
72
|
+
*/
|
|
73
|
+
export declare function verifyWebhook(provider: WebhookProvider, secret: string, signature: string, body: string | Buffer, options?: VerifyWebhookOptions): true;
|
|
74
|
+
/**
|
|
75
|
+
* Options controlling webhook verification behavior.
|
|
76
|
+
*/
|
|
77
|
+
export declare interface VerifyWebhookOptions {
|
|
78
|
+
toleranceSeconds?: number
|
|
79
|
+
algorithm?: 'sha256' | 'sha512' | 'sha1'
|
|
80
|
+
now?: number
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Supported webhook providers with built-in signature schemes.
|
|
84
|
+
*/
|
|
85
|
+
export type WebhookProvider = 'stripe' | 'github' | 'generic';
|
|
86
|
+
/**
|
|
87
|
+
* Thrown when a webhook signature fails verification.
|
|
88
|
+
*
|
|
89
|
+
* Catch this specifically to differentiate signature failures from generic
|
|
90
|
+
* errors. Returning a 400 (rather than 500) on this class is the standard
|
|
91
|
+
* response for failed webhook auth.
|
|
92
|
+
*/
|
|
93
|
+
export declare class InvalidWebhookSignature extends Error {
|
|
94
|
+
readonly reason: 'malformed' | 'expired' | 'mismatch' | 'missing';
|
|
95
|
+
constructor(message: string, reason?: 'malformed' | 'expired' | 'mismatch' | 'missing');
|
|
96
|
+
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/security",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.70.
|
|
4
|
+
"version": "0.70.25",
|
|
5
5
|
"description": "The Stacks framework security.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
|
-
"contributors": [
|
|
7
|
+
"contributors": [
|
|
8
|
+
"Chris Breuer <chris@stacksjs.com>"
|
|
9
|
+
],
|
|
8
10
|
"license": "MIT",
|
|
9
11
|
"funding": "https://github.com/sponsors/chrisbbreuer",
|
|
10
12
|
"homepage": "https://github.com/stacksjs/stacks/tree/main/storage/framework/core/security#readme",
|
|
@@ -16,30 +18,42 @@
|
|
|
16
18
|
"bugs": {
|
|
17
19
|
"url": "https://github.com/stacksjs/stacks/issues"
|
|
18
20
|
},
|
|
19
|
-
"keywords": [
|
|
21
|
+
"keywords": [
|
|
22
|
+
"security",
|
|
23
|
+
"framework",
|
|
24
|
+
"typescript",
|
|
25
|
+
"javascript"
|
|
26
|
+
],
|
|
20
27
|
"exports": {
|
|
21
28
|
".": {
|
|
29
|
+
"bun": "./src/index.ts",
|
|
30
|
+
"types": "./dist/index.d.ts",
|
|
22
31
|
"import": "./dist/index.js"
|
|
23
32
|
},
|
|
24
33
|
"./*": {
|
|
34
|
+
"bun": "./src/*",
|
|
25
35
|
"import": "./dist/*"
|
|
26
36
|
}
|
|
27
37
|
},
|
|
28
38
|
"module": "dist/index.js",
|
|
29
39
|
"types": "dist/index.d.ts",
|
|
30
|
-
"files": [
|
|
40
|
+
"files": [
|
|
41
|
+
"README.md",
|
|
42
|
+
"dist"
|
|
43
|
+
],
|
|
31
44
|
"scripts": {
|
|
32
45
|
"build": "bun build.ts",
|
|
33
46
|
"typecheck": "bun tsc --noEmit",
|
|
34
47
|
"prepublishOnly": "bun run build"
|
|
35
48
|
},
|
|
49
|
+
"dependencies": {
|
|
50
|
+
"ts-security-crypto": "0.0.2"
|
|
51
|
+
},
|
|
36
52
|
"devDependencies": {
|
|
37
|
-
"@stacksjs/config": "0.70.
|
|
38
|
-
"
|
|
39
|
-
"@stacksjs/env": "0.70.
|
|
40
|
-
"@stacksjs/types": "0.70.
|
|
41
|
-
"@stacksjs/validation": "0.70.
|
|
42
|
-
"crypto-js": "^4.2.0",
|
|
43
|
-
"js-base64": "^3.7.7"
|
|
53
|
+
"@stacksjs/config": "0.70.23",
|
|
54
|
+
"better-dx": "^0.2.12",
|
|
55
|
+
"@stacksjs/env": "0.70.23",
|
|
56
|
+
"@stacksjs/types": "0.70.23",
|
|
57
|
+
"@stacksjs/validation": "0.70.23"
|
|
44
58
|
}
|
|
45
59
|
}
|
package/dist/crypt.d.ts
DELETED
package/dist/hash.d.ts
DELETED
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
declare interface MakeOptions {
|
|
2
|
-
algorithm?: 'bcrypt' | 'base64' | 'argon2'
|
|
3
|
-
type?: 'argon2id' | 'argon2i' | 'argon2d'
|
|
4
|
-
}
|
|
5
|
-
declare function make(password: string, options?: MakeOptions): Promise<string>;
|
|
6
|
-
declare type Algorithm = 'bcrypt' | 'base64' | 'argon2'
|
|
7
|
-
|
|
8
|
-
async function verify(password: string, hash: string, algorithm?: Algorithm): Promise<boolean> {
|
|
9
|
-
if (algorithm === 'argon2')
|
|
10
|
-
return await argon2Verify(password, hash)
|
|
11
|
-
if (algorithm === 'bcrypt')
|
|
12
|
-
return await bcryptVerify(password, hash)
|
|
13
|
-
if (algorithm === 'base64')
|
|
14
|
-
return base64Verify(password, hash)
|
|
15
|
-
|
|
16
|
-
throw new Error('Unsupported algorithm')
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export async function bcryptEncode(password: string): Promise<string> {
|
|
20
|
-
if (!hashing.bcrypt)
|
|
21
|
-
throw new Error('Bcrypt hashing is not configured')
|
|
22
|
-
|
|
23
|
-
const bcryptHash = await Bun.password.hash(password, {
|
|
24
|
-
algorithm: 'bcrypt',
|
|
25
|
-
cost: hashing.bcrypt.cost,
|
|
26
|
-
})
|
|
27
|
-
|
|
28
|
-
return bcryptHash
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export async function argon2Encode(
|
|
32
|
-
password: string,
|
|
33
|
-
options?: { type: 'argon2id' | 'argon2i' | 'argon2d' },
|
|
34
|
-
): Promise<string> {
|
|
35
|
-
if (!hashing.argon2)
|
|
36
|
-
throw new Error('Argon2 hashing is not configured')
|
|
37
|
-
|
|
38
|
-
const argon2Hash = await Bun.password.hash(password, {
|
|
39
|
-
algorithm: options?.type || 'argon2id',
|
|
40
|
-
memoryCost: hashing.argon2.memory,
|
|
41
|
-
timeCost: hashing.argon2.time,
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
return argon2Hash
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
export async function argon2Verify(password: string, hash: string): Promise<boolean> {
|
|
48
|
-
return await Bun.password.verify(password, hash)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
export async function bcryptVerify(password: string, hash: string): Promise<boolean> {
|
|
52
|
-
return await Bun.password.verify(password, hash)
|
|
53
|
-
}
|
|
54
|
-
export declare function base64Encode(password: string): string;
|
|
55
|
-
export declare function base64Verify(password: string, hash: string): boolean;
|
|
56
|
-
export declare function md5Encode(password: string): CryptoJS.lib.WordArray;
|
|
57
|
-
|
|
58
|
-
export { make as makeHash, verify as verifyHash }
|
package/dist/index.d.ts
DELETED
package/dist/key.d.ts
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export declare function generateAppKey(): string;
|