feldmanVSS documention

DKG
tzlil.gon 2016-01-28 13:57:47 +02:00
parent 93240c10f4
commit 8ba55bacd2
5 changed files with 180 additions and 35 deletions

View File

@ -13,43 +13,64 @@ import java.util.Random;
*/ */
public class VerifiableSecretSharing extends SecretSharing { public class VerifiableSecretSharing extends SecretSharing {
private final CyclicGroup<BigInteger> group;
private final BigInteger g; // public generator of group
private final BigInteger[] commitments; private final BigInteger[] commitments;
private final BigInteger g;
/**
* @param group a cyclic group of prime order p.
* it must be chosen such that computing discrete logarithms is hard in this group.
*/
public VerifiableSecretSharing(CyclicGroup<BigInteger> group, int t, int n, BigInteger s, Random random) { public VerifiableSecretSharing(CyclicGroup<BigInteger> group, int t, int n, BigInteger s, Random random) {
super(group, t, n, s, random); super(group.orderUpperBound(), t, n, s, random);
this.group = group;
this.g = group.getGenerator(); this.g = group.getGenerator();
this.commitments = generateCommitments(); this.commitments = generateCommitments();
} }
/**
* @return commitments[i] = g ^ polynomial.coefficients[i]
*/
private BigInteger[] generateCommitments() { private BigInteger[] generateCommitments() {
BigInteger[] coefficients = polynomial.getCoefficients(); BigInteger[] coefficients = polynomial.getCoefficients();
BigInteger[] commitments = new BigInteger[coefficients.length]; BigInteger[] commitments = new BigInteger[coefficients.length];
for (int i = 0 ; i < commitments.length;i++){ for (int i = 0 ; i < commitments.length;i++){
commitments[i] = group.multiply(g,coefficients[i]); //(g ^ coeff[i]) % p commitments[i] = group.multiply(g,coefficients[i]);
} }
return commitments; return commitments;
} }
public BigInteger verify(int i) throws Exception { /**
if(i < 1 || i > n){ * @param i share holder id
throw new Exception(); * @param commitments
} * @param group
*
* @return product of commitments[j] ^ (i ^ j) == g ^ polynomial(i)
*/
public static BigInteger verify(int i,BigInteger[] commitments,CyclicGroup<BigInteger> group) {
BigInteger v = group.zero(); BigInteger v = group.zero();
int power = 1; int power = 1;
for (int j = 0 ; j < commitments.length ; j ++){ for (int j = 0 ; j < commitments.length ; j ++){
v = group.add(v,commitments[i].pow(power)); v = group.add(v,commitments[i].pow(power));
power *=i; power *=i;
} }
return v;
return group.add(group.zero(),v);
} }
public BigInteger getG() { /**
* getter
* @return generator of group
*/
public BigInteger getGenerator() {
return g; return g;
} }
/**
* getter
* @return copy of commitments
*/
public BigInteger[] getCommitments() { public BigInteger[] getCommitments() {
return Arrays.clone(commitments); return Arrays.clone(commitments);
} }

View File

@ -4,19 +4,41 @@ import java.math.BigInteger;
/** /**
* Created by Tzlil on 1/28/2016. * Created by Tzlil on 1/28/2016.
*
* container of lagrange polynomial
*
* can't be constructed, constructor is private
*
* l = (image/divisor)* polynomial
*
* Note : image and divisor stored separately for avoiding lose of information by division
*/ */
class LagrangePolynomial{ class LagrangePolynomial{
public final Polynomial polynomial; public final Polynomial polynomial;
public final BigInteger image; public final BigInteger image;
public final BigInteger divisor; public final BigInteger divisor;
/**
* inner constructor, stores all given parameters
* @param polynomial
* @param image
* @param divisor
*/
private LagrangePolynomial(Polynomial polynomial, BigInteger image, BigInteger divisor) { private LagrangePolynomial(Polynomial polynomial, BigInteger image, BigInteger divisor) {
this.polynomial = polynomial; this.polynomial = polynomial;
this.image = image; this.image = image;
this.divisor = divisor; this.divisor = divisor;
} }
public static LagrangePolynomial[] lagrangePolynomials(Polynomial.Point[] points){ /**
* static method
* @param points array points s.t there are no couple of points that shares the same x value
*
* @return the lagrange polynomials that mach to given points
*
* @throws Exception there exists i != j s.t points[i].x == points[j].x
*/
public static LagrangePolynomial[] lagrangePolynomials(Polynomial.Point[] points) throws Exception {
LagrangePolynomial[] lagrangePolynomials = new LagrangePolynomial[points.length]; LagrangePolynomial[] lagrangePolynomials = new LagrangePolynomial[points.length];
Polynomial[] factors = new Polynomial[points.length]; Polynomial[] factors = new Polynomial[points.length];
for (int i = 0 ; i < factors.length ; i++){ for (int i = 0 ; i < factors.length ; i++){
@ -33,6 +55,8 @@ class LagrangePolynomial{
product = product.mul(factors[j]); product = product.mul(factors[j]);
} }
} }
if(divisor.equals(BigInteger.ZERO))
throw new Exception();
lagrangePolynomials[i] = new LagrangePolynomial(product,points[i].y,divisor); lagrangePolynomials[i] = new LagrangePolynomial(product,points[i].y,divisor);
} }
return lagrangePolynomials; return lagrangePolynomials;

View File

@ -9,27 +9,39 @@ import java.math.BigInteger;
/** /**
* Created by Tzlil on 1/27/2016. * Created by Tzlil on 1/27/2016.
*/ */
public class Polynomial { public class Polynomial implements Comparable<Polynomial> {
protected static final Polynomial ZERO = new Polynomial(new BigInteger[]{BigInteger.ZERO}); // neutral for add
protected static final Polynomial ZERO = new Polynomial(new BigInteger[]{BigInteger.ZERO}); protected static final Polynomial ONE = new Polynomial(new BigInteger[]{BigInteger.ONE}); // neutral for mul
protected static final Polynomial ONE = new Polynomial(new BigInteger[]{BigInteger.ONE});
private final int degree; private final int degree;
private final BigInteger[] coefficients; private final BigInteger[] coefficients;
/**
* constructor
* @param coefficients
* degree set as max index such that coefficients[degree] not equals zero
*/
public Polynomial(BigInteger[] coefficients) { public Polynomial(BigInteger[] coefficients) {
this.degree = coefficients.length - 1; int d = coefficients.length - 1;
while (d > 0 && coefficients[d].equals(BigInteger.ZERO)){
d--;
}
this.degree = d;
this.coefficients = coefficients; this.coefficients = coefficients;
} }
public Polynomial(Polynomial polynomial) {
this.degree = polynomial.getDegree();
this.coefficients = polynomial.getCoefficients();
}
public boolean isEquals(Polynomial other) { @Override
public int compareTo(Polynomial other) {
if (this.degree != other.degree) if (this.degree != other.degree)
return false; return this.degree - other.degree;
return Arrays.areEqual(this.coefficients,other.coefficients); int compare;
for (int i = degree; i >= degree ; i--){
compare = this.coefficients[i].compareTo(other.coefficients[i]);
if (compare != 0){
return compare;
}
}
return 0;
} }
@Override @Override
@ -40,6 +52,11 @@ public class Polynomial {
'}'; '}';
} }
/**
* @param x
* @return sum of coefficients[i] * (x ^ i)
*/
public BigInteger image(BigInteger x){ public BigInteger image(BigInteger x){
BigInteger result = BigInteger.ZERO; BigInteger result = BigInteger.ZERO;
BigInteger power = BigInteger.ONE; BigInteger power = BigInteger.ONE;
@ -50,20 +67,28 @@ public class Polynomial {
return result; return result;
} }
/**
* @param points
* @return polynomial of minimal degree which goes through all points
*/
public static Polynomial interpolation(Point[] points){ public static Polynomial interpolation(Point[] points){
LagrangePolynomial[] l = LagrangePolynomial.lagrangePolynomials(points); LagrangePolynomial[] l = LagrangePolynomial.lagrangePolynomials(points);
// product = product of l[i].divisor
BigInteger product = BigInteger.ONE; BigInteger product = BigInteger.ONE;
for (int i = 0; i < l.length;i++){ for (int i = 0; i < l.length;i++){
product = product.multiply(l[i].divisor); product = product.multiply(l[i].divisor);
} }
// factor[i] = product divided by l[i].divisor = product of l[j].divisor s.t j!=i
BigInteger[] factors = new BigInteger[l.length]; BigInteger[] factors = new BigInteger[l.length];
for (int i = 0; i < l.length;i++){ for (int i = 0; i < l.length;i++){
factors[i] = product.divide(l[i].divisor); factors[i] = product.divide(l[i].divisor);
} }
int degree = l[0].polynomial.degree; int degree = l[0].polynomial.degree;
// coefficients[j] = (sum of l[i].image * factor[i] * l[i].coefficients[j] s.t i!=j) divide by product =
// = sum of l[i].image * l[i].coefficients[j] / l[i].divisor s.t i!=j
BigInteger[] coefficients = new BigInteger[degree + 1]; BigInteger[] coefficients = new BigInteger[degree + 1];
for (int j = 0; j < coefficients.length;j++){ for (int j = 0; j < coefficients.length;j++){
coefficients[j] = BigInteger.ZERO; coefficients[j] = BigInteger.ZERO;
@ -75,6 +100,11 @@ public class Polynomial {
return new Polynomial(coefficients); return new Polynomial(coefficients);
} }
/**
* @param other
* @return new Polynomial of degree max(this degree,other degree) s.t for all x in Z
* new.image(x) = this.image(x) + other.image(x)
*/
public Polynomial add(Polynomial other){ public Polynomial add(Polynomial other){
Polynomial bigger,smaller; Polynomial bigger,smaller;
if(this.degree < other.degree){ if(this.degree < other.degree){
@ -92,6 +122,11 @@ public class Polynomial {
return new Polynomial(coefficients); return new Polynomial(coefficients);
} }
/**
* @param constant
* @return new Polynomial of degree this.degree s.t for all x in Z
* new.image(x) = constant * this.image(x)
*/
public Polynomial mul(BigInteger constant){ public Polynomial mul(BigInteger constant){
BigInteger[] coefficients = this.getCoefficients(); BigInteger[] coefficients = this.getCoefficients();
@ -102,6 +137,11 @@ public class Polynomial {
return new Polynomial(coefficients); return new Polynomial(coefficients);
} }
/**
* @param other
* @return new Polynomial of degree this degree + other degree + 1 s.t for all x in Z
* new.image(x) = this.image(x) * other.image(x)
*/
public Polynomial mul(Polynomial other){ public Polynomial mul(Polynomial other){
BigInteger[] coefficients = new BigInteger[this.degree + other.degree + 1]; BigInteger[] coefficients = new BigInteger[this.degree + other.degree + 1];
@ -116,21 +156,45 @@ public class Polynomial {
} }
/** getter
* @return copy of coefficients
*/
public BigInteger[] getCoefficients() { public BigInteger[] getCoefficients() {
return Arrays.clone(coefficients); return Arrays.clone(coefficients);
} }
/** getter
* @return degree
*/
public int getDegree() { public int getDegree() {
return degree; return degree;
} }
/**
* inner class
* container for (x,y) x from range and y from image of polynomial
*/
public static class Point{ public static class Point{
public final BigInteger x; public final BigInteger x;
public final BigInteger y; public final BigInteger y;
public Point(BigInteger x, BigInteger y) { /**
* constructor
* @param x
* @param polynomial y = polynomial.image(x)
*/
public Point(BigInteger x, Polynomial polynomial) {
this.x = x; this.x = x;
this.y = y; this.y = polynomial.image(x);
}
/**
* copy constructor
* @param point
*/
public Point(Point point) {
this.x = point.x;
this.y = point.y;
} }
} }

View File

@ -9,48 +9,84 @@ import java.util.Random;
/** /**
* Created by Tzlil on 1/27/2016. * Created by Tzlil on 1/27/2016.
* an implementation of Shamire's secret sharing scheme
*/ */
public class SecretSharing { public class SecretSharing {
protected final CyclicGroup<BigInteger> group;
protected final int t; protected final int t;
protected final int n; protected final int n;
protected final BigInteger p;
protected final Polynomial polynomial; protected final Polynomial polynomial;
public SecretSharing(CyclicGroup<BigInteger> group, int t, int n, BigInteger s, Random random) { /**
this.group = group; * constructor
* @param p prime
* @param t threshold. Any t+1 share holders can recover the secret,
* but any set of at most t share holders cannot
* @param n number of share holders
* @param s secret, chosen from Zp
* @param random use for generate random polynomial
*/
public SecretSharing(BigInteger p, int t, int n, BigInteger s, Random random) {
this.p = p;
this.t = t; this.t = t;
this.n = n; this.n = n;
this.polynomial = generateRandomPolynomial(s,random); this.polynomial = generateRandomPolynomial(s,random);
} }
/**
* @param s
* @param random
* @return new Polynomial polynomial of degree t ,such that
* 1. polynomial(0) = s
* 2. polynomial coefficients randomly chosen from Zp (except of coefficients[0] = s)
*/
private Polynomial generateRandomPolynomial(BigInteger s, Random random) { private Polynomial generateRandomPolynomial(BigInteger s, Random random) {
BigInteger[] coefficients = new BigInteger[t + 1]; BigInteger[] coefficients = new BigInteger[t + 1];
coefficients[0] = s; coefficients[0] = s;
BigInteger p = group.orderUpperBound();
int bits = p.bitLength(); int bits = p.bitLength();
for (int i = 1 ; i <= t; i++ ){ for (int i = 1 ; i <= t; i++ ){
coefficients[i] = new BigInteger(bits,random).mod(p); // sample from Zp [0,... p-1] coefficients[i] = new BigInteger(bits,random).mod(p);
} }
return new Polynomial(coefficients); return new Polynomial(coefficients);
} }
//ToDo make it safe : permission to call this func //ToDo make it safe : permission to call this func
/**
* @param i in range of [1,...n]
*
* @return polynomial.image(i)
*
* @throws Exception i out of range
*/
public Polynomial.Point getShare(int i) throws Exception { public Polynomial.Point getShare(int i) throws Exception {
if(i < 1 || i > n){ if(i < 1 || i > n){
throw new Exception(); throw new Exception();
} }
return new Polynomial.Point(BigInteger.valueOf(i), polynomial.image(BigInteger.valueOf(i))); return new Polynomial.Point(BigInteger.valueOf(i), polynomial);
} }
/**
* @param shares - subset of the original shares
*
* @return image of interpolation(shares) at x = 0
*/
public static BigInteger getSecrete(Polynomial.Point[] shares){ public static BigInteger getSecrete(Polynomial.Point[] shares){
Polynomial polynomial = Polynomial.interpolation(shares); Polynomial polynomial = Polynomial.interpolation(shares);
return polynomial.image(BigInteger.ZERO); return polynomial.image(BigInteger.ZERO);
} }
/**
* getter
* @return threshold
*/
public int getThreshold() { public int getThreshold() {
return t; return t;
} }
/**
* getter
* @return number of share holders
*/
public int getN() { public int getN() {
return n; return n;
} }

View File

@ -42,14 +42,14 @@ public class InterpolationTest {
continue; continue;
} }
set.add(x); set.add(x);
points[i] = new Polynomial.Point(x,p.image(x)); points[i] = new Polynomial.Point(x,p);
} }
return points; return points;
} }
public void oneTest(Polynomial p, Polynomial.Point[] points){ public void oneTest(Polynomial p, Polynomial.Point[] points){
Polynomial interpolation = Polynomial.interpolation(points); Polynomial interpolation = Polynomial.interpolation(points);
assert (p.isEquals(interpolation)); assert (p.compareTo(interpolation) == 0);
} }
@Test @Test