joint feldman protocol with test
parent
8288b07d80
commit
a233f2f713
|
@ -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()))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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() {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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()));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue