public BigInteger combineShares(int x[], Share[] shares) throws Exception { int t = publicInfo.getT(); int n = publicInfo.getN(); BigInteger[] z = this.publicInfo.getInterpolationPoints(); if (x.length != t) { throw new RuntimeException("There must be " + t + " diferent and valid shares"); } for (int i : x) { if (shares[i] == null) { throw new RuntimeException("There must be " + t + " diferent and valid shares"); } } BigInteger q = publicInfo.getGroupPrimeOrder(); BigInteger qm1 = q.subtract(BigInteger.ONE); BigInteger secret = BigInteger.ONE; // System.out.print("PVSSEngine.combineShares: Using shares"); for (int i = 0; i < t; i++) { // iterates over x[i] // System.out.print(" "+x[i]); /* * float lambda = 1; for(int j=0; j<t; j++) { //iterates over x[j] * if(j != i){ lambda = lambda*((float)(x[j]+1)/(float)(x[j]-x[i])); * } } * * secret = secret.multiply(shares[x[i]].getShare() .modPow(BigInteger.valueOf((long)lambda),q)).mod(q); */ BigInteger lambda = BigInteger.ONE; BigInteger lambdadenom = BigInteger.ONE; BigInteger lambdanumer = BigInteger.ONE; BigInteger gcd = BigInteger.ONE; for (int j = 0; j < t; j++) { // iterates over x[j] if (j != i) { // It,s essential that mod is not done here, because of gcd lambdanumer = lambdanumer.multiply(z[x[j]]); lambdadenom = lambdadenom.multiply(z[x[j]].subtract(z[x[i]])); } } // System.out.println("lambdanumer " + lambdanumer + ", lambdadenom " + lambdadenom); gcd = lambdadenom.gcd(lambdanumer); lambdadenom = lambdadenom.divide(gcd); lambdanumer = lambdanumer.divide(gcd); /** Sanity check * */ gcd = lambdadenom.gcd(qm1); // System.out.println("GCD :" + gcd.intValue()); if (gcd.intValue() != 1) { // System.out.println("i :" + i); // System.out.println("lambdanumer " + lambdanumer); // System.out.println("lambdadenom " + lambdadenom); // System.out.println("z array :" + Arrays.toString(z)); // System.out.println("x array :" + Arrays.toString(x)); throw invalidLagrangeCoeff(); } BigInteger invdenom = lambdadenom.modInverse(qm1); lambda = lambdanumer.multiply(invdenom).mod(qm1); // System.out.println("i = " + i + ", lambda = " + lambda + ", lambdanumer " // + lambdanumer + ", lambdadenom " + lambdadenom); secret = secret.multiply(shares[x[i]].getShare().modPow(lambda, q)).mod(q); } /* * BigInteger secret = BigInteger.ONE; * * //System.out.print("PVSSEngine.combineShares: Using shares"); for(int * i=0; i<t; i++){ //iterates over x[i] //System.out.print(" "+x[i]); * * BigInteger lambda2 = BigInteger.valueOf(1); for(int j=0; j<t; j++) { * //iterates over x[j] if(j != i){ * * BigInteger denominator = BigInteger.valueOf(x[j]-x[i]); lambda2 = * lambda2.multiply( BigInteger.valueOf((x[j]+1)).multiply( * denominator.modInverse(q)) ).mod(qm1); } } * * System.out.println("shares[x[i]].getShare() * ="+shares[x[i]].getShare()); System.out.println("Our lambda2 : * "+lambda2); System.out.println("q : "+q); * * BigInteger temp2 = (shares[x[i]].getShare()).modPow(lambda2,q); * System.out.println("temp2 ="+temp2); * * float lambda = 1; for(int j=0; j<t; j++) { //iterates over x[j] if(j * != i){ lambda = lambda*((float)(x[j]+1)/(float)(x[j]-x[i])); } } * * BigInteger temp1 = * shares[x[i]].getShare().modPow(BigInteger.valueOf((long)lambda),q); * System.out.println("lambda : "+lambda); System.out.println("temp1 * ="+temp1); * * System.out.println("q : "+q); * * secret = * secret.multiply(shares[x[i]].getShare().modPow(BigInteger.valueOf((long)lambda),q)).mod(q); } */ // System.out.println("Secret returning from combine share :" + secret); return secret; }