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());
}
/**
* constructor
* @param x
* @param y
*/
public Point(BigInteger x,BigInteger y) {
this.x = x;
this.y = y;
}
public DKGMessages.SecretMessage.Point asMessage(){
return DKGMessages.SecretMessage.Point.newBuilder()
.setX(ByteString.copyFrom(x.toByteArray()))

View File

@ -53,7 +53,7 @@ public class SecretSharing {
*
* @return polynomial.image(i)%q
*/
protected Polynomial.Point getShare(int i){
protected final Polynomial.Point getShare(int i){
assert (i > 0 && i <= n);
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.Random;
import java.util.Set;
import java.util.concurrent.Callable;
/**
* Created by Tzlil on 2/5/2016.
@ -19,28 +20,31 @@ import java.util.Set;
*/
public class DKG extends VerifiableSecretSharing implements Runnable{
private Network.User user;
private Network.MailHandler handler;
private Polynomial.Point[] shares;
private Polynomial.Point[] myshares;
private BigInteger[][] commitmentsArray;
private BigInteger[] ys;
final ComplainState[][] complainStates;
private Set<Integer> QUAL;
private final int id;
private final Network.User user; // send and receive messages throw network
private final BigInteger[] ys; // container for y values that
private final Polynomial.Point[] shares; // shares[i] equivalent to Si,id in terms of the protocol
private final BigInteger[][] commitmentsArray; // commitmentsArray[i] equivalent to Ai in terms of the protocol
private final ComplainState[][] complainStates; // complainStates[i][j] == state of Pj's complaint against Pi
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) {
super(t, n, x, random, p, q, g);
this.commitmentsArray = new BigInteger[n][t + 1];
this.shares = new Polynomial.Point[n];
this.myshares = new Polynomial.Point[n];
this.handler = new Handler();
this.user = network.connect(handler);
this.user = network.connect(new Handler());
this.id = user.getID();
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 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(){
int i = user.getID();
// for avoiding edge cases, sets commitmentsArray[id - 1]
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;
for (int k = 1; k <= commitmentsArray[i - 1].length; k ++){
for (int k = 0; k <= t ; k ++){
commitment = CommitmentMessage.newBuilder()
.setK(k)
.setCommitment(ByteString.copyFrom(commitmentsArray[i - 1][k - 1].toByteArray()))
.setCommitment(ByteString.copyFrom(commitmentsArray[id - 1][k].toByteArray()))
.build();
user.broadcast(Mail.Type.COMMITMENT,commitment);
}
// computes and sends shares
SecretMessage secret;
for (int j = 1; j <= n ; j++ ){
if(j != i){
myshares[j - 1] = super.getShare(j);
if(j != id){
secret = SecretMessage.newBuilder()
.setSecret(myshares[j - 1].asMessage())
.setSecret(getShare(j).asMessage())
.build();
user.send(j, Mail.Type.SECRET,secret);
}
else{
shares[id - 1] = super.getShare(id);
}
}
while (!isStage1Complete()){
try {
Thread.sleep(30);
Thread.sleep(300);
} catch (InterruptedException e) {
// do nothing
}
}
}
/**
* @return true iff all shares and commitments were received
*/
private boolean isStage1Complete(){
int id = user.getID();
for (int j = 1 ; j <= n ; j++){
if(id != j && shares[j - 1] == null)
for (int i = 1 ; i <= n ; i++){
if(shares[i - 1] == null)
return false;
}
@ -99,28 +126,36 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
return true;
}
/**
* @param secret
* @param i
* @return g ^ Sij == verify(j,Ai,zpstar) (mod p)
*/
private boolean isValidSecret(Polynomial.Point secret, int i){
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(){
int j = user.getID();
QUAL = new HashSet<Integer>();
ys[id - 1] = super.getY();
ComplaintMessage complaint;
for (int i = 1; i <= n ; i++ ){
if(isValidSecret(shares[i - 1],j)) {
QUAL.add(i);
}else{
if(id != i && !isValidSecret(shares[i - 1],i)) {
//message = new Message(Type.Complaint, j)
complaint = ComplaintMessage.newBuilder()
.setId(i)
.build();
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()
.setY(ByteString.copyFrom(super.getY().toByteArray()))
.build();
@ -128,87 +163,99 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
while (!isStage2Complete()){
try {
Thread.sleep(30);
Thread.sleep(300);
} catch (InterruptedException e) {
// do nothing
}
}
}
/**
* @return true iff all yi received for i = 1,...,n .
*/
private boolean isStage2Complete() {
int id = user.getID();
for (int j = 1; j <= n ; j++) {
if (id != j && ys[j - 1] == null)
if (j != id && ys[j - 1] == null)
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;
}
/**
* 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(){
// broadcasts Sij for each complaint against Pid
for (int j = 1 ; j <= complainStates[id - 1].length;j++) {
switch (complainStates[id - 1][j - 1]) {
case Waiting:
user.broadcast(Mail.Type.SECRET, SecretMessage.newBuilder()
.setSecret(getShare(j).asMessage())
.build());
complainStates[id - 1][j - 1] = ComplainState.NonDisqualified;
break;
default:
break;
}
}
// wait until there is no complaint waiting for answer
for (int i = 0; i < complainStates.length;i++){
ComplainState state = ComplainState.Non;
for (int j = 0 ; j < complainStates[i].length;j++){
switch (complainStates[i][j]){
case Disqualified:
state = ComplainState.Disqualified;
break;
case NonDisqualified:
if(state == ComplainState.Non){
state = ComplainState.NonDisqualified;
while (complainStates[i][j].equals(ComplainState.Waiting)){
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// do nothing
}
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;
default:
break;
}
}
}
private void stage4(){
BigInteger y = zpstar.zero();
for (int i : QUAL) {
y = zpstar.add(y , ys[i - 1]);
// 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(){
this.y = zpstar.zero();
for (int i : QUAL) {
this.y = zpstar.add(this.y , ys[i - 1]);
}
this.commitments = new BigInteger[t];
BigInteger commitment;
for (int k = 1; k <= t ; k++){
for (int k = 0; k <= t ; k++){
commitment = zpstar.zero();
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 x = BigInteger.ZERO;
BigInteger xj = BigInteger.ZERO;
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
@ -221,18 +268,8 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
return Arrays.clone(commitments);
}
@Override
protected Polynomial.Point getShare(int i) {
return null;
}
@Override
public void run() {
stage1();
stage2();
stage3();
stage4();
}
private enum ComplainState{
Non, Waiting,Disqualified,NonDisqualified
@ -240,11 +277,7 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
private class Handler implements Network.MailHandler {
final int id;
private Handler() {
this.id = user.getID();
}
private Handler() {}
void handelSecretMessage(Mail mail) throws InvalidProtocolBufferException {
if(shares[mail.getSender() - 1] == null) {
@ -255,12 +288,12 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
}else{
int i = mail.getSender();
int j = secret.x.intValue();
switch (complainStates[i][j]){
switch (complainStates[i - 1][j - 1]){
case Waiting:
if(isValidSecret(secret,i)){
complainStates[i][j] = ComplainState.NonDisqualified;
complainStates[i - 1][j - 1] = ComplainState.NonDisqualified;
}else{
complainStates[i][j] = ComplainState.Disqualified;
complainStates[i - 1][j - 1] = ComplainState.Disqualified;
}
break;
default:
@ -291,15 +324,11 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
}
void handelComplaintMessage(Mail mail) throws InvalidProtocolBufferException {
int id = user.getID();
if(!mail.getIsPrivate()) { //broadcast only
ComplaintMessage complaintMessage = ComplaintMessage.parseFrom(mail.getMessage());
int i = complaintMessage.getId();
int j = mail.getSender();
if(i == id){
user.broadcast(Mail.Type.SECRET,SecretMessage.newBuilder()
.setSecret(myshares[j].asMessage())
.build());
}else{
switch (complainStates[i - 1][j - 1]){
case Non:
complainStates[i - 1][j - 1] = ComplainState.Waiting;
@ -309,7 +338,6 @@ public class DKG extends VerifiableSecretSharing implements Runnable{
}
}
}
}
@Override
public void handel(Mail mail) throws InvalidProtocolBufferException {

View File

@ -7,6 +7,9 @@ import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
/**
* 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 {
@ -28,7 +31,8 @@ public class Network {
Integer id = availableIDs.poll();
if (id == 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){
@ -70,13 +74,12 @@ public class Network {
private final MailHandler messageHandler;
private final Queue<Mail> mailbox;
private final int ID;
private final Thread receiverThread;
public User(int ID, MailHandler messageHandler) {
this.mailbox = new ArrayBlockingQueue<Mail>(n*n);
this.mailbox = new ArrayBlockingQueue<Mail>(1 << n);
this.ID = ID;
this.messageHandler = messageHandler;
Thread thread = new Thread(new Receiver());
thread.run();
this.receiverThread = new Thread(new Receiver());
}
public boolean send(int id, Mail.Type type,Message message){
@ -88,7 +91,9 @@ public class Network {
public int getID() {
return ID;
}
public Thread getReceiverThread(){
return receiverThread;
}
private class Receiver implements Runnable{
@Override
public void run() {

View File

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