@neabyte/quantum-zkp
Version:
Educational quantum-resistant zero-knowledge proof library for learning and prototyping
1 lines • 5.31 kB
JavaScript
import{createHash,randomBytes,createHmac}from"crypto";export class QuantumCrypto{static VERSION="1.0.0";static generateRandomBytes(t){if(t<=0)throw new Error("Length must be positive");return randomBytes(t)}static generateQuantumSafeChallenge(t){const e=this.getChallengeLength(t);return this.generateRandomBytes(e)}static hash(t,e="sha256"){const r="string"==typeof t?Buffer.from(t,"utf8"):t;return createHash(e).update(r).digest()}static hmac(t,e,r="sha256"){const n="string"==typeof t?Buffer.from(t,"utf8"):t,a="string"==typeof e?Buffer.from(e,"utf8"):e;return createHmac(r,a).update(n).digest()}static generateLargePrime(t){if(t<64)throw new Error("Prime must be at least 64 bits for security");const e=(1n<<BigInt(t))-1n,r=1n<<BigInt(t-1);let n=this.generateRandomBigInt(r,e);for(n%2n==0n&&(n+=1n);!this.millerRabinPrimalityTest(n,40);)n+=2n,n>e&&(n=r);return n}static generateRandomBigInt(t,e){const r=e-t,n=Math.ceil(r.toString(16).length/2),a=this.generateRandomBytes(n);let s=BigInt(`0x${a.toString("hex")}`);return s=s%r+t,s}static isStrongProbablePrime(t,e,r,n){let a=this.modPow(e,r,t);if(1n===a||a===t-1n)return!0;for(let e=1n;e<n;e++){if(a=a*a%t,a===t-1n)return!0;if(1n===a)return!1}return!1}static millerRabinPrimalityTest(t,e=40){if(t<=1n)return!1;if(t<=3n)return!0;if(t%2n==0n)return!1;let r=0n,n=t-1n;for(;n%2n==0n;)n/=2n,r+=1n;for(let a=0;a<e;a++){const e=this.generateRandomBigInt(2n,t-2n);if(!this.isStrongProbablePrime(t,e,n,r))return!1}return!0}static isProbablePrime(t){return this.millerRabinPrimalityTest(t,5)}static modPow(t,e,r){if(1n===r)return 0n;let n=1n;for(t%=r;e>0n;)e%2n==1n&&(n=n*t%r),e>>=1n,t=t*t%r;return n}static createHashChain(t,e){if(e<=0)throw new Error("Chain length must be positive");const r=[];let n=t;for(let t=0;t<e;t++)n=this.hash(n,"sha256"),r.push(n);return r}static combineHashes(t){if(0===t.length)throw new Error("Cannot combine empty hash array");return 1===t.length?t[0]:t.reduce((t,e)=>this.hash(Buffer.concat([t,e]),"sha256"))}static getChallengeLength(t){switch(t){case"lattice":default:return 32;case"hash":return 16;case"multivariate":return 24;case"hybrid":return 40}}static validateParameters(t,e){switch(t){case"lattice":return this.validateLatticeParameters(e);case"hash":return this.validateHashParameters(e);case"multivariate":return this.validateMultivariateParameters(e);case"hybrid":return this.validateHybridParameters(e);default:return!1}}static validateLatticeParameters(t){const{dimension:e,modulus:r}=t;return!("number"!=typeof e||e<128)&&!("bigint"!=typeof r||r<=0n)}static validateHashParameters(t){const{chainLength:e}=t;return!("number"!=typeof e||e<100)}static validateMultivariateParameters(t){const{variables:e,equations:r}=t;return!("number"!=typeof e||e<8)&&!("number"!=typeof r||r<e)}static validateHybridParameters(t){const{algorithms:e}=t;return!(!Array.isArray(e)||e.length<2)&&e.every(t=>["lattice","hash","multivariate"].includes(t))}static bufferToBigInts(t,e){const r=[],n=Math.ceil(t.length/e);for(let a=0;a<e;a++){const e=a*n,s=Math.min(e+n,t.length),i=t.slice(e,s);if(0===i.length){r.push(0n);continue}const o=i.toString("hex").padStart(2*i.length,"0"),h=BigInt(`0x${o}`);r.push(h)}return r}static bigIntsToBuffer(t){const e=t.map(t=>{const e=t.toString(16);return Buffer.from(e.padStart(e.length+e.length%2,"0"),"hex")});return Buffer.concat(e)}static generateLWESample(t,e,r){const n=[];for(let r=0;r<t;r++)n.push(this.generateRandomBigInt(0n,e));const a=this.generateDiscreteGaussianError(r);return{a:n,b:(this.generateRandomBigInt(0n,e)+a)%e}}static generateDiscreteGaussianError(t){const e=Math.max(1e-4,Number(this.generateRandomBigInt(0n,1000n))/1e3),r=Number(this.generateRandomBigInt(0n,1000n))/1e3,n=Math.sqrt(-2*Math.log(e))*Math.cos(2*Math.PI*r);return BigInt(Math.round(Number(t)*n))}static generateRLWEPolynomial(t,e,r){if(t&t-1)throw new Error("Degree must be a power of 2 for RLWE");const n=[];for(let r=0;r<t;r++)n.push(this.generateRandomBigInt(0n,e));for(let a=0;a<t;a++){const t=this.generateDiscreteGaussianError(r);n[a]=(n[a]+t)%e}return n}static polynomialMultiply(t,e,r){const n=t.length,a=new Array(n).fill(0n);for(let s=0;s<n;s++)for(let i=0;i<n;i++){const o=(s+i)%n;a[o]=(a[o]+t[s]*e[i])%r}return a}static generateMultivariateSystem(t,e,r){const n=[];for(let a=0;a<e;a++){const e=[];for(let n=0;n<t;n++){const t=[];for(let e=0;e<=r;e++)t.push(this.generateRandomBigInt(0n,2n**64n));e.push(t)}n.push(e)}return n}static evaluateMultivariatePolynomial(t,e){let r=0n;for(let n=0;n<t.length;n++){let a=1n;for(let r=0;r<t[n].length;r++)r<e.length&&(a*=e[r]**BigInt(r));r+=t[n][0]*a}return r}static generateMerkleTree(t){if(0===t.length)throw new Error("Cannot generate Merkle tree with no leaves");const e=[t];let r=t;for(;r.length>1;){const t=[];for(let e=0;e<r.length;e+=2){const n=r[e],a=e+1<r.length?r[e+1]:n,s=Buffer.concat([n,a]);t.push(this.hash(s,"sha256"))}e.push(t),r=t}return{tree:e,root:r[0]}}static generateMerkleProof(t,e){const r=[];let n=e;for(let e=0;e<t.length-1;e++){const a=n%2==1?n-1:n+1;a<t[e].length&&r.push(t[e][a]),n=Math.floor(n/2)}return r}static verifyMerkleProof(t,e,r,n){let a=t,s=n;for(const t of e){const e=s%2==1?Buffer.concat([t,a]):Buffer.concat([a,t]);a=this.hash(e,"sha256"),s=Math.floor(s/2)}return a.equals(r)}static getVersion(){return this.VERSION}}