├── package.json ├── README.md ├── consts.js ├── utils.js ├── bulletproof_single.js └── bullet_proof_specific_range.js /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "bp1", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "start": "node ./bin/www" 7 | }, 8 | "dependencies": { 9 | "big-integer": "^1.6.26", 10 | "elliptic": "^6.4.0" 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # simple-bulletproof-js 2 | javascript code for one-round,single range-proof bulletproof for *secp256k1* elliptic curve. 3 | 4 | Based on first version of https://eprint.iacr.org/2017/1066. 5 | 6 | **This code is a proof of concept and should not be used in production.** 7 | 8 | **To run**: 1) npm install. 2) node bulletproof_single.js 9 | 10 | **NPM packages**: elliptic, big-integer. 11 | 12 | To configure value and range: (a) change value inside controller() and (b) change bound in Consts.js. 13 | 14 | Verifier should return true if OK. -------------------------------------------------------------------------------- /consts.js: -------------------------------------------------------------------------------- 1 | const BigInteger = require('big-integer'); 2 | 3 | 4 | 5 | //https://github.com/indutny/elliptic/blob/79e2f3769771cbd092c75c740ac45c73a59be688/lib/elliptic/curves.js 6 | // https://en.bitcoin.it/wiki/Secp256k1 7 | // Parameter N in secp256k1 8 | 9 | const q = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141", 16); 10 | const MAXIMUM_NUMBER = new BigInteger("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", 16); 11 | const start=2; 12 | var MAX_RANGE_END= 4294967296 //2^32 13 | var upperBoundNumBits = 32; 14 | module.exports = { 15 | q, 16 | MAXIMUM_NUMBER, 17 | HEX: 16, 18 | upperBoundNumBits, 19 | start, 20 | MAX_RANGE_END 21 | }; -------------------------------------------------------------------------------- /utils.js: -------------------------------------------------------------------------------- 1 | const BigInteger = require('big-integer'); 2 | const Consts = require('./consts'); 3 | const EC = require('elliptic').ec; 4 | 5 | const ec = new EC('secp256k1'); 6 | 7 | 8 | function pickRandom(max = Consts.MAXIMUM_NUMBER,min=0) { 9 | return BigInteger.randBetween(min, max); 10 | } 11 | function turnToBig(number){ 12 | return BigInteger(number) 13 | } 14 | 15 | function pickRandomInRange(min = 0, max = Consts.MAXIMUM_NUMBER) { 16 | return BigInteger.randBetween(min, max); 17 | } 18 | 19 | function generateProbablePrime(maxSize, certainty = 5) { 20 | let random; 21 | 22 | do { 23 | random = pickRandom(maxSize); 24 | } while (random.isProbablePrime(certainty)==false) ; 25 | 26 | return random; 27 | } 28 | 29 | //performs a mod b for bigInteger 30 | // a must be bigInteger 31 | function modulo(a,b) { 32 | while (a.lesser(BigInteger(0))){a=a.add(b);} 33 | const c = a.mod(b); 34 | const d = new BigInteger(c < 0 ? c.add(b) : c); 35 | return d 36 | } 37 | 38 | function moduloMul(A,B,m){ 39 | return modulo(modulo(A,m).multiply(modulo(B,m)),m); 40 | } 41 | function moduloMulq(A,B){ 42 | return modulo(modulo(A,Consts.q).multiply(modulo(B,Consts.q)),Consts.q); 43 | } 44 | function moduloAdd(A,B,m){ 45 | return modulo(modulo(A,m).add(modulo(B,m)),m); 46 | } 47 | function moduloAddq(A,B){ 48 | return modulo(modulo(A,Consts.q).add(modulo(B,Consts.q)),Consts.q); 49 | } 50 | function moduloSub(A,B,m){ 51 | return modulo(modulo(A,m).subtract(modulo(B,m)),m); 52 | } 53 | function moduloSubq(A,B){ 54 | return modulo(modulo(A,Consts.q).subtract(modulo(B,Consts.q)),Consts.q); 55 | } 56 | function subtractBigAndNegate(A,B){ 57 | return A.subtract(B); 58 | 59 | } 60 | function moduloPow(base,exp, mod) { 61 | exp = new BigInteger(exp); 62 | mod = new BigInteger(mod); 63 | if (mod.isZero()) throw new Error("Cannot take modPow with modulus 0"); 64 | var r = BigInteger.one, 65 | base; 66 | //base = this.mod(mod); 67 | while (exp.isPositive()) { 68 | if (base.isZero()) return BigInteger.zero; 69 | if (exp.isOdd()) r = modulo(r.multiply(base),mod); 70 | exp = exp.divide(2); 71 | base = modulo(base.square(),mod); 72 | } 73 | return r; 74 | } 75 | 76 | 77 | module.exports = { 78 | moduloMul, 79 | moduloMulq, 80 | moduloAdd, 81 | moduloAddq, 82 | moduloSub, 83 | moduloSubq, 84 | pickRandom, 85 | generateProbablePrime, 86 | modulo, 87 | moduloPow, 88 | ec, 89 | pickRandomInRange, 90 | turnToBig 91 | }; -------------------------------------------------------------------------------- /bulletproof_single.js: -------------------------------------------------------------------------------- 1 | 2 | /*###############################################################################################*/ 3 | /*################################ Prover ##################################################*/ 4 | /*###############################################################################################*/ 5 | 6 | 7 | 8 | 9 | function rangeBpProver(x1,pedCom1,r0,r1){ 10 | 11 | const crypto = require('crypto'); 12 | const BigInteger = require('big-integer'); 13 | const Consts = require('./consts'); 14 | const utils = require('./utils'); 15 | const pickRandom = utils.pickRandom; 16 | const modulo = utils.modulo; 17 | const moduloPow = utils.moduloPow; 18 | const moduloAddq = utils.moduloAddq; 19 | const moduloSubq = utils.moduloSubq; 20 | const moduloMulq = utils.moduloMulq; 21 | const moduloMul = utils.moduloMul; 22 | 23 | 24 | 25 | const aL = []; 26 | const aR = []; 27 | const SL = []; 28 | const SR = []; 29 | 30 | const alpha = pickRandom(Consts.q); 31 | const rho = pickRandom(Consts.q); 32 | 33 | const gVector = []; 34 | const hVector = []; 35 | var gRand; 36 | var hRand; 37 | const H = utils.ec.g.mul((r0.toString(Consts.HEX))); 38 | let v = 0; 39 | while(v< Consts.upperBoundNumBits){ 40 | gRand = utils.ec.g.x.fromRed().toString(16).concat(BigInteger(v).toString(Consts.HEX)); 41 | hRand = H.x.fromRed().toString(16).concat(BigInteger(v).toString(Consts.HEX)); 42 | gVector[v] = utils.ec.g.mul(modulo(BigInteger(crypto.createHash('sha256').update(gRand).digest('hex'),Consts.HEX),Consts.q).toString(Consts.HEX)); 43 | hVector[v] = H.mul(modulo(BigInteger(crypto.createHash('sha256').update(hRand).digest('hex'),Consts.HEX),Consts.q).toString(Consts.HEX)); 44 | v++; 45 | } 46 | 47 | 48 | var A = H.mul(alpha.toString(Consts.HEX)); 49 | var S = H.mul(rho.toString(Consts.HEX)); 50 | let i = 0; 51 | while(i< Consts.upperBoundNumBits){ 52 | aL[i]=x1.shiftRight(i).mod(2).and(BigInteger(1)); 53 | aR[i]= moduloSubq(aL[i],BigInteger(1)); 54 | A = A.add(gVector[i].mul(aL[i].toString(Consts.HEX))).add(hVector[i].mul(aR[i].toString(Consts.HEX))); 55 | //A = A.add(Q.mul(aL[i].toString(Consts.HEX))).add(Q.mul(aR[i].toString(Consts.HEX))); 56 | SL[i] = pickRandom(Consts.q); 57 | SR[i] = pickRandom(Consts.q); 58 | S = (S).add(gVector[i].mul(SL[i].toString(Consts.HEX))).add(hVector[i].mul(SR[i].toString(Consts.HEX))); 59 | //S = (S).add(Q.mul(SL[i].toString(Consts.HEX))).add(Q.mul(SR[i].toString(Consts.HEX))); 60 | i++; 61 | } 62 | 63 | 64 | const y_str = crypto.createHash('sha256').update(A.x.fromRed().toString(16).concat(S.x.fromRed().toString(16))).digest('hex'); 65 | const z_str = crypto.createHash('sha256').update(A.x.fromRed().toString(16).concat(S.x.fromRed().toString(16).concat(y_str))).digest('hex'); 66 | const y = BigInteger(y_str,Consts.HEX); 67 | const z = BigInteger(z_str,Consts.HEX); 68 | 69 | 70 | const zSquared = moduloPow(z,2,Consts.q); 71 | const zCubed = moduloPow(z,3,Consts.q); 72 | var t0 = modulo(modulo(zSquared,Consts.q).multiply(modulo(x1,Consts.q)),Consts.q); 73 | var t0Part1; 74 | var t0Part2; 75 | var t0Part3; 76 | var t1 = BigInteger(0); 77 | var t1Part1; 78 | var t1Part2; 79 | var t1Part3; 80 | var t1Part4; 81 | var t1Part5; 82 | var t1Part6; 83 | var t1Part7; 84 | var t1Part8; 85 | var t2 = BigInteger(0); 86 | var t2Part1; 87 | var t2Part2; 88 | var t2Part3; 89 | var yi = []; 90 | let s = 0; 91 | while(s< Consts.upperBoundNumBits){ 92 | yi[s] = moduloPow(y,s,Consts.q); 93 | t0Part1 = modulo(modulo(z,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 94 | t0Part2 = modulo(modulo(zSquared,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 95 | t0Part3 = modulo(modulo(zCubed,Consts.q).multiply(moduloPow(BigInteger(2),s,Consts.q)),Consts.q); 96 | t0 = moduloSubq(moduloSubq(moduloAddq(t0,t0Part1),t0Part2),t0Part3); 97 | //t0 = modulo(modulo(modulo(t0.add(t0Part1),Consts.q).subtract(t0Part2),Consts.q).subtract(t0Part3),Consts.q); 98 | //t0 = t0.add(z.multiply(yi[i]).add(zSquared.multiply(yi[i]).multiply(-1)).add(zCubed.multiply(BigInteger(2).pow(i)).multiply(-1))); 99 | t1Part1 = modulo(aR[s].add(z),Consts.q); 100 | t1Part2 = modulo(modulo(t1Part1,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 101 | t1Part3 = modulo(modulo(SL[s],Consts.q).multiply(modulo(t1Part2,Consts.q)),Consts.q); 102 | t1Part4 = moduloSubq(aL[s],z); 103 | //t1Part4 = modulo(aL[i].subtract(z),Consts.q); 104 | t1Part5 = modulo(modulo(SR[s],Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 105 | t1Part6 = modulo(modulo(t1Part4,Consts.q).multiply(modulo(t1Part5,Consts.q)),Consts.q); 106 | t1Part7 = modulo(modulo(zSquared,Consts.q).multiply(moduloPow(BigInteger(2),s,Consts.q)),Consts.q); 107 | t1Part8 = moduloMulq(t1Part7,SL[s]); 108 | t1 = moduloAddq(moduloAddq(moduloAddq(t1,t1Part3),t1Part6),t1Part8); 109 | // t1 = modulo(modulo(t1.add(t1Part3),Consts.q).add(t1Part6),Consts.q); 110 | t2Part1 = modulo(modulo(SR[s],Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 111 | t2Part2 = modulo(modulo(SL[s],Consts.q).multiply(modulo(t2Part1,Consts.q)),Consts.q); 112 | t2 = modulo(t2.add(t2Part2),Consts.q); 113 | //t1 = t1.add((SL[i].multiply((aR[i].add(z)).multiply(yi[i]))).add((aL[i].subtract(z)).multiply(SR[i].add(yi[i])))); 114 | //t2 = t2.add(SL[i].multiply(SR[i].multiply(yi[i]))); 115 | s++; 116 | } 117 | const tau1 = pickRandom(Consts.q); 118 | const tau2 = pickRandom(Consts.q); 119 | const T1 = utils.ec.g.mul(t1.toString(Consts.HEX)).add(H.mul(tau1.toString(Consts.HEX))); 120 | const T2 = utils.ec.g.mul(t2.toString(Consts.HEX)).add(H.mul(tau2.toString(Consts.HEX))); 121 | 122 | //fiat shamir for verifier challenge: 123 | const concatStrings = T1.x.fromRed().toString(16).concat(T2.x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 124 | const temp = crypto.createHash('sha256').update(concatStrings).digest('hex'); 125 | const xFiatShamirChall = modulo(BigInteger(temp,Consts.HEX),Consts.q); 126 | const xFiatShamirChallSquared = moduloPow(xFiatShamirChall, 2,Consts.q); 127 | //(A * B) mod C = (A mod C * B mod C) mod C 128 | const tauPart1 = modulo(modulo(tau1,Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 129 | const tauPart2 = modulo(modulo(tau2,Consts.q).multiply(xFiatShamirChallSquared),Consts.q); 130 | const tauPart3 = modulo(modulo(zSquared,Consts.q).multiply(modulo(r1,Consts.q)),Consts.q); 131 | const tauX = modulo(modulo(tauPart1.add(tauPart2),Consts.q).add(tauPart3),Consts.q); 132 | const miuPart1 = modulo(modulo(rho,Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 133 | const miu = modulo(alpha.add(miuPart1),Consts.q); 134 | var Lp = []; 135 | var LpPart1; 136 | var Rp = []; 137 | var RpPart1; 138 | var RpPart2; 139 | var RpPart3; 140 | var RpPart4; 141 | var tX = BigInteger(0); 142 | var tXPart1; 143 | var j = 0; 144 | while(j< Consts.upperBoundNumBits){ 145 | //(A + B) mod C = (A mod C + B mod C) mod C 146 | LpPart1 = modulo(modulo(SL[j],Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 147 | //Lp[j] = modulo(modulo(aL[j].subtract(z),Consts.q).add(LpPart1),Consts.q); 148 | Lp[j] = moduloAddq(moduloSubq(aL[j],z),LpPart1); 149 | //Lp[j] = aL[j].subtract(z).add(SL[j].multiply(xFiatShamirChall)); 150 | RpPart1 = modulo(modulo(SR[j],Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 151 | RpPart2 = modulo(modulo(zSquared,Consts.q).multiply(moduloPow(BigInteger(2),j,Consts.q)),Consts.q); 152 | RpPart3 = modulo(modulo(aR[j].add(z),Consts.q).add(RpPart1),Consts.q); 153 | RpPart4 = modulo(modulo(yi[j],Consts.q).multiply(modulo(RpPart3,Consts.q)),Consts.q); 154 | Rp[j] = modulo(RpPart4.add(RpPart2),Consts.q); 155 | //Rp[j] = (yi[j].multiply(aR[j].add(z).add(SR[j].multiply(xFiatShamirChall)))).add(zSquared.multiply(BigInteger(2).pow(j))); 156 | tXPart1 = modulo(modulo(Lp[j],Consts.q).multiply(modulo(Rp[j],Consts.q)),Consts.q); 157 | tX = modulo(tX.add(tXPart1),Consts.q); 158 | //tX = tX.add(Lp[j].multiply(Rp[j])); 159 | j++; 160 | } 161 | 162 | const transcript1 = tauX.toString(Consts.HEX).concat(miu.toString(Consts.HEX)).concat(tX.toString(Consts.HEX)); 163 | const NIchallenge1 = crypto.createHash('sha256').update(transcript1).digest('hex'); 164 | const nic1 = modulo(BigInteger(NIchallenge1,Consts.HEX),Consts.q); 165 | 166 | 167 | let k=0; 168 | 169 | var P = utils.ec.g.mul(nic1.toString(Consts.HEX)).mul(tX.toString(Consts.HEX)); 170 | //var P = utils.ec.g.mul(0); 171 | 172 | var hiTag = []; 173 | var yiInv = []; 174 | while(k=1){ 232 | L[j]= utils.ec.g.mul('0'); //init 233 | R[j]=utils.ec.g.mul('0'); //init 234 | cL=BigInteger(0); 235 | cR=BigInteger(0); 236 | i1=0; 237 | 238 | while (i1 354 | var t0 = BigInteger(0); 355 | var t0Part1; 356 | var t0Part2; 357 | var t0Part3; 358 | let j = 0; 359 | while(j< Consts.upperBoundNumBits){ 360 | t0Part1 = modulo(modulo(z,Consts.q).multiply(modulo(yi[j],Consts.q)),Consts.q); 361 | t0Part2 = modulo(modulo(zSquared,Consts.q).multiply(modulo(yi[j],Consts.q)),Consts.q); 362 | t0Part3 = modulo(modulo(zCubed,Consts.q).multiply(moduloPow(BigInteger(2),j,Consts.q)),Consts.q); 363 | //t0 = modulo(modulo(modulo(t0.add(t0Part1),Consts.q).subtract(t0Part2),Consts.q).subtract(t0Part3),Consts.q); 364 | t0 = moduloSubq(moduloSubq(moduloAddq(t0,t0Part1),t0Part2),t0Part3); 365 | j++; 366 | } 367 | 368 | // fiat shamir challenge line 50 369 | const concatStrings = T1.x.fromRed().toString(16).concat(T2.x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 370 | const temp = crypto.createHash('sha256').update(concatStrings).digest('hex'); 371 | const xFiatShamirChall = modulo(BigInteger(temp,Consts.HEX),Consts.q); 372 | const xFiatShamirChallSquared = moduloPow(xFiatShamirChall,2,Consts.q); 373 | 374 | const eq63LeftSide = (utils.ec.g.mul(tX.toString(Consts.HEX))).add(H.mul(tauX.toString(Consts.HEX))); 375 | const eq63RightSide = (utils.ec.g.mul(t0.toString(Consts.HEX))).add(pedCom1.mul(zSquared.toString(Consts.HEX))).add(T1.mul(xFiatShamirChall.toString(Consts.HEX))).add(T2.mul(xFiatShamirChallSquared.toString(Consts.HEX))); 376 | if(eq63LeftSide.x.fromRed().toString(16)!=eq63RightSide.x.fromRed().toString(16)){result10=false;} 377 | if(eq63LeftSide.y.fromRed().toString(16)!=eq63RightSide.y.fromRed().toString(16)){result10=false;} 378 | //inner product proof: 379 | // P 380 | const transcript1 = tauX.toString(Consts.HEX).concat(miu.toString(Consts.HEX)).concat(tX.toString(Consts.HEX)); //33 381 | const NIchallenge1 = crypto.createHash('sha256').update(transcript1).digest('hex'); 382 | const nic1 = BigInteger(NIchallenge1,Consts.HEX); 383 | 384 | 385 | //line 62 : 386 | 387 | var P = utils.ec.g.mul(nic1.toString(Consts.HEX)).mul(tX.toString(Consts.HEX)).add(H.mul(((Consts.q).subtract(miu)).toString(Consts.HEX))) 388 | 389 | P = P.add(A).add(S.mul(xFiatShamirChall.toString(Consts.HEX))); 390 | 391 | 392 | var hExponent = []; 393 | let k = 0; 394 | while(k< Consts.upperBoundNumBits){ 395 | hExponent[k] = moduloAddq(moduloMulq(z,yi[k]),moduloMulq(zSquared,moduloPow(BigInteger(2),k,Consts.q))); 396 | P = P.add(gVector[k].mul(((Consts.q).subtract(z)).toString(Consts.HEX))).add(hiTag[k].mul(hExponent[k].toString(Consts.HEX))); 397 | 398 | k++; 399 | } 400 | 401 | var Ptag = P; 402 | const nPad = Consts.upperBoundNumBits; 403 | var nTag = nPad/2; 404 | var i2; 405 | 406 | var transcript; 407 | var NIchallenge; 408 | var x; 409 | var xinv; 410 | var xSquare; 411 | var xSquareInv; 412 | var gVectorTag= gVector; 413 | var hVectorTag = hiTag; 414 | j = 0; 415 | while(nTag>=1){ 416 | 417 | transcript = L[j].x.fromRed().toString(16).concat(R[j].x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 418 | NIchallenge = crypto.createHash('sha256').update(transcript).digest('hex'); 419 | x = BigInteger(NIchallenge,Consts.HEX); 420 | xinv = x.modInv(Consts.q); 421 | xSquare = moduloPow(x,2,Consts.q); 422 | xSquareInv = xSquare.modInv(Consts.q); 423 | gVector = gVectorTag; 424 | hiTag = hVectorTag; 425 | gVectorTag = []; 426 | hVectorTag = []; 427 | 428 | 429 | i2=0; 430 | while (i2256){console.log("error: upper bound should be <256bits");return;} 480 | if(padSize>0){console.log("error: range works only for powers of 2 for now");return;} 481 | const x1 = pickRandom(BigInteger(2).pow(Consts.upperBoundNumBits)); 482 | const r0 = pickRandom(Consts.q); 483 | const r1 = pickRandom(Consts.q); 484 | const pedCom1 = utils.ec.g.mul(x1.toString(Consts.HEX)).add(utils.ec.g.mul((r0.multiply(r1)).toString(Consts.HEX))); 485 | 486 | const {A,S,T1,T2,tauX,miu,tX,L,R,aTag,bTag} = rangeBpProver(x1,pedCom1,r0,r1); 487 | 488 | 489 | const result10 = rangeBpVerifier(r0,r1,pedCom1,A,S,T1,T2,tauX,miu,tX,L,R,aTag,bTag); 490 | if(result10 == false){} //abort 491 | console.log(result10) 492 | 493 | 494 | } 495 | 496 | 497 | controller() 498 | 499 | 500 | 501 | module.exports = { 502 | controller, 503 | }; -------------------------------------------------------------------------------- /bullet_proof_specific_range.js: -------------------------------------------------------------------------------- 1 | 2 | /*###############################################################################################*/ 3 | /*################################ Prover ##################################################*/ 4 | /*###############################################################################################*/ 5 | 6 | const EC = require('elliptic').ec; 7 | 8 | const ec = new EC('secp256k1'); 9 | 10 | 11 | function rangeBpProver(x1,pedCom1,r0,r1){ 12 | 13 | const crypto = require('crypto'); 14 | const BigInteger = require('big-integer'); 15 | const Consts = require('./consts'); 16 | const utils = require('./utils'); 17 | const pickRandom = utils.pickRandom; 18 | const modulo = utils.modulo; 19 | const moduloPow = utils.moduloPow; 20 | const moduloAddq = utils.moduloAddq; 21 | const moduloSubq = utils.moduloSubq; 22 | const moduloMulq = utils.moduloMulq; 23 | const moduloMul = utils.moduloMul; 24 | 25 | 26 | 27 | const aL = []; 28 | const aR = []; 29 | const SL = []; 30 | const SR = []; 31 | 32 | const alpha = pickRandom(Consts.q); 33 | const rho = pickRandom(Consts.q); 34 | 35 | const gVector = []; 36 | const hVector = []; 37 | var gRand; 38 | var hRand; 39 | const H = utils.ec.g.mul((r0.toString(Consts.HEX))); 40 | let v = 0; 41 | while(v< Consts.upperBoundNumBits){ 42 | gRand = utils.ec.g.x.fromRed().toString(16).concat(BigInteger(v).toString(Consts.HEX)); 43 | hRand = H.x.fromRed().toString(16).concat(BigInteger(v).toString(Consts.HEX)); 44 | gVector[v] = utils.ec.g.mul(modulo(BigInteger(crypto.createHash('sha256').update(gRand).digest('hex'),Consts.HEX),Consts.q).toString(Consts.HEX)); 45 | hVector[v] = H.mul(modulo(BigInteger(crypto.createHash('sha256').update(hRand).digest('hex'),Consts.HEX),Consts.q).toString(Consts.HEX)); 46 | v++; 47 | } 48 | 49 | 50 | var A = H.mul(alpha.toString(Consts.HEX)); 51 | var S = H.mul(rho.toString(Consts.HEX)); 52 | let i = 0; 53 | while(i< Consts.upperBoundNumBits){ 54 | aL[i]=x1.shiftRight(i).mod(2).and(BigInteger(1)); 55 | aR[i]= moduloSubq(aL[i],BigInteger(1)); 56 | A = A.add(gVector[i].mul(aL[i].toString(Consts.HEX))).add(hVector[i].mul(aR[i].toString(Consts.HEX))); 57 | //A = A.add(Q.mul(aL[i].toString(Consts.HEX))).add(Q.mul(aR[i].toString(Consts.HEX))); 58 | SL[i] = pickRandom(Consts.q); 59 | SR[i] = pickRandom(Consts.q); 60 | S = (S).add(gVector[i].mul(SL[i].toString(Consts.HEX))).add(hVector[i].mul(SR[i].toString(Consts.HEX))); 61 | //S = (S).add(Q.mul(SL[i].toString(Consts.HEX))).add(Q.mul(SR[i].toString(Consts.HEX))); 62 | i++; 63 | } 64 | 65 | 66 | const y_str = crypto.createHash('sha256').update(A.x.fromRed().toString(16).concat(S.x.fromRed().toString(16))).digest('hex'); 67 | const z_str = crypto.createHash('sha256').update(A.x.fromRed().toString(16).concat(S.x.fromRed().toString(16).concat(y_str))).digest('hex'); 68 | const y = BigInteger(y_str,Consts.HEX); 69 | const z = BigInteger(z_str,Consts.HEX); 70 | 71 | 72 | const zSquared = moduloPow(z,2,Consts.q); 73 | const zCubed = moduloPow(z,3,Consts.q); 74 | var t0 = modulo(modulo(zSquared,Consts.q).multiply(modulo(x1,Consts.q)),Consts.q); 75 | var t0Part1; 76 | var t0Part2; 77 | var t0Part3; 78 | var t1 = BigInteger(0); 79 | var t1Part1; 80 | var t1Part2; 81 | var t1Part3; 82 | var t1Part4; 83 | var t1Part5; 84 | var t1Part6; 85 | var t1Part7; 86 | var t1Part8; 87 | var t2 = BigInteger(0); 88 | var t2Part1; 89 | var t2Part2; 90 | var t2Part3; 91 | var yi = []; 92 | let s = 0; 93 | while(s< Consts.upperBoundNumBits){ 94 | yi[s] = moduloPow(y,s,Consts.q); 95 | t0Part1 = modulo(modulo(z,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 96 | t0Part2 = modulo(modulo(zSquared,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 97 | t0Part3 = modulo(modulo(zCubed,Consts.q).multiply(moduloPow(BigInteger(2),s,Consts.q)),Consts.q); 98 | t0 = moduloSubq(moduloSubq(moduloAddq(t0,t0Part1),t0Part2),t0Part3); 99 | //t0 = modulo(modulo(modulo(t0.add(t0Part1),Consts.q).subtract(t0Part2),Consts.q).subtract(t0Part3),Consts.q); 100 | //t0 = t0.add(z.multiply(yi[i]).add(zSquared.multiply(yi[i]).multiply(-1)).add(zCubed.multiply(BigInteger(2).pow(i)).multiply(-1))); 101 | t1Part1 = modulo(aR[s].add(z),Consts.q); 102 | t1Part2 = modulo(modulo(t1Part1,Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 103 | t1Part3 = modulo(modulo(SL[s],Consts.q).multiply(modulo(t1Part2,Consts.q)),Consts.q); 104 | t1Part4 = moduloSubq(aL[s],z); 105 | //t1Part4 = modulo(aL[i].subtract(z),Consts.q); 106 | t1Part5 = modulo(modulo(SR[s],Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 107 | t1Part6 = modulo(modulo(t1Part4,Consts.q).multiply(modulo(t1Part5,Consts.q)),Consts.q); 108 | t1Part7 = modulo(modulo(zSquared,Consts.q).multiply(moduloPow(BigInteger(2),s,Consts.q)),Consts.q); 109 | t1Part8 = moduloMulq(t1Part7,SL[s]); 110 | t1 = moduloAddq(moduloAddq(moduloAddq(t1,t1Part3),t1Part6),t1Part8); 111 | // t1 = modulo(modulo(t1.add(t1Part3),Consts.q).add(t1Part6),Consts.q); 112 | t2Part1 = modulo(modulo(SR[s],Consts.q).multiply(modulo(yi[s],Consts.q)),Consts.q); 113 | t2Part2 = modulo(modulo(SL[s],Consts.q).multiply(modulo(t2Part1,Consts.q)),Consts.q); 114 | t2 = modulo(t2.add(t2Part2),Consts.q); 115 | //t1 = t1.add((SL[i].multiply((aR[i].add(z)).multiply(yi[i]))).add((aL[i].subtract(z)).multiply(SR[i].add(yi[i])))); 116 | //t2 = t2.add(SL[i].multiply(SR[i].multiply(yi[i]))); 117 | s++; 118 | } 119 | const tau1 = pickRandom(Consts.q); 120 | const tau2 = pickRandom(Consts.q); 121 | const T1 = utils.ec.g.mul(t1.toString(Consts.HEX)).add(H.mul(tau1.toString(Consts.HEX))); 122 | const T2 = utils.ec.g.mul(t2.toString(Consts.HEX)).add(H.mul(tau2.toString(Consts.HEX))); 123 | 124 | //fiat shamir for verifier challenge: 125 | const concatStrings = T1.x.fromRed().toString(16).concat(T2.x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 126 | const temp = crypto.createHash('sha256').update(concatStrings).digest('hex'); 127 | const xFiatShamirChall = modulo(BigInteger(temp,Consts.HEX),Consts.q); 128 | const xFiatShamirChallSquared = moduloPow(xFiatShamirChall, 2,Consts.q); 129 | //(A * B) mod C = (A mod C * B mod C) mod C 130 | const tauPart1 = modulo(modulo(tau1,Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 131 | const tauPart2 = modulo(modulo(tau2,Consts.q).multiply(xFiatShamirChallSquared),Consts.q); 132 | const tauPart3 = modulo(modulo(zSquared,Consts.q).multiply(modulo(r1,Consts.q)),Consts.q); 133 | const tauX = modulo(modulo(tauPart1.add(tauPart2),Consts.q).add(tauPart3),Consts.q); 134 | const miuPart1 = modulo(modulo(rho,Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 135 | const miu = modulo(alpha.add(miuPart1),Consts.q); 136 | var Lp = []; 137 | var LpPart1; 138 | var Rp = []; 139 | var RpPart1; 140 | var RpPart2; 141 | var RpPart3; 142 | var RpPart4; 143 | var tX = BigInteger(0); 144 | var tXPart1; 145 | var j = 0; 146 | while(j< Consts.upperBoundNumBits){ 147 | //(A + B) mod C = (A mod C + B mod C) mod C 148 | LpPart1 = modulo(modulo(SL[j],Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 149 | //Lp[j] = modulo(modulo(aL[j].subtract(z),Consts.q).add(LpPart1),Consts.q); 150 | Lp[j] = moduloAddq(moduloSubq(aL[j],z),LpPart1); 151 | //Lp[j] = aL[j].subtract(z).add(SL[j].multiply(xFiatShamirChall)); 152 | RpPart1 = modulo(modulo(SR[j],Consts.q).multiply(modulo(xFiatShamirChall,Consts.q)),Consts.q); 153 | RpPart2 = modulo(modulo(zSquared,Consts.q).multiply(moduloPow(BigInteger(2),j,Consts.q)),Consts.q); 154 | RpPart3 = modulo(modulo(aR[j].add(z),Consts.q).add(RpPart1),Consts.q); 155 | RpPart4 = modulo(modulo(yi[j],Consts.q).multiply(modulo(RpPart3,Consts.q)),Consts.q); 156 | Rp[j] = modulo(RpPart4.add(RpPart2),Consts.q); 157 | //Rp[j] = (yi[j].multiply(aR[j].add(z).add(SR[j].multiply(xFiatShamirChall)))).add(zSquared.multiply(BigInteger(2).pow(j))); 158 | tXPart1 = modulo(modulo(Lp[j],Consts.q).multiply(modulo(Rp[j],Consts.q)),Consts.q); 159 | tX = modulo(tX.add(tXPart1),Consts.q); 160 | //tX = tX.add(Lp[j].multiply(Rp[j])); 161 | j++; 162 | } 163 | 164 | const transcript1 = tauX.toString(Consts.HEX).concat(miu.toString(Consts.HEX)).concat(tX.toString(Consts.HEX)); 165 | const NIchallenge1 = crypto.createHash('sha256').update(transcript1).digest('hex'); 166 | const nic1 = modulo(BigInteger(NIchallenge1,Consts.HEX),Consts.q); 167 | 168 | 169 | let k=0; 170 | 171 | var P = utils.ec.g.mul(nic1.toString(Consts.HEX)).mul(tX.toString(Consts.HEX)); 172 | //var P = utils.ec.g.mul(0); 173 | 174 | var hiTag = []; 175 | var yiInv = []; 176 | while(k=1){ 234 | L[j]= utils.ec.g.mul('0'); //init 235 | R[j]=utils.ec.g.mul('0'); //init 236 | cL=BigInteger(0); 237 | cR=BigInteger(0); 238 | i1=0; 239 | 240 | while (i1 356 | var t0 = BigInteger(0); 357 | var t0Part1; 358 | var t0Part2; 359 | var t0Part3; 360 | let j = 0; 361 | while(j< Consts.upperBoundNumBits){ 362 | t0Part1 = modulo(modulo(z,Consts.q).multiply(modulo(yi[j],Consts.q)),Consts.q); 363 | t0Part2 = modulo(modulo(zSquared,Consts.q).multiply(modulo(yi[j],Consts.q)),Consts.q); 364 | t0Part3 = modulo(modulo(zCubed,Consts.q).multiply(moduloPow(BigInteger(2),j,Consts.q)),Consts.q); 365 | //t0 = modulo(modulo(modulo(t0.add(t0Part1),Consts.q).subtract(t0Part2),Consts.q).subtract(t0Part3),Consts.q); 366 | t0 = moduloSubq(moduloSubq(moduloAddq(t0,t0Part1),t0Part2),t0Part3); 367 | j++; 368 | } 369 | 370 | // fiat shamir challenge line 50 371 | const concatStrings = T1.x.fromRed().toString(16).concat(T2.x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 372 | const temp = crypto.createHash('sha256').update(concatStrings).digest('hex'); 373 | const xFiatShamirChall = modulo(BigInteger(temp,Consts.HEX),Consts.q); 374 | const xFiatShamirChallSquared = moduloPow(xFiatShamirChall,2,Consts.q); 375 | 376 | const eq63LeftSide = (utils.ec.g.mul(tX.toString(Consts.HEX))).add(H.mul(tauX.toString(Consts.HEX))); 377 | const eq63RightSide = (utils.ec.g.mul(t0.toString(Consts.HEX))).add(pedCom1.mul(zSquared.toString(Consts.HEX))).add(T1.mul(xFiatShamirChall.toString(Consts.HEX))).add(T2.mul(xFiatShamirChallSquared.toString(Consts.HEX))); 378 | if(eq63LeftSide.x.fromRed().toString(16)!=eq63RightSide.x.fromRed().toString(16)){result10=false;} 379 | if(eq63LeftSide.y.fromRed().toString(16)!=eq63RightSide.y.fromRed().toString(16)){result10=false;} 380 | //inner product proof: 381 | // P 382 | const transcript1 = tauX.toString(Consts.HEX).concat(miu.toString(Consts.HEX)).concat(tX.toString(Consts.HEX)); //33 383 | const NIchallenge1 = crypto.createHash('sha256').update(transcript1).digest('hex'); 384 | const nic1 = BigInteger(NIchallenge1,Consts.HEX); 385 | 386 | 387 | //line 62 : 388 | 389 | var P = utils.ec.g.mul(nic1.toString(Consts.HEX)).mul(tX.toString(Consts.HEX)).add(H.mul(((Consts.q).subtract(miu)).toString(Consts.HEX))) 390 | 391 | P = P.add(A).add(S.mul(xFiatShamirChall.toString(Consts.HEX))); 392 | 393 | 394 | var hExponent = []; 395 | let k = 0; 396 | while(k< Consts.upperBoundNumBits){ 397 | hExponent[k] = moduloAddq(moduloMulq(z,yi[k]),moduloMulq(zSquared,moduloPow(BigInteger(2),k,Consts.q))); 398 | P = P.add(gVector[k].mul(((Consts.q).subtract(z)).toString(Consts.HEX))).add(hiTag[k].mul(hExponent[k].toString(Consts.HEX))); 399 | 400 | k++; 401 | } 402 | 403 | var Ptag = P; 404 | const nPad = Consts.upperBoundNumBits; 405 | var nTag = nPad/2; 406 | var i2; 407 | 408 | var transcript; 409 | var NIchallenge; 410 | var x; 411 | var xinv; 412 | var xSquare; 413 | var xSquareInv; 414 | var gVectorTag= gVector; 415 | var hVectorTag = hiTag; 416 | j = 0; 417 | while(nTag>=1){ 418 | 419 | transcript = L[j].x.fromRed().toString(16).concat(R[j].x.fromRed().toString(16)).concat(H.x.fromRed().toString(16)); 420 | NIchallenge = crypto.createHash('sha256').update(transcript).digest('hex'); 421 | x = BigInteger(NIchallenge,Consts.HEX); 422 | xinv = x.modInv(Consts.q); 423 | xSquare = moduloPow(x,2,Consts.q); 424 | xSquareInv = xSquare.modInv(Consts.q); 425 | gVector = gVectorTag; 426 | hiTag = hVectorTag; 427 | gVectorTag = []; 428 | hVectorTag = []; 429 | 430 | 431 | i2=0; 432 | while (i2256){console.log("error: upper bound should be <256bits");return;} 482 | if(padSize>0){console.log("error: range works only for powers of 2 for now");return;} 483 | const x1 = turnToBig(97) 484 | const start=turnToBig(0) 485 | const end=turnToBig(99) 486 | const x_minus_b=x1.subtract(end).add(turnToBig(Consts.MAX_RANGE_END)) 487 | const r0 = pickRandom(Consts.q) 488 | const r1 = pickRandom(Consts.q) 489 | const r2 =pickRandom(Consts.q,r0) 490 | const r3 = pickRandom(Consts.q,r1) 491 | const difference=x1.subtract(start); 492 | // prover proves that they have x1 493 | const pedCom1 =utils.ec.g.mul(x1.toString(Consts.HEX)).add(utils.ec.g.mul((r2.multiply(r3)).toString(Consts.HEX))); 494 | 495 | const pedComXMinusb=utils.ec.g.mul(x_minus_b.toString(Consts.HEX)).add(utils.ec.g.mul((r2.multiply(r3)).toString(Consts.HEX))); 496 | 497 | //pedcom1-g*a+g*(r0*r1)-(g*(r2*r1)+g*(r0*r3)) 498 | 499 | //verifier would take the original commitment and calulate random diiference and new commitment based on above formula 500 | 501 | 502 | const r1_diff=r2.subtract(r0); 503 | const r2_diff=r3.subtract(r1); 504 | const gstarA=utils.ec.g.mul(start.toString(Consts.HEX)); 505 | const negGstarA=gstarA.neg(gstarA); 506 | const gr0tor1=utils.ec.g.mul((r0.multiply(r1)).toString(Consts.HEX)); 507 | const gr2tor1=utils.ec.g.mul((r2.multiply(r1)).toString(Consts.HEX)); 508 | const gr0tor3=utils.ec.g.mul((r0.multiply(r3).toString(Consts.HEX))) 509 | const sum_gr2tor1=gr2tor1.add(gr0tor3); 510 | const neg_sum_gr2tor1=sum_gr2tor1.neg(sum_gr2tor1) 511 | 512 | //pedcom1-g*a+g*(r0*r1)-(g*(r2*r1)+g*(r0*r3)) 513 | /** 514 | * 515 | * 516 | pedcom1= g*x+g*(r2*r3) 517 | pedcomstart= g*a +g*(r0*r1) 518 | pedcomdiff= g*(x-a) +g*((r2-r0)*(r3-r1)) 519 | g*(x-a) +g*((r2-r0)*(r3-r1)) 520 | g*x-g*a +g*(r2*r3-r2*r1-r0*r3+r0*r1) 521 | g*x -g*a + g*(r2*r3)-g*(r2*r1)- g*(r0*r3) +g*(r0*r1) 522 | 523 | g*x+g*(r2*r3)-g*a+g*(r0*r1)-g*(r2*r1)-g*(r0*r3) 524 | g*x+g*(r2*r3)-g*a+g*(r0*r1)-(g*(r2*r1)+g*(r0*r3)) 525 | pedcom1-g*a+g*(r0*r1)-(g*(r2*r1)+g*(r0*r3)) 526 | */ 527 | const finalpedCom=pedCom1.add(negGstarA).add(gr0tor1).add(neg_sum_gr2tor1) 528 | //first proof to prove that aa",result10) 533 | //second proof to prove that x