UNPKG

hsynchronous

Version:

Hybrid synchronous encryption protocol using NIST approved post-quantum algorithms.

1 lines 4.8 kB
import {b,a,c,d,e}from'./chunk-JP4D3ASY.js';import {kem,sign}from'pqclean';import {randomBytes,createCipheriv,timingSafeEqual,createDecipheriv}from'crypto';var W=kem.supportedAlgorithms,ee=sign.supportedAlgorithms,V=W.map(t=>t.name),Y=ee.map(t=>t.name),M="1.0.1",_="hsynchronous",L="aes-256-gcm",j=32,q=50,z=25,l=128,te={fixedRunTime:true},re={fixedRunTime:true,memoryNonceProtection:true},C=new Set,se=(t="ml-kem-1024",e="falcon-1024")=>b(null,null,function*(){let o=yield kem.generateKeyPair(t),s=yield sign.generateKeyPair(e);return {kemKeyPair:o,sigKeyPair:s}}),ie=t=>b(null,null,function*(){let e=t.kemKeyPair.publicKey.algorithm.name,o=t.sigKeyPair.publicKey.algorithm.name,s=t.kemKeyPair.publicKey.export(),f=t.kemKeyPair.privateKey.export(),y=t.sigKeyPair.publicKey.export(),n=t.sigKeyPair.privateKey.export(),a=[e.length,o.length,s.byteLength,f.byteLength,y.byteLength],i=Buffer.from(a.join(","),"utf8"),r=Buffer.concat([Buffer.from(e,"utf8"),Buffer.from(o,"utf8"),Buffer.from(s),Buffer.from(f),Buffer.from(y),Buffer.from(n)]);return `${_}:${M}:${i.toString("hex")}:${r.toString("hex")}`}),ce=t=>b(null,null,function*(){let[e,o,s,f]=t.split(":");if(e!==_||o!==M)throw new Error(`Unsupported protocol or version: ${e} ${o}`);let y=Buffer.from(s,"hex").toString("utf8").split(",").map(Number),[n,a,i,r,u]=y,c=Buffer.from(f,"hex"),g=c.subarray(0,n).toString("utf8"),m=c.subarray(n,n+a).toString("utf8");if(!V.includes(g))throw new Error(`Unsupported KEM algorithm: ${g}`);if(!Y.includes(m))throw new Error(`Unsupported signature algorithm: ${m}`);let P=c.subarray(n+a,n+a+i),w=c.subarray(n+a+i,n+a+i+r),K=c.subarray(n+a+i+r,n+a+i+r+u),d=c.subarray(n+a+i+r+u),p=new kem.PublicKey(g,P),b=new kem.PrivateKey(g,w),x=new sign.PublicKey(m,K),h=new sign.PrivateKey(m,d);return {kemKeyPair:{publicKey:p,privateKey:b},sigKeyPair:{publicKey:x,privateKey:h}}}),ue=(t,e$1,o,s)=>b(null,null,function*(){let f=performance.now();if(!e$1||!e$1.kemKeyPair||!e$1.sigKeyPair)throw new Error("Call generateKeys() first");if(typeof t!="string")throw new Error("Message must be a string");if(s||(s=randomBytes(l/2).toString("hex")),typeof s!="string")throw new Error("Nonce must be a string");if(s.length>l)throw new Error(`Nonce must be less than ${l} characters`);if(o=a(a({},te),o),!V.includes(e$1.kemKeyPair.publicKey.algorithm.name))throw new Error("Unsupported KEM algorithm");if(!Y.includes(e$1.sigKeyPair.publicKey.algorithm.name))throw new Error("Unsupported signature algorithm");let{key:y,encryptedKey:n}=yield e$1.kemKeyPair.publicKey.generateKey(),a$1=Buffer.from(y),i=Buffer.from(n),r=randomBytes(64),u=Buffer.from(`${e$1.kemKeyPair.publicKey.algorithm.name}-${e$1.sigKeyPair.publicKey.algorithm.name}-${L}-${_}-${M}`,"utf8"),c$1=c(a$1,r,u,j);d(a$1);let m=Date.now().toString().padStart(z,"0"),P=s.padStart(l," "),w=`${t}${m}${P}`,K=randomBytes(12),d$1=createCipheriv(L,c$1,K),p=Buffer.concat([d$1.update(w,"utf8"),d$1.final()]),b=d$1.getAuthTag();d(c$1);let x=Buffer.concat([r,i,p,K,b]),h=yield e$1.sigKeyPair.privateKey.sign(x),v=p.byteLength,E=Buffer.from(h).byteLength,B=Buffer.from(`${v},${E}`,"utf8"),O=Buffer.concat([r,i,K,b,p,Buffer.from(h)]),I=`${B.toString("hex")}.${O.toString("hex")}`,A=e(I,1024);return o.fixedRunTime?yield new Promise(k=>setTimeout(k,q-(performance.now()-f))).then(()=>A):A}),me=(t,e,o)=>b(null,null,function*(){o=a(a({},re),o);let s=performance.now(),[f,y]=t.split("."),n=Buffer.from(f,"hex"),[a$1,i]=n.toString("utf8").split(",").map(Number),r=e.kemKeyPair.publicKey.algorithm.encryptedKeySize,u=Buffer.from(y,"hex"),c$1=u.subarray(0,64),g=u.subarray(64,64+r),m=u.subarray(64+r,64+r+12),P=u.subarray(64+r+12,64+r+12+16),w=u.subarray(64+r+12+16,64+r+12+16+a$1),K=u.subarray(64+r+12+16+a$1),d$1=Buffer.concat([c$1,g,w,m,P]),p=yield e.sigKeyPair.publicKey.verify(d$1,K),b=timingSafeEqual(Buffer.from(p?"":"\0"),Buffer.from(""));if(!p)throw new Error("Invalid signature");if(!b)throw new Error("Signature verification failed due to timing attack protection");let x=Buffer.from(`${e.kemKeyPair.publicKey.algorithm.name}-${e.sigKeyPair.publicKey.algorithm.name}-${L}-${_}-${M}`,"utf8"),h=Buffer.from(yield e.kemKeyPair.privateKey.decryptKey(g)),v=c(h,c$1,x,j);d(h);let E=createDecipheriv(L,v,m);d(v),E.setAuthTag(P);let B=Buffer.concat([E.update(w),E.final()]).toString("utf8"),O=B.slice(-l),I=B.slice(-153,-l),A=B.slice(0,-153),k=new Date(parseInt(I,10)),F=O.trimEnd();if(o.memoryNonceProtection){if(C.has(F))throw new Error("Nonce reuse detected");C.add(F);}let U={message:A,createdAt:k,decryptedAt:new Date,nonce:F};return o.fixedRunTime?yield new Promise(X=>setTimeout(X,q-(performance.now()-s))).then(()=>U):U});export{M as VERSION,me as decrypt,ue as encrypt,ie as exportKeys,se as generateKeys,ce as importKeys,W as supportedKemAlgorithms,ee as supportedSigAlgorithms};