joint feldman protocol with test

DKG
tzlil.gon 2016-02-09 20:37:57 +02:00
parent 8288b07d80
commit a233f2f713
6 changed files with 220 additions and 121 deletions

View File

@ -208,6 +208,16 @@ public class Polynomial implements Comparable<Polynomial> {
this.y = new BigInteger(pointMessage.getY().toByteArray()); this.y = new BigInteger(pointMessage.getY().toByteArray());
} }
/**
* constructor
* @param x
* @param y
*/
public Point(BigInteger x,BigInteger y) {
this.x = x;
this.y = y;
}
public DKGMessages.SecretMessage.Point asMessage(){ public DKGMessages.SecretMessage.Point asMessage(){
return DKGMessages.SecretMessage.Point.newBuilder() return DKGMessages.SecretMessage.Point.newBuilder()
.setX(ByteString.copyFrom(x.toByteArray())) .setX(ByteString.copyFrom(x.toByteArray()))

View File

@ -53,7 +53,7 @@ public class SecretSharing {
* *
* @return polynomial.image(i)%q * @return polynomial.image(i)%q
*/ */
protected Polynomial.Point getShare(int i){ protected final Polynomial.Point getShare(int i){
assert (i > 0 && i <= n); assert (i > 0 && i <= n);
return new Polynomial.Point(BigInteger.valueOf(i), polynomial, q); return new Polynomial.Point(BigInteger.valueOf(i), polynomial, q);
} }

View File

@ -11,6 +11,7 @@ import java.math.BigInteger;
import java.util.HashSet; import java.util.HashSet;
import java.util.Random; import java.util.Random;
import java.util.Set; import java.util.Set;
import java.util.concurrent.Callable;
/** /**
* Created by Tzlil on 2/5/2016. * Created by Tzlil on 2/5/2016.
@ -19,28 +20,31 @@ import java.util.Set;
*/ */
public class DKG extends VerifiableSecretSharing implements Runnable{ public class DKG extends VerifiableSecretSharing implements Runnable{
private Network.User user; private final int id;
private Network.MailHandler handler; private final Network.User user; // send and receive messages throw network
private Polynomial.Point[] shares;
private Polynomial.Point[] myshares; private final BigInteger[] ys; // container for y values that
private BigInteger[][] commitmentsArray; private final Polynomial.Point[] shares; // shares[i] equivalent to Si,id in terms of the protocol
private BigInteger[] ys; private final BigInteger[][] commitmentsArray; // commitmentsArray[i] equivalent to Ai in terms of the protocol
final ComplainState[][] complainStates; private final ComplainState[][] complainStates; // complainStates[i][j] == state of Pj's complaint against Pi
private Set<Integer> QUAL;
private final Set<Integer> QUAL; // set of all non-disqualified parties
private final BigInteger[] commitments; // public verification values
private Polynomial.Point share; // final share of the secrete
private BigInteger y; // final public value
private BigInteger x;
private BigInteger y;
private BigInteger[] commitments;
public DKG(int t, int n, BigInteger x, Random random, BigInteger p, BigInteger q, BigInteger g,Network network) { public DKG(int t, int n, BigInteger x, Random random, BigInteger p, BigInteger q, BigInteger g,Network network) {
super(t, n, x, random, p, q, g); super(t, n, x, random, p, q, g);
this.commitmentsArray = new BigInteger[n][t + 1]; this.commitmentsArray = new BigInteger[n][t + 1];
this.shares = new Polynomial.Point[n]; this.shares = new Polynomial.Point[n];
this.myshares = new Polynomial.Point[n]; this.user = network.connect(new Handler());
this.handler = new Handler(); this.id = user.getID();
this.user = network.connect(handler);
this.complainStates = new ComplainState[n][n]; this.complainStates = new ComplainState[n][n];
this.QUAL = new HashSet<Integer>();
this.ys = new BigInteger[n];
this.commitments = new BigInteger[t + 1];
for (int i = 0; i < n; i ++){ for (int i = 0; i < n; i ++){
for (int j = 0 ; j < n ; j ++) for (int j = 0 ; j < n ; j ++)
@ -49,44 +53,67 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
} }
/**
* use for simulate real distributed protocol
*/
@Override
public void run() {
user.getReceiverThread().start();
stage1();
stage2();
stage3();
stage4();
user.getReceiverThread().interrupt();
}
/**
* stage1 according to the protocol
* 1. Pi broadcasts Aik for k = 0,...,t.
* 2. Pi computes the shares Sij for j = 1,...,n and sends Sij secretly to Pj.
*/
private void stage1(){ private void stage1(){
int i = user.getID(); // for avoiding edge cases, sets commitmentsArray[id - 1]
BigInteger[] commitments = super.getCommitments(); BigInteger[] commitments = super.getCommitments();
System.arraycopy(commitments, 0, commitmentsArray[i - 1], 0, commitmentsArray[i - 1].length); System.arraycopy(commitments, 0, commitmentsArray[id - 1], 0, commitmentsArray[id - 1].length);
// broadcasts commitments
CommitmentMessage commitment; CommitmentMessage commitment;
for (int k = 1; k <= commitmentsArray[i - 1].length; k ++){ for (int k = 0; k <= t ; k ++){
commitment = CommitmentMessage.newBuilder() commitment = CommitmentMessage.newBuilder()
.setK(k) .setK(k)
.setCommitment(ByteString.copyFrom(commitmentsArray[i - 1][k - 1].toByteArray())) .setCommitment(ByteString.copyFrom(commitmentsArray[id - 1][k].toByteArray()))
.build(); .build();
user.broadcast(Mail.Type.COMMITMENT,commitment); user.broadcast(Mail.Type.COMMITMENT,commitment);
} }
// computes and sends shares
SecretMessage secret; SecretMessage secret;
for (int j = 1; j <= n ; j++ ){ for (int j = 1; j <= n ; j++ ){
if(j != i){ if(j != id){
myshares[j - 1] = super.getShare(j);
secret = SecretMessage.newBuilder() secret = SecretMessage.newBuilder()
.setSecret(myshares[j - 1].asMessage()) .setSecret(getShare(j).asMessage())
.build(); .build();
user.send(j, Mail.Type.SECRET,secret); user.send(j, Mail.Type.SECRET,secret);
} }
else{
shares[id - 1] = super.getShare(id);
}
} }
while (!isStage1Complete()){ while (!isStage1Complete()){
try { try {
Thread.sleep(30); Thread.sleep(300);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// do nothing // do nothing
} }
} }
} }
/**
* @return true iff all shares and commitments were received
*/
private boolean isStage1Complete(){ private boolean isStage1Complete(){
int id = user.getID(); for (int i = 1 ; i <= n ; i++){
for (int j = 1 ; j <= n ; j++){ if(shares[i - 1] == null)
if(id != j && shares[j - 1] == null)
return false; return false;
} }
@ -99,28 +126,36 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
return true; return true;
} }
/**
* @param secret
* @param i
* @return g ^ Sij == verify(j,Ai,zpstar) (mod p)
*/
private boolean isValidSecret(Polynomial.Point secret, int i){ private boolean isValidSecret(Polynomial.Point secret, int i){
int j = secret.x.intValue(); int j = secret.x.intValue();
return zpstar.multiply(g,secret.y).equals(verify(j,commitmentsArray[i],zpstar)); return zpstar.multiply(g,secret.y).equals(verify(j,commitmentsArray[i - 1],zpstar));
} }
/**
* stage2 according to the protocol
* Pj verifies all the shares he received (using isValidSecret)
* if check fails for an index i, Pj broadcasts a complaint against Pi.
* Pj broadcasts yj value at the end of this stage
*/
private void stage2(){ private void stage2(){
int j = user.getID(); ys[id - 1] = super.getY();
QUAL = new HashSet<Integer>();
ComplaintMessage complaint; ComplaintMessage complaint;
for (int i = 1; i <= n ; i++ ){ for (int i = 1; i <= n ; i++ ){
if(isValidSecret(shares[i - 1],j)) { if(id != i && !isValidSecret(shares[i - 1],i)) {
QUAL.add(i);
}else{
//message = new Message(Type.Complaint, j) //message = new Message(Type.Complaint, j)
complaint = ComplaintMessage.newBuilder() complaint = ComplaintMessage.newBuilder()
.setId(i) .setId(i)
.build(); .build();
user.broadcast(Mail.Type.COMPLAINT,complaint); user.broadcast(Mail.Type.COMPLAINT,complaint);
complainStates[j - 1][i - 1] = ComplainState.Waiting; complainStates[i - 1][id - 1] = ComplainState.Waiting;
} }
} }
//sending y after Complaints //broadcast y after all complaints
YMessage yMessage = YMessage.newBuilder() YMessage yMessage = YMessage.newBuilder()
.setY(ByteString.copyFrom(super.getY().toByteArray())) .setY(ByteString.copyFrom(super.getY().toByteArray()))
.build(); .build();
@ -128,87 +163,99 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
while (!isStage2Complete()){ while (!isStage2Complete()){
try { try {
Thread.sleep(30); Thread.sleep(300);
} catch (InterruptedException e) { } catch (InterruptedException e) {
// do nothing // do nothing
} }
} }
} }
/**
* @return true iff all yi received for i = 1,...,n .
*/
private boolean isStage2Complete() { private boolean isStage2Complete() {
int id = user.getID();
for (int j = 1; j <= n ; j++) { for (int j = 1; j <= n ; j++) {
if (id != j && ys[j - 1] == null) if (j != id && ys[j - 1] == null)
return false; return false;
} }
for (int i = 0; i < complainStates.length;i++){
for (int j =0 ; j < complainStates[i].length;j++){
switch (complainStates[i][j]){
case Waiting:
return false;
default:
break;
}
}
}
return true; return true;
} }
/**
* stage3 according to the protocol
* 1. if more than t players complain against a player Pi he is disqualified.
* 2. Pi broadcasts the share Sij for each complaining player Pj.
* 3. if any of the revealed shares fails the verification test, player Pi is disqualified.
* 4. set QUAL to be the set of non-disqualified players.
*/
private void stage3(){ private void stage3(){
for (int i = 0; i < complainStates.length;i++){
ComplainState state = ComplainState.Non; // broadcasts Sij for each complaint against Pid
for (int j = 0 ; j < complainStates[i].length;j++){ for (int j = 1 ; j <= complainStates[id - 1].length;j++) {
switch (complainStates[i][j]){ switch (complainStates[id - 1][j - 1]) {
case Disqualified: case Waiting:
state = ComplainState.Disqualified; user.broadcast(Mail.Type.SECRET, SecretMessage.newBuilder()
break; .setSecret(getShare(j).asMessage())
case NonDisqualified: .build());
if(state == ComplainState.Non){ complainStates[id - 1][j - 1] = ComplainState.NonDisqualified;
state = ComplainState.NonDisqualified;
}
break;
default:
break;
}
}
switch (state){
case Disqualified:
if(QUAL.contains(i + 1)){
QUAL.remove(i + 1);
}
break;
case NonDisqualified:
if (!QUAL.contains(i + 1)){
QUAL.add(i + 1);
}
break; break;
default: default:
break; break;
} }
} }
// wait until there is no complaint waiting for answer
for (int i = 0; i < complainStates.length;i++){
for (int j = 0 ; j < complainStates[i].length;j++){
while (complainStates[i][j].equals(ComplainState.Waiting)){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// do nothing
}
}
}
}
// add each non-disqualified player to QUAL
boolean nonDisqualified;
for (int i = 1; i <= complainStates.length;i++){
nonDisqualified = true;
for (int j = 1 ; j <= complainStates[i - 1].length;j++){
nonDisqualified &= complainStates[i - 1][j - 1].equals(ComplainState.Disqualified);
}
if(nonDisqualified){
QUAL.add(i);
}
}
} }
/**
* stage4 according to the protocol
* 1. public value y is computed as y = multiplication of yi mod p for i in QUAL
* 2. public verification values are computed as Ak = multiplication of Aik mod p for i in QUAL for k = 0,...,t
* 3. Pj sets is share of the secret as xj = sum of Sij mod q for i in QUAL
*/
private void stage4(){ private void stage4(){
BigInteger y = zpstar.zero(); this.y = zpstar.zero();
for (int i : QUAL) { for (int i : QUAL) {
y = zpstar.add(y , ys[i - 1]); this.y = zpstar.add(this.y , ys[i - 1]);
} }
this.commitments = new BigInteger[t];
BigInteger commitment; BigInteger commitment;
for (int k = 1; k <= t ; k++){ for (int k = 0; k <= t ; k++){
commitment = zpstar.zero(); commitment = zpstar.zero();
for (int i : QUAL) { for (int i : QUAL) {
commitment = zpstar.add(commitment,commitmentsArray[i - 1][k - 1]); commitment = zpstar.add(commitment,commitmentsArray[i - 1][k]);
} }
commitments[k - 1] = commitment; commitments[k] = commitment;
} }
int j = user.getID(); BigInteger xj = BigInteger.ZERO;
BigInteger x = BigInteger.ZERO;
for (int i : QUAL) { for (int i : QUAL) {
x = x.add(shares[i - 1].y); xj = xj.add(shares[i - 1].y);
} }
this.x = x.mod(q); this.share = new Polynomial.Point(BigInteger.valueOf(id) , xj.mod(q));
} }
@Override @Override
@ -221,18 +268,8 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
return Arrays.clone(commitments); return Arrays.clone(commitments);
} }
@Override
protected Polynomial.Point getShare(int i) {
return null;
}
@Override
public void run() {
stage1();
stage2();
stage3();
stage4();
}
private enum ComplainState{ private enum ComplainState{
Non, Waiting,Disqualified,NonDisqualified Non, Waiting,Disqualified,NonDisqualified
@ -240,11 +277,7 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
private class Handler implements Network.MailHandler { private class Handler implements Network.MailHandler {
final int id; private Handler() {}
private Handler() {
this.id = user.getID();
}
void handelSecretMessage(Mail mail) throws InvalidProtocolBufferException { void handelSecretMessage(Mail mail) throws InvalidProtocolBufferException {
if(shares[mail.getSender() - 1] == null) { if(shares[mail.getSender() - 1] == null) {
@ -255,12 +288,12 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
}else{ }else{
int i = mail.getSender(); int i = mail.getSender();
int j = secret.x.intValue(); int j = secret.x.intValue();
switch (complainStates[i][j]){ switch (complainStates[i - 1][j - 1]){
case Waiting: case Waiting:
if(isValidSecret(secret,i)){ if(isValidSecret(secret,i)){
complainStates[i][j] = ComplainState.NonDisqualified; complainStates[i - 1][j - 1] = ComplainState.NonDisqualified;
}else{ }else{
complainStates[i][j] = ComplainState.Disqualified; complainStates[i - 1][j - 1] = ComplainState.Disqualified;
} }
break; break;
default: default:
@ -291,22 +324,17 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
} }
void handelComplaintMessage(Mail mail) throws InvalidProtocolBufferException { void handelComplaintMessage(Mail mail) throws InvalidProtocolBufferException {
int id = user.getID();
if(!mail.getIsPrivate()) { //broadcast only if(!mail.getIsPrivate()) { //broadcast only
ComplaintMessage complaintMessage = ComplaintMessage.parseFrom(mail.getMessage()); ComplaintMessage complaintMessage = ComplaintMessage.parseFrom(mail.getMessage());
int i = complaintMessage.getId(); int i = complaintMessage.getId();
int j = mail.getSender(); int j = mail.getSender();
if(i == id){ switch (complainStates[i - 1][j - 1]){
user.broadcast(Mail.Type.SECRET,SecretMessage.newBuilder() case Non:
.setSecret(myshares[j].asMessage()) complainStates[i - 1][j - 1] = ComplainState.Waiting;
.build()); break;
}else{ default:
switch (complainStates[i - 1][j - 1]){ break;
case Non:
complainStates[i - 1][j - 1] = ComplainState.Waiting;
break;
default:
break;
}
} }
} }
} }

View File

@ -7,6 +7,9 @@ import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent.ArrayBlockingQueue;
/** /**
* Created by Tzlil on 2/7/2016. * Created by Tzlil on 2/7/2016.
* JointFeldamn protocol assumes all parties can communicate throw broadcast chanel
* and private chanel (for each pair)
* this class simulates it
*/ */
public class Network { public class Network {
@ -28,7 +31,8 @@ public class Network {
Integer id = availableIDs.poll(); Integer id = availableIDs.poll();
if (id == null) if (id == null)
return null; return null;
return new User(id,messageHandler); users[id - 1] = new User(id,messageHandler);
return users[id - 1];
} }
private boolean sendMessage(User sender,int destination,Mail.Type type,Message message){ private boolean sendMessage(User sender,int destination,Mail.Type type,Message message){
@ -70,13 +74,12 @@ public class Network {
private final MailHandler messageHandler; private final MailHandler messageHandler;
private final Queue<Mail> mailbox; private final Queue<Mail> mailbox;
private final int ID; private final int ID;
private final Thread receiverThread;
public User(int ID, MailHandler messageHandler) { public User(int ID, MailHandler messageHandler) {
this.mailbox = new ArrayBlockingQueue<Mail>(n*n); this.mailbox = new ArrayBlockingQueue<Mail>(1 << n);
this.ID = ID; this.ID = ID;
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
Thread thread = new Thread(new Receiver()); this.receiverThread = new Thread(new Receiver());
thread.run();
} }
public boolean send(int id, Mail.Type type,Message message){ public boolean send(int id, Mail.Type type,Message message){
@ -88,7 +91,9 @@ public class Network {
public int getID() { public int getID() {
return ID; return ID;
} }
public Thread getReceiverThread(){
return receiverThread;
}
private class Receiver implements Runnable{ private class Receiver implements Runnable{
@Override @Override
public void run() { public void run() {

View File

@ -33,7 +33,6 @@ public class InterpolationTest {
public Polynomial.Point[] randomPoints(Polynomial p){ public Polynomial.Point[] randomPoints(Polynomial p){
Polynomial.Point[] points = new Polynomial.Point[p.getDegree() + 1]; Polynomial.Point[] points = new Polynomial.Point[p.getDegree() + 1];
BigInteger x; BigInteger x;
Boolean b;
Set<BigInteger> set = new HashSet(); Set<BigInteger> set = new HashSet();
for (int i = 0; i < points.length; i++){ for (int i = 0; i < points.length; i++){
x = new BigInteger(bits,random); x = new BigInteger(bits,random);

View File

@ -0,0 +1,57 @@
package JointFeldmanProtocol;
import org.factcenter.qilin.primitives.concrete.Zpstar;
import org.junit.Before;
import org.junit.Test;
import java.math.BigInteger;
import java.util.Random;
/**
* Created by Tzlil on 2/9/2016.
*/
public class DKGTest {
DKG[] dkgs;
Thread[] threads;
int tests = 1 << 10;
Random random;
@Before
public void settings(){
BigInteger p = BigInteger.valueOf(2903);
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
Zpstar zpstar = new Zpstar(p);
random = new Random();
BigInteger g;
BigInteger ZERO = zpstar.zero();
do{
g = zpstar.sample(random);
}while (!g.equals(ZERO) && !zpstar.multiply(g,q).equals(ZERO));// sample from QRZp*
int t = 8;
int n = 20
;
Network network = new Network(n);
dkgs = new DKG[n];
threads = new Thread[n];
for (int i = 0 ; i < n ; i++) {
dkgs[i] = new DKG(t, n, new BigInteger(q.bitLength(), random).mod(q), random, p, q, g, network);
threads[i] = new Thread(dkgs[i]);
}
}
@Test
public void DKGTest() throws Exception {
for (int i = 0 ; i < threads.length ; i++){
threads[i].start();
}
for (int i = 0 ; i < threads.length ; i++){
threads[i].join();
}
for (int i = 0; i < dkgs.length - 1 ; i++){
assert (dkgs[i].getY().equals(dkgs[i+1].getY()));
}
}
}