generic group + wait instead of sleep
parent
4f608e813d
commit
0ae9719bc5
|
@ -1,28 +0,0 @@
|
|||
package Communication;
|
||||
|
||||
/**
|
||||
* A generic commmunication channel that supports point-to-point and broadcast operation
|
||||
*/
|
||||
//
|
||||
//public interface Channel {
|
||||
// public interface ReceiverCallback {
|
||||
// public void receiveMessage(UserID fromUser, boolean isBroadcast, Message message);
|
||||
// }
|
||||
//
|
||||
// public void sendMessage(UserID destUser, Message msg);
|
||||
//
|
||||
// /**
|
||||
// * Block until a message is available (optional).
|
||||
// * @return
|
||||
// */
|
||||
// public Message getNextMessageBlocking(long timeout);
|
||||
//
|
||||
//
|
||||
// /**
|
||||
// * Register a callback to handle received messages.
|
||||
// * The callback is called in the <b>Channel</b> thread, so no long processing should
|
||||
// * occur in the callback method.
|
||||
// * @param callback
|
||||
// */
|
||||
// public void registerReceiverCallback(ReceiverCallback callback);
|
||||
//}
|
|
@ -1,75 +0,0 @@
|
|||
package Communication;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages.*;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Queue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
/**
|
||||
* Created by Tzlil on 2/7/2016.
|
||||
* Joint Feldamn protocol assumes all parties can communicate throw broadcast channel
|
||||
* and private channel (for each pair)
|
||||
* this class simulates it
|
||||
*/
|
||||
// TODO: Delete
|
||||
// TODO: Move this implementation to tests
|
||||
public class Network {
|
||||
|
||||
protected final User[] users;
|
||||
protected final int n;
|
||||
protected final Set<Integer> availableIDs;
|
||||
public static final int BROADCAST = 0;
|
||||
|
||||
|
||||
public Network(int n) {
|
||||
this.n = n;
|
||||
this.users = new User[n];
|
||||
this.availableIDs = new HashSet<Integer>();
|
||||
for (int id = 1; id <= n; id++){
|
||||
availableIDs.add(id);
|
||||
}
|
||||
}
|
||||
|
||||
public User connect(MailHandler mailHandler,int id){
|
||||
if (!availableIDs.contains(id))
|
||||
return null;
|
||||
availableIDs.remove(id);
|
||||
users[id - 1] = new User(id,this,mailHandler);
|
||||
return users[id - 1];
|
||||
}
|
||||
|
||||
protected boolean sendMessage(User sender,int destination,Mail.Type type,Message message){
|
||||
if(destination < 1 || destination > n)
|
||||
return false;
|
||||
User user = users[destination - 1];
|
||||
if (user == null)
|
||||
return false;
|
||||
Mail mail = Mail.newBuilder()
|
||||
.setSender(sender.getID())
|
||||
.setDestination(destination)
|
||||
.setIsPrivate(true)
|
||||
.setType(type)
|
||||
.setMessage(message.toByteString())
|
||||
.build();
|
||||
return user.mailbox.add(mail);
|
||||
}
|
||||
|
||||
protected void sendBroadcast(User sender,Mail.Type type,Message message){
|
||||
User user;
|
||||
Mail mail = Mail.newBuilder()
|
||||
.setSender(sender.getID())
|
||||
.setDestination(BROADCAST)
|
||||
.setIsPrivate(false)
|
||||
.setType(type)
|
||||
.setMessage(message.toByteString())
|
||||
.build();
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
user = users[i];
|
||||
user.mailbox.add(mail);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,74 +0,0 @@
|
|||
package Communication;
|
||||
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
// TODO: Change nane to network
|
||||
|
||||
public class User{
|
||||
/*
|
||||
* My view of
|
||||
*/
|
||||
|
||||
|
||||
|
||||
protected final MailHandler mailHandler;
|
||||
protected final Queue<DKGMessages.Mail> mailbox;
|
||||
protected final int ID;
|
||||
protected final Thread receiverThread;
|
||||
private final Network network;
|
||||
|
||||
protected User(int ID, Network network, MailHandler mailHandler) {
|
||||
this.mailbox = new ArrayBlockingQueue<DKGMessages.Mail>( network.n * network.n * network.n);
|
||||
this.ID = ID;
|
||||
this.mailHandler = mailHandler;
|
||||
this.receiverThread = new Thread(new Receiver());
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
public boolean send(int id, DKGMessages.Mail.Type type, Message message){
|
||||
return network.sendMessage(this,id,type,message);
|
||||
}
|
||||
|
||||
public void broadcast(DKGMessages.Mail.Type type, Message message){
|
||||
network.sendBroadcast(this,type,message);
|
||||
}
|
||||
public MailHandler getMailHandler(){
|
||||
return mailHandler;
|
||||
}
|
||||
public void setMessageHandler(MessageHandler messageHandler) {
|
||||
mailHandler.setMessageHandler(messageHandler);
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return ID;
|
||||
}
|
||||
public Thread getReceiverThread(){
|
||||
return receiverThread;
|
||||
}
|
||||
private class Receiver implements Runnable{
|
||||
@Override
|
||||
public void run() {
|
||||
while (true){
|
||||
if (!mailbox.isEmpty()){
|
||||
mailHandler.handel(mailbox.poll());
|
||||
}else{
|
||||
try {
|
||||
Thread.sleep(30);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,102 +0,0 @@
|
|||
package FeldmanVerifiableSecretSharing;
|
||||
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import ShamirSecretSharing.SecretSharing;
|
||||
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import java.util.Arrays;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*
|
||||
* an implementation of Feldman's verifiable secret sharing scheme.
|
||||
*
|
||||
* allows trusted dealer to share a key x among n parties.
|
||||
*
|
||||
* TODO: Add link to paper
|
||||
*
|
||||
*/
|
||||
// TODO: Use Group<T> rather than fix to biginteger (allow using EC groups for better comm. complexity)
|
||||
public class VerifiableSecretSharing extends SecretSharing {
|
||||
protected final Group<BigInteger> group;
|
||||
protected final BigInteger g; // public generator of group
|
||||
protected final BigInteger[] commitmentsArray;
|
||||
/**
|
||||
* @param group
|
||||
* @param q a large prime dividing group order.
|
||||
* @param g a generator of cyclic group of order q.
|
||||
* the generated group is a subgroup of the given group.
|
||||
* it must be chosen such that computing discrete logarithms is hard in this group.
|
||||
*/
|
||||
public VerifiableSecretSharing(int t, int n, BigInteger x, Random random, BigInteger q, BigInteger g
|
||||
, Group<BigInteger> group) {
|
||||
super(t, n, x, random,q);
|
||||
this.g = g;
|
||||
this.group = group;
|
||||
assert (this.group.contains(g));
|
||||
this.commitmentsArray = generateCommitments();
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: comment
|
||||
* @return commitments[i] = g ^ polynomial.coefficients[i]
|
||||
*/
|
||||
private BigInteger[] generateCommitments() {
|
||||
|
||||
Polynomial polynomial = getPolynomial();
|
||||
BigInteger[] coefficients = polynomial.getCoefficients();
|
||||
BigInteger[] commitments = new BigInteger[coefficients.length];
|
||||
for (int i = 0 ; i < commitments.length;i++){
|
||||
commitments[i] = group.multiply(g,coefficients[i]);
|
||||
}
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute verification value (g^{share value}) using coefficient commitments sent by dealer and my share id.
|
||||
* @param j my share holder id
|
||||
* @param commitments commitments to polynomial coefficients of share (received from dealer)
|
||||
* @param group
|
||||
*
|
||||
* @return product of Aik ^ (j ^ k) == g ^ polynomial(i)
|
||||
*/
|
||||
public static BigInteger computeVerificationValue(int j, BigInteger[] commitments, Group<BigInteger> group) {
|
||||
BigInteger v = group.zero();
|
||||
BigInteger power = BigInteger.ONE;
|
||||
BigInteger J = BigInteger.valueOf(j);
|
||||
for (int k = 0 ; k < commitments.length ; k ++){
|
||||
v = group.add(v,group.multiply(commitments[k],power));
|
||||
power = power.multiply(J);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
// TODO: Add verify method.
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return generator of group
|
||||
*/
|
||||
public BigInteger getGenerator() {
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return group
|
||||
*/
|
||||
public Group<BigInteger> getGroup(){
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return copy of commitmentsArray
|
||||
*/
|
||||
public BigInteger[] getCommitmentsArray() {
|
||||
return Arrays.copyOf(commitmentsArray, commitmentsArray.length);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,141 +0,0 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Communication.User;
|
||||
import FeldmanVerifiableSecretSharing.VerifiableSecretSharing;
|
||||
import JointFeldmanProtocol.DistributedKeyGeneration;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
* TODO: comments
|
||||
* TODO: put Channel (User) in constructor
|
||||
*/
|
||||
public class SecureDistributedKeyGeneration extends DistributedKeyGeneration {
|
||||
|
||||
private VerifiableSecretSharing maskingShares;
|
||||
private final BigInteger h;
|
||||
private SecureDistributedKeyGenerationParty[] parties;
|
||||
|
||||
public SecureDistributedKeyGeneration(int t, int n, BigInteger zi, Random random, BigInteger q, BigInteger g
|
||||
, BigInteger h, Group<BigInteger> group, int id) {
|
||||
super(t, n, zi, random, q, g, group, id);
|
||||
this.h = h;
|
||||
BigInteger r = new BigInteger(q.bitLength(),random).mod(q);
|
||||
this.maskingShares = new VerifiableSecretSharing(t,n,r,random,q,h,group);
|
||||
this.parties = new SecureDistributedKeyGenerationParty[n];
|
||||
for (int i = 1; i <= n ; i++){
|
||||
this.parties[i - 1] = new SecureDistributedKeyGenerationParty(i,n,t);
|
||||
}
|
||||
this.parties[id - 1].share = getShare(id);
|
||||
this.parties[id - 1].shareT = maskingShares.getShare(id);
|
||||
super.setParties(parties);
|
||||
}
|
||||
|
||||
protected SecureDistributedKeyGenerationParty[] getParties(){
|
||||
return parties;
|
||||
}
|
||||
|
||||
protected void setParties(SecureDistributedKeyGenerationParty[] parties) {
|
||||
super.setParties(parties);
|
||||
this.parties = parties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendSecret(User user, int j) {
|
||||
Polynomial.Point secret = getShare(j);
|
||||
Polynomial.Point secretT = maskingShares.getShare(j);
|
||||
DKGMessages.DoubleSecretMessage doubleSecretMessage = doubleShareMessage(id,j,secret,secretT);
|
||||
// TODO: Change SECRET to SHARE
|
||||
user.send(j, DKGMessages.Mail.Type.SECRET, doubleSecretMessage);
|
||||
}
|
||||
|
||||
|
||||
public boolean isValidShare(int i){
|
||||
SecureDistributedKeyGenerationParty party = parties[i - 1];
|
||||
return isValidShare(party.share, party.shareT, party.verifiableValues, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: comment
|
||||
* @param share
|
||||
* @param shareT
|
||||
* @param verificationValues
|
||||
* @param j
|
||||
* @return computeVerificationValue(j,verificationValues,group) == (g ^ share.y) * (h ^ shareT.y) mod q
|
||||
*/
|
||||
public boolean isValidShare(Polynomial.Point share, Polynomial.Point shareT, BigInteger[] verificationValues, int j){
|
||||
try {
|
||||
BigInteger v = computeVerificationValue(j, verificationValues, group);
|
||||
BigInteger exp = group.add(group.multiply(g, share.y), group.multiply(h, shareT.y));
|
||||
return exp.equals(v);
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: comment
|
||||
private void broadcastComplaint(User user,Polynomial.Point share,Polynomial.Point shareT,int i){
|
||||
DKGMessages.DoubleSecretMessage complaint = doubleShareMessage(i,id,share,shareT);
|
||||
user.broadcast(DKGMessages.Mail.Type.COMPLAINT,complaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* stage4.3 according to the protocol
|
||||
* if check fails for index i, Pj
|
||||
*/
|
||||
public void computeAndBroadcastComplaints(User user, Set<Integer> QUAL){
|
||||
SecureDistributedKeyGenerationParty party;
|
||||
for (int i : QUAL) {
|
||||
party = parties[i - 1];
|
||||
if (i != id) {
|
||||
if (!super.isValidSecret(party.share, party.commitments, id)) {
|
||||
broadcastComplaint(user, party.share, party.shareT, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcastVerificationValues(User user){
|
||||
BigInteger[] verificationValues = new BigInteger[t + 1];
|
||||
BigInteger[] hBaseCommitments = maskingShares.getCommitmentsArray();
|
||||
for (int k = 0 ; k < verificationValues.length ; k++){
|
||||
verificationValues[k] = group.add(commitmentsArray[k],hBaseCommitments[k]);
|
||||
}
|
||||
broadcastCommitments(user,verificationValues);
|
||||
}
|
||||
|
||||
private DKGMessages.DoubleSecretMessage doubleShareMessage(int i, int j, Polynomial.Point secret, Polynomial.Point secretT){
|
||||
DKGMessages.DoubleSecretMessage doubleSecretMessage = DKGMessages.DoubleSecretMessage.newBuilder()
|
||||
.setI(i)
|
||||
.setJ(j)
|
||||
.setSecret(ByteString.copyFrom(secret.y.toByteArray()))
|
||||
.setSecretT(ByteString.copyFrom(secretT.y.toByteArray()))
|
||||
.build();
|
||||
return doubleSecretMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastComplaintAnswer(User user, int j) {
|
||||
DKGMessages.DoubleSecretMessage answer = doubleShareMessage(id,j,getShare(j)
|
||||
, maskingShares.getShare(j));
|
||||
user.broadcast(DKGMessages.Mail.Type.ANSWER,answer);
|
||||
}
|
||||
|
||||
public void broadcastAnswer(User user,Polynomial.Point secret,Polynomial.Point secretT,int i){
|
||||
DKGMessages.DoubleSecretMessage complaint = doubleShareMessage(i,id,secret,secretT);
|
||||
user.broadcast(DKGMessages.Mail.Type.ANSWER,complaint);
|
||||
}
|
||||
|
||||
public BigInteger getH() {
|
||||
return h;
|
||||
}
|
||||
}
|
|
@ -1,29 +0,0 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import JointFeldmanProtocol.DistributedKeyGenerationParty;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
*
|
||||
* an extension of DistributedKeyGenerationParty
|
||||
* contains all relevant information on specific party during
|
||||
* the run of the safe protocol
|
||||
*/
|
||||
public class SecureDistributedKeyGenerationParty extends DistributedKeyGenerationParty {
|
||||
public Polynomial.Point shareT;
|
||||
public boolean ysDoneFlag;
|
||||
public BigInteger[] verifiableValues;
|
||||
public Set<Polynomial.Point> restoreSharesSet;
|
||||
public SecureDistributedKeyGenerationParty(int id, int n, int t) {
|
||||
super(id, n, t);
|
||||
this.shareT = null;
|
||||
this.ysDoneFlag = false;
|
||||
this.verifiableValues = new BigInteger[t + 1];
|
||||
this.restoreSharesSet = new HashSet<Polynomial.Point>();
|
||||
}
|
||||
}
|
|
@ -1,13 +0,0 @@
|
|||
package UserInterface;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/21/2016.
|
||||
*/
|
||||
public interface DistributedKeyGenerationUser extends VerifiableSecretSharingUser {
|
||||
|
||||
BigInteger getPublicValue();
|
||||
Set<Integer> getQUAL();
|
||||
}
|
|
@ -1,14 +0,0 @@
|
|||
package UserInterface;
|
||||
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/21/2016.
|
||||
*/
|
||||
public interface SecretSharingUser extends Runnable {
|
||||
|
||||
Polynomial.Point getShare();
|
||||
int getID();
|
||||
int getN();
|
||||
int getT();
|
||||
}
|
|
@ -1,16 +0,0 @@
|
|||
package UserInterface;
|
||||
|
||||
import UserInterface.SecretSharingUser;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/21/2016.
|
||||
*/
|
||||
public interface VerifiableSecretSharingUser extends SecretSharingUser {
|
||||
|
||||
BigInteger[] getCommitments();
|
||||
BigInteger getGenerator();
|
||||
Group<BigInteger> getGroup();
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
package meerkat.crypto;
|
||||
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 4/8/2016.
|
||||
*/
|
||||
public interface KeyGeneration<T> {
|
||||
|
||||
T generateKey(Random random);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
package meerkat.crypto;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 4/8/2016.
|
||||
*/
|
||||
public class SecretSharing {
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package meerkat.crypto.concrete.distributed_key_generation.Communication;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
// TODO: Change nane to network
|
||||
|
||||
public class ChannelImpl implements Channel {
|
||||
|
||||
public static int BROADCAST = 0;
|
||||
private static ChannelImpl[] channels = null;
|
||||
|
||||
protected final Queue<DKGMessages.Mail> mailbox;
|
||||
protected final int id;
|
||||
protected final int n;
|
||||
protected Thread receiverThread;
|
||||
|
||||
|
||||
public ChannelImpl(int id, int n) {
|
||||
if (channels == null){
|
||||
channels = new ChannelImpl[n];
|
||||
}
|
||||
this.mailbox = new ArrayBlockingQueue<DKGMessages.Mail>( n * n * n);
|
||||
this.id = id;
|
||||
this.n = n;
|
||||
channels[id - 1] = this;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(int destUser, DKGMessages.Mail.Type type, Message msg) {
|
||||
if(destUser < 1 || destUser > n)
|
||||
return;
|
||||
ChannelImpl channel = channels[destUser - 1];
|
||||
if (channel == null)
|
||||
return;
|
||||
DKGMessages.Mail mail = DKGMessages.Mail.newBuilder()
|
||||
.setSender(id)
|
||||
.setDestination(destUser)
|
||||
.setIsPrivate(true)
|
||||
.setType(type)
|
||||
.setMessage(msg.toByteString())
|
||||
.build();
|
||||
synchronized (channel.mailbox) {
|
||||
channel.mailbox.add(mail);
|
||||
channel.mailbox.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastMessage(DKGMessages.Mail.Type type,Message msg) {
|
||||
ChannelImpl channel;
|
||||
DKGMessages.Mail mail = DKGMessages.Mail.newBuilder()
|
||||
.setSender(id)
|
||||
.setDestination(BROADCAST)
|
||||
.setIsPrivate(false)
|
||||
.setType(type)
|
||||
.setMessage(msg.toByteString())
|
||||
.build();
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
channel = channels[i];
|
||||
synchronized (channel.mailbox) {
|
||||
channel.mailbox.add(mail);
|
||||
channel.mailbox.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerReceiverCallback(final ReceiverCallback callback) {
|
||||
try{
|
||||
receiverThread.interrupt();
|
||||
}catch (Exception e){
|
||||
//do nothing
|
||||
}
|
||||
receiverThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true){
|
||||
try {
|
||||
synchronized (mailbox) {
|
||||
while (!mailbox.isEmpty()) {
|
||||
callback.receiveMail(mailbox.remove());
|
||||
}
|
||||
mailbox.wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
receiverThread.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,58 +1,56 @@
|
|||
package Communication;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
public abstract class MailHandler {
|
||||
|
||||
private MessageHandler messageHandler;
|
||||
public MailHandler(MessageHandler messageHandler){
|
||||
this.messageHandler = messageHandler;
|
||||
}
|
||||
|
||||
public abstract Message extractMessage(DKGMessages.Mail mail);
|
||||
|
||||
public void handel(DKGMessages.Mail mail){
|
||||
|
||||
Message message = extractMessage(mail);
|
||||
if (message == null)
|
||||
return;
|
||||
|
||||
switch (mail.getType()) {
|
||||
case SECRET:
|
||||
messageHandler.handleSecretMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case COMMITMENT:
|
||||
messageHandler.handleCommitmentMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case DONE:
|
||||
messageHandler.handleDoneMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case COMPLAINT:
|
||||
messageHandler.handleComplaintMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case ANSWER:
|
||||
messageHandler.handleAnswerMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case ABORT:
|
||||
messageHandler.handleAbortMessage(mail.getSender(), mail.getDestination() == Network.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
public void setMessageHandler(MessageHandler messageHandler) {
|
||||
this.messageHandler = messageHandler;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.Communication;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
public abstract class MailHandler implements Channel.ReceiverCallback{
|
||||
|
||||
private MessageHandler messageHandler;
|
||||
public MailHandler(MessageHandler messageHandler){
|
||||
this.messageHandler = messageHandler;
|
||||
}
|
||||
|
||||
public abstract Message extractMessage(DKGMessages.Mail mail);
|
||||
|
||||
public void receiveMail(DKGMessages.Mail mail){
|
||||
|
||||
Message message = extractMessage(mail);
|
||||
if (message == null)
|
||||
return;
|
||||
|
||||
switch (mail.getType()) {
|
||||
case SHARE:
|
||||
messageHandler.handleSecretMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case COMMITMENT:
|
||||
messageHandler.handleCommitmentMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case DONE:
|
||||
messageHandler.handleDoneMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case COMPLAINT:
|
||||
messageHandler.handleComplaintMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case ANSWER:
|
||||
messageHandler.handleAnswerMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
case ABORT:
|
||||
messageHandler.handleAbortMessage(mail.getSender(), mail.getDestination() == ChannelImpl.BROADCAST
|
||||
, message);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -1,15 +1,15 @@
|
|||
package Communication;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
public interface MessageHandler {
|
||||
void handleSecretMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleCommitmentMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleComplaintMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleDoneMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleAnswerMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleAbortMessage(int sender, boolean isBroadcast, Message message);
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.Communication;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
public interface MessageHandler {
|
||||
void handleSecretMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleCommitmentMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleComplaintMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleDoneMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleAnswerMessage(int sender, boolean isBroadcast, Message message);
|
||||
void handleAbortMessage(int sender, boolean isBroadcast, Message message);
|
||||
}
|
|
@ -1,63 +1,63 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.MessageHandler;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/29/2016.
|
||||
*/
|
||||
public class SecureDistributedKeyGenerationMailHandler extends MailHandler {
|
||||
|
||||
private boolean isStage4;
|
||||
|
||||
public SecureDistributedKeyGenerationMailHandler(MessageHandler messageHandler) {
|
||||
super(messageHandler);
|
||||
this.isStage4 = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message extractMessage(DKGMessages.Mail mail) {
|
||||
try {
|
||||
Message message;
|
||||
switch (mail.getType()) {
|
||||
case SECRET:
|
||||
message = DKGMessages.DoubleSecretMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMMITMENT:
|
||||
message = DKGMessages.CommitmentMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMPLAINT:
|
||||
if(!isStage4)
|
||||
message = DKGMessages.IDMessage.parseFrom(mail.getMessage());
|
||||
else
|
||||
message = DKGMessages.DoubleSecretMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case DONE:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ANSWER:
|
||||
message = DKGMessages.DoubleSecretMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ABORT:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return message;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStage4() {
|
||||
return isStage4;
|
||||
}
|
||||
|
||||
public void setStage4(boolean stage4) {
|
||||
isStage4 = stage4;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.MessageHandler;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/29/2016.
|
||||
*/
|
||||
public class MailHandler extends Communication.MailHandler {
|
||||
|
||||
private boolean isStage4;
|
||||
|
||||
public MailHandler(MessageHandler messageHandler) {
|
||||
super(messageHandler);
|
||||
this.isStage4 = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message extractMessage(DKGMessages.Mail mail) {
|
||||
try {
|
||||
Message message;
|
||||
switch (mail.getType()) {
|
||||
case SHARE:
|
||||
message = DKGMessages.DoubleShareMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMMITMENT:
|
||||
message = DKGMessages.CommitmentMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMPLAINT:
|
||||
if(!isStage4)
|
||||
message = DKGMessages.IDMessage.parseFrom(mail.getMessage());
|
||||
else
|
||||
message = DKGMessages.DoubleShareMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case DONE:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ANSWER:
|
||||
message = DKGMessages.DoubleShareMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ABORT:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return message;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStage4() {
|
||||
return isStage4;
|
||||
}
|
||||
|
||||
public void setStage4(boolean stage4) {
|
||||
isStage4 = stage4;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.DistributedKeyGenerationParty;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
*
|
||||
* an extension of DistributedKeyGenerationParty
|
||||
* contains all relevant information on specific party during
|
||||
* the run of the safe protocol
|
||||
*/
|
||||
public class Party<T> extends DistributedKeyGenerationParty<T> {
|
||||
public Polynomial.Point shareT;
|
||||
public boolean ysDoneFlag;
|
||||
public ArrayList<T> verifiableValues;
|
||||
public Set<Polynomial.Point> recoverSharesSet;
|
||||
public Party(int id, int n, int t) {
|
||||
super(id, n, t);
|
||||
this.shareT = null;
|
||||
this.ysDoneFlag = false;
|
||||
this.verifiableValues = new ArrayList<T>(this.commitments);
|
||||
this.recoverSharesSet = new HashSet<Polynomial.Point>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,165 @@
|
|||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.util.ByteEncoder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
* TODO: comments
|
||||
* TODO: put Channel (ChannelImpl) in constructor
|
||||
*/
|
||||
public class Protocol<T> extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol<T> {
|
||||
|
||||
private VerifiableSecretSharing<T> maskingShares;
|
||||
private final T h;
|
||||
private Party<T>[] parties;
|
||||
|
||||
public Protocol(int t, int n, BigInteger zi, Random random, BigInteger q, T g
|
||||
, T h, Group<T> group, int id, ByteEncoder<T> byteEncoder) {
|
||||
super(t, n, zi, random, q, g, group, id,byteEncoder);
|
||||
this.h = h;
|
||||
BigInteger r = new BigInteger(q.bitLength(),random).mod(q);
|
||||
this.maskingShares = new VerifiableSecretSharing(t,n,r,random,q,h,group);
|
||||
this.parties = new Party[n];
|
||||
for (int i = 1; i <= n ; i++){
|
||||
this.parties[i - 1] = new Party(i,n,t);
|
||||
}
|
||||
this.parties[id - 1].share = getShare(id);
|
||||
this.parties[id - 1].shareT = maskingShares.getShare(id);
|
||||
super.setParties(parties);
|
||||
}
|
||||
|
||||
protected Party[] getParties(){
|
||||
return parties;
|
||||
}
|
||||
|
||||
protected void setParties(Party[] parties) {
|
||||
super.setParties(parties);
|
||||
this.parties = parties;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void sendSecret(int j) {
|
||||
Polynomial.Point secret = getShare(j);
|
||||
Polynomial.Point secretT = maskingShares.getShare(j);
|
||||
DKGMessages.DoubleShareMessage doubleSecretMessage = doubleShareMessage(id,j,secret,secretT);
|
||||
// TODO: Change SHARE to SHARE
|
||||
channel.sendMessage(j, DKGMessages.Mail.Type.SHARE, doubleSecretMessage);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean isValidShare(int i){
|
||||
Party party = parties[i - 1];
|
||||
return isValidShare(party.share, party.shareT, party.verifiableValues, id);
|
||||
}
|
||||
|
||||
/**
|
||||
* test if share, shareT are valid with respect to verificationValues
|
||||
* @param share
|
||||
* @param shareT
|
||||
* @param verificationValues
|
||||
* @param j
|
||||
* @return computeVerificationValue(j,verificationValues,group) == (g ^ share.y) * (h ^ shareT.y) mod q
|
||||
*/
|
||||
public boolean isValidShare(Polynomial.Point share, Polynomial.Point shareT, ArrayList<T> verificationValues, int j){
|
||||
try {
|
||||
T v = computeVerificationValue(j, verificationValues, group);
|
||||
T exp = group.add(group.multiply(g, share.y), group.multiply(h, shareT.y));
|
||||
return exp.equals(v);
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create complaint message against i and broadcast it
|
||||
* @param share
|
||||
* @param shareT
|
||||
* @param i
|
||||
*/
|
||||
private void broadcastComplaint(Polynomial.Point share, Polynomial.Point shareT, int i){
|
||||
DKGMessages.DoubleShareMessage complaint = doubleShareMessage(i,id,share,shareT);
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.COMPLAINT,complaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* stage4.3 according to the protocol
|
||||
* if check fails for index i, Pj
|
||||
*/
|
||||
public void computeAndBroadcastComplaints(Set<Integer> QUAL){
|
||||
Party party;
|
||||
for (int i : QUAL) {
|
||||
party = parties[i - 1];
|
||||
if (i != id) {
|
||||
if (!super.isValidShare(party.share, party.commitments, id)) {
|
||||
broadcastComplaint(party.share, party.shareT, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* compute verification values and broadcast them
|
||||
* verificationValues[k] = g ^ commitments [k] * h ^ maskingShares.commitments [k]
|
||||
*/
|
||||
public void computeAndBroadcastVerificationValues(){
|
||||
ArrayList<T> verificationValues = new ArrayList<T>(t+1);
|
||||
ArrayList<T> hBaseCommitments = maskingShares.getCommitmentsArrayList();
|
||||
for (int k = 0 ; k <= t ; k++){
|
||||
verificationValues.add(k,group.add(commitmentsArrayList.get(k),hBaseCommitments.get(k)));
|
||||
}
|
||||
broadcastCommitments(verificationValues);
|
||||
}
|
||||
|
||||
/**
|
||||
* pack share, shareT i,j to doubleShareMessage
|
||||
* @param i
|
||||
* @param j
|
||||
* @param share
|
||||
* @param shareT
|
||||
* @return
|
||||
*/
|
||||
|
||||
private DKGMessages.DoubleShareMessage doubleShareMessage(int i, int j, Polynomial.Point share, Polynomial.Point shareT){
|
||||
DKGMessages.DoubleShareMessage doubleShareMessage = DKGMessages.DoubleShareMessage.newBuilder()
|
||||
.setI(i)
|
||||
.setJ(j)
|
||||
.setSecret(ByteString.copyFrom(share.y.toByteArray()))
|
||||
.setSecretT(ByteString.copyFrom(shareT.y.toByteArray()))
|
||||
.build();
|
||||
return doubleShareMessage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastComplaintAnswer(int j) {
|
||||
DKGMessages.DoubleShareMessage answer = doubleShareMessage(id,j,getShare(j)
|
||||
, maskingShares.getShare(j));
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.ANSWER,answer);
|
||||
}
|
||||
|
||||
public void broadcastAnswer(Polynomial.Point secret, Polynomial.Point secretT, int i){
|
||||
DKGMessages.DoubleShareMessage complaint = doubleShareMessage(i,id,secret,secretT);
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.ANSWER,complaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return h
|
||||
*/
|
||||
public T getH() {
|
||||
return h;
|
||||
}
|
||||
}
|
|
@ -1,307 +1,326 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
import Arithmetics.Fp;
|
||||
import Communication.Network;
|
||||
import JointFeldmanProtocol.DistributedKeyGeneration;
|
||||
import JointFeldmanProtocol.DistributedKeyGenerationUserImpl;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import ShamirSecretSharing.SecretSharing;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
*/
|
||||
public class SecureDistributedKeyGenerationUserImpl extends DistributedKeyGenerationUserImpl {
|
||||
|
||||
protected SecureDistributedKeyGenerationParty[] parties;
|
||||
protected final SecureDistributedKeyGeneration sdkg;
|
||||
private Arithmetic<BigInteger> arithmetic;
|
||||
private boolean isStage4;
|
||||
|
||||
public SecureDistributedKeyGenerationUserImpl(SecureDistributedKeyGeneration sdkg, Network network) {
|
||||
super(sdkg, network,new SecureDistributedKeyGenerationMailHandler(null));
|
||||
this.sdkg = sdkg;
|
||||
this.messageHandler = new MessageHandler();
|
||||
this.user.setMessageHandler(this.messageHandler);
|
||||
this.parties = sdkg.getParties();
|
||||
this.arithmetic = new Fp(sdkg.getQ());
|
||||
this.isStage4 = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage1 according to the protocol
|
||||
* 1. Pi broadcasts Cik=Aik*Bik for k = 0,...,t.
|
||||
* 2. Pi computes the shares Sij,Sij' for j = 1,...,n and sends Sij,Sij' secretly to Pj.
|
||||
*/
|
||||
@Override
|
||||
protected void stage1() {
|
||||
sdkg.broadcastVerificationValues(user);
|
||||
sdkg.sendSecrets(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void waitUntilStageOneCompleted(){
|
||||
super.waitUntilStageOneCompleted();
|
||||
// save the received commitments as verification values
|
||||
BigInteger[] temp;
|
||||
for (int i = 0 ; i < n; i++){
|
||||
temp = parties[i].verifiableValues;
|
||||
parties[i].verifiableValues = parties[i].commitments;
|
||||
parties[i].commitments = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares,sharesT he received
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
* Pj broadcasts done message at the end of this stage
|
||||
*/
|
||||
@Override
|
||||
protected void stage2(){
|
||||
sdkg.broadcastComplaints(user);
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
user.broadcast(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
}
|
||||
|
||||
// TODO: ??
|
||||
private void resolveQualifyingPublicKey(){
|
||||
sdkg.broadcastCommitments(user);
|
||||
// wait until all parties in QUAL broadcast their commitments or aborted
|
||||
// TODO: in main run loop
|
||||
for (int i:QUAL) {
|
||||
for(int k = 0; k <= t; k++) {
|
||||
while (parties[i - 1].commitments[k] == null && !parties[i - 1].aborted) {
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sdkg.computeAndBroadcastComplaints(user,QUAL);
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
user.broadcast(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
|
||||
// wait until all parties in QUAL done or aborted
|
||||
for (int i:QUAL) {
|
||||
while (!parties[i - 1].ysDoneFlag && !parties[i - 1].aborted) {
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast i private secret foreach i in QUAL that aborted
|
||||
for (int i:QUAL) {
|
||||
if(parties[i - 1].aborted){
|
||||
sdkg.broadcastAnswer(user, parties[i - 1].share, parties[i - 1].shareT, i);
|
||||
}
|
||||
}
|
||||
// wait until at least t + 1 secrets will received foreach i in QUAL that aborted
|
||||
for (int i:QUAL) {
|
||||
if(parties[i - 1].aborted){
|
||||
while (parties[i - 1].restoreSharesSet.size() <= t) {
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore necessary information
|
||||
for (int i = 0; i < n ; i++) {
|
||||
if(parties[i].restoreSharesSet.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[t + 1];
|
||||
int j = 0;
|
||||
for (Polynomial.Point share: parties[i].restoreSharesSet){
|
||||
shares[j++] = share;
|
||||
if (j >= shares.length){
|
||||
break;
|
||||
}
|
||||
}
|
||||
Polynomial polynomial = SecretSharing.recoverPolynomial(shares,arithmetic);
|
||||
BigInteger[] coefficients = polynomial.getCoefficients();
|
||||
for (int k = 0 ; k <= t; k++){
|
||||
parties[i].commitments[k] = group.multiply(g,coefficients[k]);
|
||||
}
|
||||
parties[i].share = new Polynomial.Point(BigInteger.valueOf(id),polynomial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notifies mail handler that stage 4 was started
|
||||
*/
|
||||
protected void setStage4(){
|
||||
this.isStage4 = true;
|
||||
SecureDistributedKeyGenerationMailHandler handler =
|
||||
(SecureDistributedKeyGenerationMailHandler)user.getMailHandler();
|
||||
handler.setStage4(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
setStage4();
|
||||
resolveQualifyingPublicKey();
|
||||
super.stage4();
|
||||
}
|
||||
|
||||
private class MessageHandler extends DistributedKeyGenerationUserImpl.MessageHandler{
|
||||
|
||||
/**
|
||||
* as in super, with extension to double secret message
|
||||
*/
|
||||
protected boolean isValidSecretMessage(int sender, boolean isBroadcast, DKGMessages.DoubleSecretMessage doubleSecretMessage) {
|
||||
DKGMessages.SecretMessage secretMessage = DKGMessages.SecretMessage.newBuilder()
|
||||
.setI(doubleSecretMessage.getI())
|
||||
.setJ(doubleSecretMessage.getJ())
|
||||
.setSecret(doubleSecretMessage.getSecret())
|
||||
.build();
|
||||
return super.isValidSecretMessage(sender,isBroadcast,secretMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super, with extension to double secret message
|
||||
*/
|
||||
@Override
|
||||
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.DoubleSecretMessage doubleSecretMessage = (DKGMessages.DoubleSecretMessage)message;
|
||||
if (isValidSecretMessage(sender,isBroadcast,doubleSecretMessage)) {
|
||||
int i = doubleSecretMessage.getI();
|
||||
parties[i - 1].share = extractSecret(id, doubleSecretMessage.getSecret());
|
||||
parties[i - 1].shareT = extractSecret(id, doubleSecretMessage.getSecretT());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as super, with extension to double secret message
|
||||
* else answer message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.j == sender
|
||||
* 3. QUAL contains i and j
|
||||
*/
|
||||
protected boolean isValidAnswerMessage(int sender, boolean isBroadcast, DKGMessages.DoubleSecretMessage doubleSecretMessage) {
|
||||
if(!isStage4) {
|
||||
DKGMessages.SecretMessage secretMessage = DKGMessages.SecretMessage.newBuilder()
|
||||
.setI(doubleSecretMessage.getI())
|
||||
.setJ(doubleSecretMessage.getJ())
|
||||
.setSecret(doubleSecretMessage.getSecret())
|
||||
.build();
|
||||
return super.isValidAnswerMessage(sender, isBroadcast, secretMessage);
|
||||
}else{
|
||||
int i = doubleSecretMessage.getI();
|
||||
int j = doubleSecretMessage.getJ();
|
||||
return isBroadcast && j == sender && parties[i -1].aborted && !parties[j - 1].aborted
|
||||
&& QUAL.contains(i) && QUAL.contains(j);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as super, with extension to double secret message
|
||||
* else saves secret
|
||||
*/
|
||||
@Override
|
||||
public void handleAnswerMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.DoubleSecretMessage doubleSecretMessage = (DKGMessages.DoubleSecretMessage)message;
|
||||
if(isValidAnswerMessage(sender,isBroadcast,doubleSecretMessage)) {
|
||||
int i = doubleSecretMessage.getI();
|
||||
int j = doubleSecretMessage.getJ();
|
||||
Polynomial.Point secret = extractSecret(j, doubleSecretMessage.getSecret());
|
||||
Polynomial.Point secretT = extractSecret(j, doubleSecretMessage.getSecretT());
|
||||
if (!isStage4) {
|
||||
if (sdkg.isValidShare(secret, secretT, parties[j - 1].verifiableValues, i)) {
|
||||
parties[i - 1].complaints[j - 1] = DistributedKeyGeneration.ComplaintState.NonDisqualified;
|
||||
|
||||
} else {
|
||||
parties[i - 1].complaints[j - 1] = DistributedKeyGeneration.ComplaintState.Disqualified;
|
||||
}
|
||||
if(j == id){
|
||||
parties[i - 1].share = secret;
|
||||
parties[i - 1].shareT = secretT;
|
||||
}
|
||||
} else if (sdkg.isValidShare(secret, secretT, parties[j - 1].verifiableValues, i)) {
|
||||
// TODO: Check that this is ok
|
||||
parties[i - 1].restoreSharesSet.add(secret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super with respect to protocol stage
|
||||
*/
|
||||
@Override
|
||||
protected boolean isValidDoneMessage(int sender, boolean isBroadcast) {
|
||||
if(!isStage4) {
|
||||
return super.isValidDoneMessage(sender, isBroadcast);
|
||||
}else{
|
||||
return isBroadcast && !parties[sender - 1].ysDoneFlag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super with respect to protocol state
|
||||
*/
|
||||
@Override
|
||||
public void handleDoneMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(!isStage4)
|
||||
super.handleDoneMessage(sender, isBroadcast, message);
|
||||
else{
|
||||
if(isValidDoneMessage(sender,isBroadcast)) {
|
||||
parties[sender - 1].ysDoneFlag = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* use only in stage4
|
||||
* complaint message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.j == sender
|
||||
* 3. QUAL contains i and j
|
||||
*/
|
||||
protected boolean isValidComplaintMessage(int sender, boolean isBroadcast,
|
||||
DKGMessages.DoubleSecretMessage complaintMessage){
|
||||
int i = complaintMessage.getI();
|
||||
int j = complaintMessage.getJ();
|
||||
return isBroadcast && j == sender && QUAL.contains(i) && QUAL.contains(j);
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as in super
|
||||
* else if secret,secretT are valid with respect to verifiableValues but
|
||||
* secret is not valid with respect to commitments then
|
||||
* marks i as aborted
|
||||
*/
|
||||
@Override
|
||||
public void handleComplaintMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(!isStage4) {
|
||||
super.handleComplaintMessage(sender, isBroadcast, message);
|
||||
}else {
|
||||
DKGMessages.DoubleSecretMessage ysComplaintMessage =(DKGMessages.DoubleSecretMessage)message;
|
||||
if (isValidComplaintMessage(sender,isBroadcast,ysComplaintMessage)) {
|
||||
int i = ysComplaintMessage.getI();
|
||||
int j = ysComplaintMessage.getJ();
|
||||
Polynomial.Point secret = extractSecret(i,ysComplaintMessage.getSecret());
|
||||
Polynomial.Point secretT = extractSecret(i,ysComplaintMessage.getSecretT());
|
||||
if (sdkg.isValidShare(secret, secretT, parties[i - 1].verifiableValues, j)
|
||||
&& !dkg.isValidSecret(secret,parties[i - 1].commitments, j)) {
|
||||
parties[i - 1].aborted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.User;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/16/2016.
|
||||
*/
|
||||
public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.User<T> {
|
||||
|
||||
protected Party<T>[] parties;
|
||||
protected final Protocol<T> sdkg;
|
||||
private Arithmetic<BigInteger> arithmetic;
|
||||
private boolean isStage4;
|
||||
|
||||
public User(Protocol sdkg, Channel channel) {
|
||||
super(sdkg, channel);
|
||||
this.sdkg = sdkg;
|
||||
this.parties = sdkg.getParties();
|
||||
this.arithmetic = new Fp(sdkg.getQ());
|
||||
this.isStage4 = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void registerReceiverCallback(){
|
||||
this.mailHandler = new MailHandler(new MessageHandler());
|
||||
this.channel.registerReceiverCallback(mailHandler);
|
||||
}
|
||||
/**
|
||||
* stage1 according to the protocol
|
||||
* 1. Pi broadcasts Cik=Aik*Bik for k = 0,...,t.
|
||||
* 2. Pi computes the shares Sij,Sij' for j = 1,...,n and sends Sij,Sij' secretly to Pj.
|
||||
*/
|
||||
@Override
|
||||
protected void stage1() {
|
||||
sdkg.computeAndBroadcastVerificationValues();
|
||||
sdkg.sendSecrets();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void waitUntilStageOneCompleted(){
|
||||
super.waitUntilStageOneCompleted();
|
||||
// save the received commitments as verification values
|
||||
ArrayList<T> temp;
|
||||
for (int i = 0 ; i < n; i++){
|
||||
temp = parties[i].verifiableValues;
|
||||
parties[i].verifiableValues = parties[i].commitments;
|
||||
parties[i].commitments = temp;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares,sharesT he received
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
* Pj broadcasts done message at the end of this stage
|
||||
*/
|
||||
@Override
|
||||
protected void stage2(){
|
||||
sdkg.broadcastComplaints();
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* broadcast commitments and recover parties information if necessary
|
||||
*/
|
||||
private void resolveQualifyingPublicKey(){
|
||||
sdkg.broadcastCommitments();
|
||||
// wait until all parties in QUAL broadcast their commitments or aborted
|
||||
for (int i:QUAL) {
|
||||
for(int k = 0; k <= t; k++) {
|
||||
synchronized (parties[i - 1]) {
|
||||
while (parties[i - 1].commitments.get(k) == null && !parties[i - 1].aborted) {
|
||||
try {
|
||||
parties[i - 1].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
sdkg.computeAndBroadcastComplaints(QUAL);
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
|
||||
// wait until all parties in QUAL done or aborted
|
||||
for (int i:QUAL) {
|
||||
synchronized ((parties[i - 1])) {
|
||||
while (!parties[i - 1].ysDoneFlag && !parties[i - 1].aborted) {
|
||||
try {
|
||||
parties[i - 1].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// broadcast i private secret foreach i in QUAL that aborted
|
||||
for (int i:QUAL) {
|
||||
if(parties[i - 1].aborted){
|
||||
sdkg.broadcastAnswer(parties[i - 1].share, parties[i - 1].shareT, i);
|
||||
}
|
||||
}
|
||||
// wait until at least t + 1 secrets will received foreach i in QUAL that aborted
|
||||
for (int i:QUAL) {
|
||||
synchronized ((parties[i - 1])) {
|
||||
if (parties[i - 1].aborted) {
|
||||
while (parties[i - 1].recoverSharesSet.size() <= t) {
|
||||
try {
|
||||
parties[i - 1].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// restore necessary information
|
||||
for (int i = 0; i < n ; i++) {
|
||||
if(parties[i].recoverSharesSet.isEmpty()){
|
||||
continue;
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[t + 1];
|
||||
int j = 0;
|
||||
for (Polynomial.Point share: parties[i].recoverSharesSet){
|
||||
shares[j++] = share;
|
||||
if (j >= shares.length){
|
||||
break;
|
||||
}
|
||||
}
|
||||
Polynomial polynomial = SecretSharing.recoverPolynomial(shares,arithmetic);
|
||||
BigInteger[] coefficients = polynomial.getCoefficients();
|
||||
for (int k = 0 ; k <= t; k++){
|
||||
parties[i].commitments.add(k,group.multiply(g,coefficients[k]));
|
||||
}
|
||||
parties[i].share = new Polynomial.Point(BigInteger.valueOf(id),polynomial);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* notifies mail handler that stage 4 was started
|
||||
*/
|
||||
protected void setStage4(){
|
||||
this.isStage4 = true;
|
||||
((MailHandler)this.mailHandler).setStage4(true);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
setStage4();
|
||||
resolveQualifyingPublicKey();
|
||||
super.stage4();
|
||||
}
|
||||
|
||||
private class MessageHandler extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.User.MessageHandler {
|
||||
|
||||
/**
|
||||
* as in super, with extension to double secret message
|
||||
*/
|
||||
protected boolean isValidSecretMessage(int sender, boolean isBroadcast, DKGMessages.DoubleShareMessage doubleSecretMessage) {
|
||||
DKGMessages.ShareMessage secretMessage = DKGMessages.ShareMessage.newBuilder()
|
||||
.setI(doubleSecretMessage.getI())
|
||||
.setJ(doubleSecretMessage.getJ())
|
||||
.setSecret(doubleSecretMessage.getSecret())
|
||||
.build();
|
||||
return super.isValidSecretMessage(sender,isBroadcast,secretMessage);
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super, with extension to double secret message
|
||||
*/
|
||||
@Override
|
||||
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.DoubleShareMessage doubleSecretMessage = (DKGMessages.DoubleShareMessage)message;
|
||||
if (isValidSecretMessage(sender,isBroadcast,doubleSecretMessage)) {
|
||||
int i = doubleSecretMessage.getI();
|
||||
synchronized (parties[i - 1]) {
|
||||
parties[i - 1].share = extractShare(id, doubleSecretMessage.getSecret());
|
||||
parties[i - 1].shareT = extractShare(id, doubleSecretMessage.getSecretT());
|
||||
parties[i - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as super, with extension to double secret message
|
||||
* else answer message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.j == sender
|
||||
* 3. QUAL contains i and j
|
||||
*/
|
||||
protected boolean isValidAnswerMessage(int sender, boolean isBroadcast, DKGMessages.DoubleShareMessage doubleSecretMessage) {
|
||||
if(!isStage4) {
|
||||
DKGMessages.ShareMessage secretMessage = DKGMessages.ShareMessage.newBuilder()
|
||||
.setI(doubleSecretMessage.getI())
|
||||
.setJ(doubleSecretMessage.getJ())
|
||||
.setSecret(doubleSecretMessage.getSecret())
|
||||
.build();
|
||||
return super.isValidAnswerMessage(sender, isBroadcast, secretMessage);
|
||||
}else{
|
||||
int i = doubleSecretMessage.getI();
|
||||
int j = doubleSecretMessage.getJ();
|
||||
return isBroadcast && j == sender && parties[i -1].aborted && !parties[j - 1].aborted
|
||||
&& QUAL.contains(i) && QUAL.contains(j);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as super, with extension to double secret message
|
||||
* else saves secret
|
||||
*/
|
||||
@Override
|
||||
public void handleAnswerMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.DoubleShareMessage doubleSecretMessage = (DKGMessages.DoubleShareMessage)message;
|
||||
if(isValidAnswerMessage(sender,isBroadcast,doubleSecretMessage)) {
|
||||
int i = doubleSecretMessage.getI();
|
||||
int j = doubleSecretMessage.getJ();
|
||||
Polynomial.Point secret = extractShare(j, doubleSecretMessage.getSecret());
|
||||
Polynomial.Point secretT = extractShare(j, doubleSecretMessage.getSecretT());
|
||||
synchronized (parties[i - 1]) {
|
||||
if (!isStage4) {
|
||||
if (sdkg.isValidShare(secret, secretT, parties[j - 1].verifiableValues, i)) {
|
||||
parties[i - 1].complaints[j - 1] = meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol.ComplaintState.NonDisqualified;
|
||||
|
||||
} else {
|
||||
parties[i - 1].complaints[j - 1] = meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol.ComplaintState.Disqualified;
|
||||
}
|
||||
if (j == id) {
|
||||
parties[i - 1].share = secret;
|
||||
parties[i - 1].shareT = secretT;
|
||||
}
|
||||
} else if (sdkg.isValidShare(secret, secretT, parties[i - 1].verifiableValues, j)) {
|
||||
parties[i - 1].recoverSharesSet.add(secret);
|
||||
}
|
||||
parties[i - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super with respect to protocol stage
|
||||
*/
|
||||
@Override
|
||||
protected boolean isValidDoneMessage(int sender, boolean isBroadcast) {
|
||||
if(!isStage4) {
|
||||
return super.isValidDoneMessage(sender, isBroadcast);
|
||||
}else{
|
||||
return isBroadcast && !parties[sender - 1].ysDoneFlag;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* as in super with respect to protocol state
|
||||
*/
|
||||
@Override
|
||||
public void handleDoneMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(!isStage4)
|
||||
super.handleDoneMessage(sender, isBroadcast, message);
|
||||
else{
|
||||
if(isValidDoneMessage(sender,isBroadcast)) {
|
||||
synchronized (parties[sender - 1]) {
|
||||
parties[sender - 1].ysDoneFlag = true;
|
||||
parties[sender - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* use only in stage4
|
||||
* complaint message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.j == sender
|
||||
* 3. QUAL contains i and j
|
||||
*/
|
||||
protected boolean isValidComplaintMessage(int sender, boolean isBroadcast,
|
||||
DKGMessages.DoubleShareMessage complaintMessage){
|
||||
int i = complaintMessage.getI();
|
||||
int j = complaintMessage.getJ();
|
||||
return isBroadcast && j == sender && QUAL.contains(i) && QUAL.contains(j);
|
||||
}
|
||||
|
||||
/**
|
||||
* if !isStage4 as in super
|
||||
* else if secret,secretT are valid with respect to verifiableValues but
|
||||
* secret is not valid with respect to commitments then
|
||||
* marks i as aborted
|
||||
*/
|
||||
@Override
|
||||
public void handleComplaintMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(!isStage4) {
|
||||
super.handleComplaintMessage(sender, isBroadcast, message);
|
||||
}else {
|
||||
DKGMessages.DoubleShareMessage ysComplaintMessage =(DKGMessages.DoubleShareMessage)message;
|
||||
if (isValidComplaintMessage(sender,isBroadcast,ysComplaintMessage)) {
|
||||
int i = ysComplaintMessage.getI();
|
||||
int j = ysComplaintMessage.getJ();
|
||||
Polynomial.Point secret = extractShare(i,ysComplaintMessage.getSecret());
|
||||
Polynomial.Point secretT = extractShare(i,ysComplaintMessage.getSecretT());
|
||||
if (sdkg.isValidShare(secret, secretT, parties[i - 1].verifiableValues, j)
|
||||
&& !dkg.isValidShare(secret,parties[i - 1].commitments, j)) {
|
||||
synchronized (parties[i - 1]) {
|
||||
parties[i - 1].aborted = true;
|
||||
parties[i - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,49 +1,49 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.MessageHandler;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/29/2016.
|
||||
*/
|
||||
public class DistributedKeyGenerationMailHandler extends MailHandler {
|
||||
|
||||
public DistributedKeyGenerationMailHandler(MessageHandler messageHandler) {
|
||||
super(messageHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message extractMessage(DKGMessages.Mail mail) {
|
||||
try {
|
||||
Message message;
|
||||
switch (mail.getType()) {
|
||||
case SECRET:
|
||||
message = DKGMessages.SecretMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMMITMENT:
|
||||
message = DKGMessages.CommitmentMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMPLAINT:
|
||||
message = DKGMessages.IDMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case DONE:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ANSWER:
|
||||
message = DKGMessages.SecretMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ABORT:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return message;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.MessageHandler;
|
||||
import com.google.protobuf.InvalidProtocolBufferException;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/29/2016.
|
||||
*/
|
||||
public class MailHandler extends Communication.MailHandler {
|
||||
|
||||
public MailHandler(MessageHandler messageHandler) {
|
||||
super(messageHandler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Message extractMessage(DKGMessages.Mail mail) {
|
||||
try {
|
||||
Message message;
|
||||
switch (mail.getType()) {
|
||||
case SHARE:
|
||||
message = DKGMessages.ShareMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMMITMENT:
|
||||
message = DKGMessages.CommitmentMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case COMPLAINT:
|
||||
message = DKGMessages.IDMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case DONE:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ANSWER:
|
||||
message = DKGMessages.ShareMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
case ABORT:
|
||||
message = DKGMessages.EmptyMessage.parseFrom(mail.getMessage());
|
||||
break;
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
return message;
|
||||
} catch (InvalidProtocolBufferException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,32 +1,35 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*
|
||||
* contains all relevant information on specific party during
|
||||
* the run of Joint Feldamn protocol
|
||||
*/
|
||||
// TODO: comments for every field.
|
||||
public class DistributedKeyGenerationParty {
|
||||
public final int id;
|
||||
public Polynomial.Point share;
|
||||
public BigInteger[] commitments;
|
||||
public boolean doneFlag;
|
||||
public DistributedKeyGeneration.ComplaintState[] complaints;
|
||||
public boolean aborted;
|
||||
|
||||
public DistributedKeyGenerationParty(int id, int n, int t) {
|
||||
this.id = id;
|
||||
this.share = null;
|
||||
this.doneFlag = false;
|
||||
this.complaints = new DistributedKeyGeneration.ComplaintState[n];
|
||||
Arrays.fill(this.complaints, DistributedKeyGeneration.ComplaintState.OK);
|
||||
this.commitments = new BigInteger[t + 1];
|
||||
this.aborted = false;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*
|
||||
* contains all relevant information on specific party during
|
||||
* the run of Joint Feldamn protocol
|
||||
*/
|
||||
// TODO: comments for every field.
|
||||
public class Party<T> {
|
||||
public final int id;
|
||||
public Polynomial.Point share;
|
||||
public ArrayList<T> commitments;
|
||||
public boolean doneFlag;
|
||||
public DistributedKeyGeneration.ComplaintState[] complaints;
|
||||
public boolean aborted;
|
||||
|
||||
public Party(int id, int n, int t) {
|
||||
this.id = id;
|
||||
this.share = null;
|
||||
this.doneFlag = false;
|
||||
this.complaints = new DistributedKeyGeneration.ComplaintState[n];
|
||||
Arrays.fill(this.complaints, DistributedKeyGeneration.ComplaintState.OK);
|
||||
this.commitments = new ArrayList<T>(t + 1);
|
||||
for (int i = 0; i <= t ; i++){
|
||||
commitments.add(null);
|
||||
}
|
||||
this.aborted = false;
|
||||
}
|
||||
}
|
|
@ -1,280 +1,356 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Communication.User;
|
||||
import FeldmanVerifiableSecretSharing.VerifiableSecretSharing;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*/
|
||||
// TODO: Lots of comments...
|
||||
// TODO: User Channel instead of User
|
||||
public class DistributedKeyGeneration extends VerifiableSecretSharing {
|
||||
public enum ComplaintState {
|
||||
/**
|
||||
* No complaints, no response required at this point.
|
||||
*/
|
||||
OK,
|
||||
|
||||
/**
|
||||
* Party received complaint, waiting for response from party
|
||||
*/
|
||||
Waiting,
|
||||
|
||||
/**
|
||||
* Party gave invalid answer to conplaint.
|
||||
*/
|
||||
Disqualified,
|
||||
|
||||
/**
|
||||
* Party received complaint, gave valid answer.
|
||||
*/
|
||||
NonDisqualified
|
||||
}
|
||||
|
||||
/**
|
||||
* My share id.
|
||||
*/
|
||||
protected final int id;
|
||||
|
||||
/**
|
||||
* All parties participating in key generation.
|
||||
* parties[id-1] has my info.
|
||||
*/
|
||||
private DistributedKeyGenerationParty[] parties;
|
||||
|
||||
|
||||
// TODO: Copy comment
|
||||
public DistributedKeyGeneration(int t, int n, BigInteger zi, Random random, BigInteger q, BigInteger g
|
||||
, Group<BigInteger> group, int id) {
|
||||
super(t, n, zi, random, q, g,group);
|
||||
this.id = id;
|
||||
this.parties = new DistributedKeyGenerationParty[n];
|
||||
for (int i = 1; i <= n ; i++){
|
||||
this.parties[i - 1] = new DistributedKeyGenerationParty(i,n,t);
|
||||
}
|
||||
this.parties[id - 1].share = getShare(id);
|
||||
}
|
||||
|
||||
protected void setParties(DistributedKeyGenerationParty[] parties){
|
||||
this.parties = parties;
|
||||
}
|
||||
|
||||
protected DistributedKeyGenerationParty[] getParties(){
|
||||
return parties;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage1.1 according to the protocol
|
||||
* Pi broadcasts Aik for k = 0,...,t.
|
||||
*/
|
||||
public void broadcastCommitments(User user){
|
||||
broadcastCommitments(user,commitmentsArray);
|
||||
}
|
||||
|
||||
public void broadcastCommitments(User user, BigInteger[] commitments){
|
||||
DKGMessages.CommitmentMessage commitmentMessage;
|
||||
for (int k = 0; k <= t ; k++){
|
||||
commitmentMessage = DKGMessages.CommitmentMessage.newBuilder()
|
||||
.setCommitment(ByteString.copyFrom(commitments[k].toByteArray()))
|
||||
.setK(k)
|
||||
.build();
|
||||
user.broadcast(DKGMessages.Mail.Type.COMMITMENT, commitmentMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send user j her secret share (of my polynomial)
|
||||
* @param user
|
||||
* @param j
|
||||
*/
|
||||
public void sendSecret(User user, int j){
|
||||
ByteString secret = ByteString.copyFrom(getShare(j).y.toByteArray());
|
||||
user.send(j, DKGMessages.Mail.Type.SECRET,
|
||||
DKGMessages.SecretMessage.newBuilder()
|
||||
.setI(id)
|
||||
.setJ(j)
|
||||
.setSecret(secret)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* stage1.2 according to the protocol
|
||||
* Pi computes the shares Sij for j = 1,...,n and sends Sij secretly to Pj.
|
||||
*/
|
||||
public void sendSecrets(User user){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
sendSecret(user,j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: comment
|
||||
* @param i
|
||||
* @return
|
||||
*/
|
||||
public boolean isValidSecret(int i){
|
||||
DistributedKeyGenerationParty party = parties[i - 1];
|
||||
return isValidSecret(party.share,party.commitments,id);
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: Move to VerifiableSecretSharing
|
||||
* @param secret
|
||||
* @param commitments
|
||||
* @param j
|
||||
* @return computeVerificationValue(j,commitments,group) == g ^ secret.y mod q
|
||||
*/
|
||||
public boolean isValidSecret(Polynomial.Point secret, BigInteger[] commitments, int j){
|
||||
try{
|
||||
BigInteger v = computeVerificationValue(j,commitments,group);
|
||||
return group.multiply(g,secret.y).equals(v);
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares he received (using isValidShare)
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
*/
|
||||
public void broadcastComplaints(User user){
|
||||
for (int i = 1; i <= n ; i++ ){
|
||||
if(i != id && !isValidSecret(i)) {
|
||||
broadcastComplaint(user,i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void broadcastComplaint(User user, int i){
|
||||
//message = new Message(Type.Complaint, j)
|
||||
DKGMessages.IDMessage complaint = DKGMessages.IDMessage.newBuilder()
|
||||
.setId(i)
|
||||
.build();
|
||||
user.broadcast(DKGMessages.Mail.Type.COMPLAINT, complaint);
|
||||
}
|
||||
|
||||
public void broadcastComplaintAnswer(User user, int j){
|
||||
user.broadcast(DKGMessages.Mail.Type.ANSWER, DKGMessages.SecretMessage.newBuilder()
|
||||
.setI(id)
|
||||
.setJ(j)
|
||||
.setSecret(ByteString.copyFrom(getShare(j).y.toByteArray()))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* stage3.1 according to the protocol
|
||||
* if more than t players complain against a player Pi he is disqualified.
|
||||
*/
|
||||
public void answerAllComplainingPlayers(User user){
|
||||
ComplaintState[] complaints = parties[id - 1].complaints;
|
||||
for (int i = 1; i <= n ; i++) {
|
||||
switch (complaints[i - 1]) {
|
||||
case Waiting:
|
||||
broadcastComplaintAnswer(user,i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage3.2 according to the protocol
|
||||
* if any of the revealed shares fails the verification test, player Pi is disqualified.
|
||||
* set QUAL to be the set of non-disqualified players.
|
||||
*/
|
||||
public Set<Integer> calcQUAL(){
|
||||
Set<Integer> QUAL = new HashSet<Integer>();
|
||||
boolean nonDisqualified;
|
||||
int counter;
|
||||
for (int i = 1; i <= n; i++){
|
||||
ComplaintState[] complaints = parties[i - 1].complaints;
|
||||
nonDisqualified = true;
|
||||
counter = 0;
|
||||
for (int j = 1; j <= n; j++){
|
||||
switch (complaints[j - 1]) {
|
||||
case OK:
|
||||
break;
|
||||
case NonDisqualified:
|
||||
// TODO: Add test for false complaint
|
||||
counter++;
|
||||
break;
|
||||
default:
|
||||
nonDisqualified = false;
|
||||
break;
|
||||
}
|
||||
if(!nonDisqualified)
|
||||
break;
|
||||
}
|
||||
if(nonDisqualified && counter <= t){
|
||||
QUAL.add(i);
|
||||
}
|
||||
}
|
||||
return QUAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* compute Y, the commitment to the final public key (includes only qualifying set)
|
||||
* stage4.1 according to the protocol
|
||||
* public value y is computed as y = multiplication of yi mod p for i in QUAL
|
||||
*/
|
||||
public BigInteger calcY(Set<Integer> QUAL){
|
||||
BigInteger y = group.zero();
|
||||
for (int i : QUAL) {
|
||||
y = group.add(y , parties[i - 1].commitments[0]);
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: better comment.
|
||||
* stage4.2 according to the protocol
|
||||
* public verification values are computed as Ak = multiplication of Aik mod p for i in QUAL for k = 0,...,t
|
||||
*/
|
||||
public BigInteger[] calcCommitments(Set<Integer> QUAL){
|
||||
BigInteger[] commitments = new BigInteger[t + 1];
|
||||
Arrays.fill(commitments,group.zero());
|
||||
for (int i : QUAL) {
|
||||
for (int k = 0; k <= t; k++){
|
||||
commitments[k] = group.add(commitments[k], parties[i - 1].commitments[k]);
|
||||
}
|
||||
}
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/**
|
||||
* TODO: better comment.
|
||||
* stage4.3 according to the protocol
|
||||
* Pj sets is share of the secret as xj = sum of Sij mod q for i in QUAL
|
||||
*/
|
||||
public Polynomial.Point calcShare(Set<Integer> QUAL){
|
||||
BigInteger xj = BigInteger.ZERO;
|
||||
for (int i : QUAL) {
|
||||
xj = xj.add(parties[i - 1].share.y);
|
||||
}
|
||||
return new Polynomial.Point(BigInteger.valueOf(id) , xj.mod(q));
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import com.google.protobuf.ByteString;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.util.ByteEncoder;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*
|
||||
* an implementation of JointFeldman distributed key generation protocol.
|
||||
*
|
||||
* allows set of n parties to generate random key with threshold t.
|
||||
*/
|
||||
public class Protocol<T> extends VerifiableSecretSharing<T> {
|
||||
public enum ComplaintState {
|
||||
/**
|
||||
* No complaints, no response required at this point.
|
||||
*/
|
||||
OK,
|
||||
|
||||
/**
|
||||
* Party received complaint, waiting for response from party
|
||||
*/
|
||||
Waiting,
|
||||
|
||||
/**
|
||||
* Party gave invalid answer to conplaint.
|
||||
*/
|
||||
Disqualified,
|
||||
|
||||
/**
|
||||
* Party received complaint, gave valid answer.
|
||||
*/
|
||||
NonDisqualified
|
||||
}
|
||||
|
||||
/**
|
||||
* My share id.
|
||||
*/
|
||||
protected final int id;
|
||||
|
||||
/**
|
||||
* All parties participating in key generation.
|
||||
* parties[id-1] has my info.
|
||||
*/
|
||||
private Party<T>[] parties;
|
||||
|
||||
/**
|
||||
* communication object
|
||||
*/
|
||||
protected Channel channel;
|
||||
|
||||
|
||||
/**
|
||||
* Encode/Decode group elements
|
||||
*/
|
||||
protected final ByteEncoder<T> encoder;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param q a large 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 zi secret, chosen from Zq
|
||||
* @param random use for generate random polynomial
|
||||
* @param group
|
||||
* @param q a large prime dividing group order.
|
||||
* @param g a generator of cyclic group of order q.
|
||||
* the generated group is a subgroup of the given group.
|
||||
* it must be chosen such that computing discrete logarithms is hard in this group.
|
||||
*/
|
||||
public Protocol(int t, int n, BigInteger zi, Random random, BigInteger q, T g
|
||||
, Group<T> group, int id, ByteEncoder<T> byteEncoder) {
|
||||
super(t, n, zi, random, q, g,group);
|
||||
this.id = id;
|
||||
this.parties = new Party[n];
|
||||
for (int i = 1; i <= n ; i++){
|
||||
this.parties[i - 1] = new Party(i,n,t);
|
||||
}
|
||||
this.parties[id - 1].share = getShare(id);
|
||||
this.encoder = byteEncoder;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter
|
||||
* @param channel
|
||||
*/
|
||||
public void setChannel(Channel channel){
|
||||
this.channel = channel;
|
||||
}
|
||||
|
||||
/**
|
||||
* setter
|
||||
* @param parties
|
||||
*/
|
||||
protected void setParties(Party[] parties){
|
||||
this.parties = parties;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return
|
||||
*/
|
||||
protected Party[] getParties(){
|
||||
return parties;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage1.1 according to the protocol
|
||||
* Pi broadcasts Aik for k = 0,...,t.
|
||||
*/
|
||||
public void broadcastCommitments(){
|
||||
broadcastCommitments(commitmentsArrayList);
|
||||
}
|
||||
|
||||
/**
|
||||
* pack commitments as messages and broadcast them
|
||||
* @param commitments
|
||||
*/
|
||||
public void broadcastCommitments(ArrayList<T> commitments){
|
||||
DKGMessages.CommitmentMessage commitmentMessage;
|
||||
for (int k = 0; k <= t ; k++){
|
||||
commitmentMessage = DKGMessages.CommitmentMessage.newBuilder()
|
||||
.setCommitment(ByteString.copyFrom(encoder.encode(commitments.get(k))))
|
||||
.setK(k)
|
||||
.build();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.COMMITMENT, commitmentMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send channel j her secret share (of my polynomial)
|
||||
* @param j
|
||||
*/
|
||||
public void sendSecret(int j){
|
||||
ByteString secret = ByteString.copyFrom(getShare(j).y.toByteArray());
|
||||
channel.sendMessage(j, DKGMessages.Mail.Type.SHARE,
|
||||
DKGMessages.ShareMessage.newBuilder()
|
||||
.setI(id)
|
||||
.setJ(j)
|
||||
.setSecret(secret)
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* stage1.2 according to the protocol
|
||||
* Pi computes the shares Sij for j = 1,...,n and sends Sij secretly to Pj.
|
||||
*/
|
||||
public void sendSecrets(){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
sendSecret(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param i
|
||||
* @return computeVerificationValue(j,parties[i - 1].commitments,group) == g ^ parties[i - 1].share mod q
|
||||
*/
|
||||
public boolean isValidShare(int i){
|
||||
Party<T> party = parties[i - 1];
|
||||
return isValidShare(party.share,party.commitments,id);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param share
|
||||
* @param commitments
|
||||
* @param j
|
||||
* @return computeVerificationValue(j,commitments,group) == g ^ secret.y mod q
|
||||
*/
|
||||
public boolean isValidShare(Polynomial.Point share, ArrayList<T> commitments, int j){
|
||||
try{
|
||||
T v = computeVerificationValue(j,commitments,group);
|
||||
return group.multiply(g,share.y).equals(v);
|
||||
}
|
||||
catch (NullPointerException e){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares he received (using isValidShare)
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
*/
|
||||
public void broadcastComplaints(){
|
||||
for (int i = 1; i <= n ; i++ ){
|
||||
if(i != id && !isValidShare(i)) {
|
||||
broadcastComplaint(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* create a complaint message against i and broadcast it
|
||||
* @param i
|
||||
*/
|
||||
private void broadcastComplaint(int i){
|
||||
//message = new Message(Type.Complaint, j)
|
||||
DKGMessages.IDMessage complaint = DKGMessages.IDMessage.newBuilder()
|
||||
.setId(i)
|
||||
.build();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.COMPLAINT, complaint);
|
||||
}
|
||||
|
||||
/**
|
||||
* create an answer message for j and broadcast it
|
||||
* @param j
|
||||
*/
|
||||
public void broadcastComplaintAnswer(int j){
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.ANSWER, DKGMessages.ShareMessage.newBuilder()
|
||||
.setI(id)
|
||||
.setJ(j)
|
||||
.setSecret(ByteString.copyFrom(getShare(j).y.toByteArray()))
|
||||
.build());
|
||||
}
|
||||
|
||||
/**
|
||||
* stage3.1 according to the protocol
|
||||
* if more than t players complain against a player Pi he is disqualified.
|
||||
*/
|
||||
public void answerAllComplainingPlayers(){
|
||||
ComplaintState[] complaints = parties[id - 1].complaints;
|
||||
for (int i = 1; i <= n ; i++) {
|
||||
switch (complaints[i - 1]) {
|
||||
case Waiting:
|
||||
broadcastComplaintAnswer(i);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage3.2 according to the protocol
|
||||
* if any of the revealed shares fails the verification test, player Pi is disqualified.
|
||||
* set QUAL to be the set of non-disqualified players.
|
||||
*/
|
||||
public Set<Integer> calcQUAL(){
|
||||
Set<Integer> QUAL = new HashSet<Integer>();
|
||||
boolean nonDisqualified;
|
||||
int counter;
|
||||
for (int i = 1; i <= n; i++){
|
||||
ComplaintState[] complaints = parties[i - 1].complaints;
|
||||
nonDisqualified = true;
|
||||
counter = 0;
|
||||
for (int j = 1; j <= n; j++){
|
||||
switch (complaints[j - 1]) {
|
||||
case OK:
|
||||
break;
|
||||
case NonDisqualified:
|
||||
counter++;
|
||||
break;
|
||||
default:
|
||||
nonDisqualified = false;
|
||||
break;
|
||||
}
|
||||
if(!nonDisqualified)
|
||||
break;
|
||||
}
|
||||
if(nonDisqualified && counter <= t){
|
||||
QUAL.add(i);
|
||||
}
|
||||
}
|
||||
return QUAL;
|
||||
}
|
||||
|
||||
/**
|
||||
* compute Y, the commitment to the final public key (includes only qualifying set)
|
||||
* stage4.1 according to the protocol
|
||||
* public value y is computed as y = multiplication of yi mod p for i in QUAL
|
||||
*/
|
||||
public T calcY(Set<Integer> QUAL){
|
||||
T y = group.zero();
|
||||
for (int i : QUAL) {
|
||||
y = group.add(y , parties[i - 1].commitments.get(0));
|
||||
}
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage4.2 according to the protocol
|
||||
* public verification values are computed as Ak = multiplication
|
||||
* of Aik mod p for i in QUAL for k = 0,...,t
|
||||
*/
|
||||
public ArrayList<T> calcCommitments(Set<Integer> QUAL){
|
||||
ArrayList<T> commitments = new ArrayList<T>(t+1);
|
||||
T value;
|
||||
for (int k = 0; k <= t; k++){
|
||||
value = group.zero();
|
||||
for (int i : QUAL) {
|
||||
value = group.add(value, parties[i - 1].commitments.get(k));
|
||||
}
|
||||
commitments.add(k,value);
|
||||
}
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/**
|
||||
* stage4.3 according to the protocol
|
||||
* Pj sets is share of the share as xj = sum of Sij mod q for i in QUAL
|
||||
*/
|
||||
public Polynomial.Point calcShare(Set<Integer> QUAL){
|
||||
BigInteger xj = BigInteger.ZERO;
|
||||
for (int i : QUAL) {
|
||||
xj = xj.add(parties[i - 1].share.y);
|
||||
}
|
||||
return new Polynomial.Point(BigInteger.valueOf(id) , xj.mod(q));
|
||||
}
|
||||
|
||||
/**
|
||||
* decode commitment from arr
|
||||
* @param arr
|
||||
* @return
|
||||
*/
|
||||
public T decodeCommitment(byte[] arr){
|
||||
return encoder.decode(arr);
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return id
|
||||
*/
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return channel
|
||||
*/
|
||||
public Channel getChannel() {
|
||||
return channel;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return encoder
|
||||
*/
|
||||
public ByteEncoder<T> getEncoder() {
|
||||
return encoder;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,393 +1,454 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.Network;
|
||||
import Communication.User;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import UserInterface.DistributedKeyGenerationUser;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
import JointFeldmanProtocol.DistributedKeyGeneration.ComplaintState;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
* TODO: Comments
|
||||
* TODO: Replace polling with monitors/wait/notify (remember synchronization)
|
||||
*/
|
||||
public class DistributedKeyGenerationUserImpl implements DistributedKeyGenerationUser {
|
||||
|
||||
// TODO: remove
|
||||
protected final static int SleepTime = 300;
|
||||
|
||||
protected final DistributedKeyGeneration dkg;
|
||||
|
||||
protected final BigInteger g;
|
||||
protected final Group<BigInteger> group;
|
||||
protected final int n;
|
||||
protected final int t;
|
||||
protected final int id;
|
||||
|
||||
protected MessageHandler messageHandler;
|
||||
protected final User user;
|
||||
protected final DistributedKeyGenerationParty[] parties;
|
||||
protected Set<Integer> QUAL; // set of all non-disqualified parties
|
||||
protected BigInteger[] commitments; // public verification values
|
||||
protected Polynomial.Point share; // final share of the secrete
|
||||
protected BigInteger y; // final public value
|
||||
|
||||
public DistributedKeyGenerationUserImpl(DistributedKeyGeneration dkg, Network network){
|
||||
this(dkg,network,new DistributedKeyGenerationMailHandler(null));
|
||||
}
|
||||
public DistributedKeyGenerationUserImpl(DistributedKeyGeneration dkg, Network network, MailHandler mailHandler) {
|
||||
this.dkg = dkg;
|
||||
|
||||
this.g = dkg.getGenerator();
|
||||
this.group = dkg.getGroup();
|
||||
this.n = dkg.getN();
|
||||
this.t = dkg.getT();
|
||||
this.id = dkg.getId();
|
||||
|
||||
this.messageHandler = new MessageHandler();
|
||||
mailHandler.setMessageHandler(this.messageHandler);
|
||||
this.user = network.connect(mailHandler,dkg.getId());
|
||||
this.parties = dkg.getParties();
|
||||
this.QUAL = null;
|
||||
this.commitments = null;
|
||||
this.share = null;
|
||||
this.y = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected void stage1() {
|
||||
dkg.broadcastCommitments(user);
|
||||
dkg.sendSecrets(user);
|
||||
}
|
||||
|
||||
|
||||
protected void waitUntilStageOneCompleted(){
|
||||
// all parties send their share or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
while (parties[i].share == null && !parties[i].aborted){
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
// all parties broadcast their commitments or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
for (int k = 0 ; k <= t ; k++) {
|
||||
while (parties[i].commitments[k] == null && !parties[i].aborted) {
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares he received
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
* Pj broadcasts done message at the end of this stage
|
||||
*/
|
||||
protected void stage2(){
|
||||
dkg.broadcastComplaints(user);
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
user.broadcast(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
}
|
||||
|
||||
|
||||
protected void waitUntilStageTwoCompleted(){
|
||||
// all parties done or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
while (!parties[i].doneFlag && !parties[i].aborted){
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage3 according to the protocol
|
||||
* 1. if more than t players complain against a player Pi he is disqualified.
|
||||
* otherwise Pi broadcasts the share Sij for each complaining player Pj.
|
||||
* 2. if any of the revealed shares fails the verification test, player Pi is disqualified.
|
||||
* set QUAL to be the set of non-disqualified players.
|
||||
*/
|
||||
protected void stage3(){
|
||||
dkg.answerAllComplainingPlayers(user);
|
||||
// wait until there is no complaint waiting for answer
|
||||
for (int i = 0; i < n; i++){
|
||||
for (int j = 0; j < n; j++){
|
||||
while (parties[i].complaints[j].equals(ComplaintState.Waiting) && !parties[i].aborted){
|
||||
try {
|
||||
Thread.sleep(SleepTime);
|
||||
} catch (InterruptedException e) {
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.QUAL = dkg.calcQUAL();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected void stage4(){
|
||||
this.y = dkg.calcY(QUAL);
|
||||
this.commitments = dkg.calcCommitments(QUAL);
|
||||
this.share = dkg.calcShare(QUAL);
|
||||
}
|
||||
|
||||
protected void startReceiver(){
|
||||
user.getReceiverThread().start();
|
||||
}
|
||||
protected void stopReceiver(){
|
||||
user.getReceiverThread().interrupt();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
startReceiver();
|
||||
stage1();
|
||||
waitUntilStageOneCompleted();
|
||||
stage2();
|
||||
waitUntilStageTwoCompleted();
|
||||
stage3();
|
||||
stage4();
|
||||
stopReceiver();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the current run loop to exit gracefully
|
||||
*/
|
||||
public void stop() {
|
||||
// TODO: implement
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger[] getCommitments() {
|
||||
return Arrays.copyOf(commitments, commitments.length);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getGenerator() {
|
||||
return g;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Group<BigInteger> getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Polynomial.Point getShare() {
|
||||
return share;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getT() {
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger getPublicValue() {
|
||||
return y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<Integer> getQUAL() {
|
||||
return QUAL;
|
||||
}
|
||||
|
||||
|
||||
protected class MessageHandler implements Communication.MessageHandler{
|
||||
|
||||
/**
|
||||
* commitment message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't sent this commitment before
|
||||
*/
|
||||
protected boolean isValidCommitmentMessage(int sender, boolean isBroadcast, DKGMessages.CommitmentMessage commitmentMessage){
|
||||
int i = sender - 1;
|
||||
int k = commitmentMessage.getK();
|
||||
return isBroadcast && parties[i].commitments[k] == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the commitment
|
||||
*/
|
||||
@Override
|
||||
public void handleCommitmentMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.CommitmentMessage commitmentMessage = (DKGMessages.CommitmentMessage) message;
|
||||
if(isValidCommitmentMessage(sender,isBroadcast,commitmentMessage)){
|
||||
int i = sender - 1;
|
||||
int k = commitmentMessage.getK();
|
||||
parties[i].commitments[k] = extractCommitment(commitmentMessage);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* secret message is valid if:
|
||||
* 1. it was received in private chanel
|
||||
* 2. the sender didn't sent secret message before
|
||||
* 3. secret.i == i
|
||||
* 4. secret.j == id
|
||||
*/
|
||||
protected boolean isValidSecretMessage(int sender, boolean isBroadcast, DKGMessages.SecretMessage secretMessage){
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
if(sender != i || isBroadcast)
|
||||
return false;
|
||||
else
|
||||
return parties[i - 1].share == null && j == id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the secret
|
||||
*/
|
||||
@Override
|
||||
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.SecretMessage secretMessage = (DKGMessages.SecretMessage) message;
|
||||
if(isValidSecretMessage(sender,isBroadcast,secretMessage)) {
|
||||
int i = secretMessage.getI();
|
||||
Polynomial.Point secret = extractSecret(id,secretMessage.getSecret());
|
||||
parties[i - 1].share = secret;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* done message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't sent done message before
|
||||
*/
|
||||
protected boolean isValidDoneMessage(int sender, boolean isBroadcast){
|
||||
return isBroadcast && !parties[sender - 1].doneFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was finished sending all his complaints
|
||||
*/
|
||||
@Override
|
||||
public void handleDoneMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(isValidDoneMessage(sender,isBroadcast)) {
|
||||
parties[sender - 1].doneFlag = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* complaint message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't complained against id before
|
||||
*/
|
||||
protected boolean isValidComplaintMessage(int sender, boolean isBroadcast, DKGMessages.IDMessage complaintMessage){
|
||||
int i = sender;
|
||||
int j = complaintMessage.getId();
|
||||
return isBroadcast && parties[i - 1].complaints[j - 1].equals( ComplaintState.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was complained against id
|
||||
*/
|
||||
@Override
|
||||
public void handleComplaintMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.IDMessage complaintMessage = (DKGMessages.IDMessage)message;
|
||||
if(isValidComplaintMessage(sender,isBroadcast,complaintMessage)){
|
||||
int i = sender;
|
||||
int j = complaintMessage.getId();
|
||||
parties[j - 1].complaints[i - 1] = ComplaintState.Waiting;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* answer message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.i == i
|
||||
* 3. 1 <= secret.j <= n
|
||||
* 4. it is marked that j complained against i and i didn't received
|
||||
*/
|
||||
protected boolean isValidAnswerMessage(int sender, boolean isBroadcast, DKGMessages.SecretMessage secretMessage){
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
if(sender != i || !isBroadcast)
|
||||
return false;
|
||||
else
|
||||
return j >= 1 && j <= n && parties[i - 1].complaints[j - 1].equals(ComplaintState.Waiting);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the secret is valid, marks the complaint as NonDisqualified
|
||||
* else marks it as Disqualified
|
||||
* in case that the complainer is id ( j == id ), saves the secret
|
||||
*/
|
||||
@Override
|
||||
public void handleAnswerMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.SecretMessage secretMessage = (DKGMessages.SecretMessage) message;
|
||||
if(isValidAnswerMessage(sender,isBroadcast,secretMessage)) {
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
Polynomial.Point secret = extractSecret(j,secretMessage.getSecret());
|
||||
if (dkg.isValidSecret(secret, parties[i - 1].commitments, j)) {
|
||||
parties[i - 1].complaints[j - 1] = ComplaintState.NonDisqualified;
|
||||
} else {
|
||||
parties[i - 1].complaints[j - 1] = ComplaintState.Disqualified;
|
||||
}
|
||||
if(j == id){
|
||||
parties[i - 1].share = secret;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was aborted
|
||||
*/
|
||||
@Override
|
||||
public void handleAbortMessage(int sender, boolean isBroadcast, Message message) {
|
||||
parties[sender - 1].aborted = true;
|
||||
}
|
||||
|
||||
public Polynomial.Point extractSecret(int i, ByteString secret){
|
||||
BigInteger x = BigInteger.valueOf(i);
|
||||
BigInteger y = new BigInteger(secret.toByteArray());
|
||||
return new Polynomial.Point(x,y);
|
||||
}
|
||||
|
||||
public BigInteger extractCommitment(DKGMessages.CommitmentMessage commitmentMessage){
|
||||
return new BigInteger(commitmentMessage.getCommitment().toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import Communication.MailHandler;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import com.google.protobuf.ByteString;
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Set;
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.DistributedKeyGeneration.ComplaintState;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
* TODO: Comments
|
||||
* TODO: Replace polling with monitors/wait/notify (remember synchronization)
|
||||
*/
|
||||
public class User<T> implements Runnable{
|
||||
|
||||
protected final DistributedKeyGeneration<T> dkg;
|
||||
|
||||
protected final T g;
|
||||
protected final Group<T> group;
|
||||
protected final int n;
|
||||
protected final int t;
|
||||
protected final int id;
|
||||
protected MailHandler mailHandler;
|
||||
|
||||
protected final Channel channel;
|
||||
protected final Party[] parties;
|
||||
protected Set<Integer> QUAL; // set of all non-disqualified parties
|
||||
protected Polynomial.Point share; // final share of the secrete
|
||||
protected ArrayList<T> commitments; // public verification values
|
||||
protected T y; // final public value
|
||||
|
||||
public User(DistributedKeyGeneration<T> dkg, Channel channel) {
|
||||
this.dkg = dkg;
|
||||
|
||||
this.g = dkg.getGenerator();
|
||||
this.group = dkg.getGroup();
|
||||
this.n = dkg.getN();
|
||||
this.t = dkg.getT();
|
||||
this.id = dkg.getId();
|
||||
|
||||
this.channel = channel;
|
||||
dkg.setChannel(channel);
|
||||
registerReceiverCallback();
|
||||
|
||||
this.parties = dkg.getParties();
|
||||
this.QUAL = null;
|
||||
this.commitments = null;
|
||||
this.share = null;
|
||||
this.y = null;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* create MailHandler and register it as ReceiverCallback
|
||||
*/
|
||||
protected void registerReceiverCallback(){
|
||||
this.mailHandler = new DistributedKeyGenerationMailHandler(new MessageHandler());
|
||||
channel.registerReceiverCallback(mailHandler);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
*/
|
||||
protected void stage1() {
|
||||
dkg.broadcastCommitments();
|
||||
dkg.sendSecrets();
|
||||
}
|
||||
|
||||
|
||||
protected void waitUntilStageOneCompleted(){
|
||||
// all parties send their share or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
synchronized (parties[i]) {
|
||||
while (parties[i].share == null && !parties[i].aborted) {
|
||||
try {
|
||||
parties[i].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// all parties broadcast their commitments or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
for (int k = 0 ; k <= t ; k++) {
|
||||
synchronized (parties[i]) {
|
||||
while (parties[i].commitments.get(k) == null && !parties[i].aborted) {
|
||||
try {
|
||||
parties[i].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* stage2 according to the protocol
|
||||
* Pj verifies all the shares he received
|
||||
* if check fails for an index i, Pj broadcasts a complaint against Pi.
|
||||
* Pj broadcasts done message at the end of this stage
|
||||
*/
|
||||
protected void stage2(){
|
||||
dkg.broadcastComplaints();
|
||||
//broadcast done message after all complaints
|
||||
DKGMessages.EmptyMessage doneMessage = DKGMessages.EmptyMessage.newBuilder().build();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.DONE,doneMessage);
|
||||
}
|
||||
|
||||
|
||||
protected void waitUntilStageTwoCompleted(){
|
||||
// all parties done or aborted
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
synchronized (parties[i]) {
|
||||
while (!parties[i].doneFlag && !parties[i].aborted) {
|
||||
try {
|
||||
parties[i].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* stage3 according to the protocol
|
||||
* 1. if more than t players complain against a player Pi he is disqualified.
|
||||
* otherwise Pi broadcasts the share Sij for each complaining player Pj.
|
||||
* 2. if any of the revealed shares fails the verification test, player Pi is disqualified.
|
||||
* set QUAL to be the set of non-disqualified players.
|
||||
*/
|
||||
protected void stage3(){
|
||||
dkg.answerAllComplainingPlayers();
|
||||
// wait until there is no complaint waiting for answer
|
||||
for (int i = 0; i < n; i++){
|
||||
for (int j = 0; j < n; j++){
|
||||
synchronized (parties[i]) {
|
||||
while (parties[i].complaints[j].equals(ComplaintState.Waiting) && !parties[i].aborted) {
|
||||
try {
|
||||
parties[i].wait();
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
this.QUAL = dkg.calcQUAL();
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected void stage4(){
|
||||
this.y = dkg.calcY(QUAL);
|
||||
this.commitments = dkg.calcCommitments(QUAL);
|
||||
this.share = dkg.calcShare(QUAL);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
stage1();
|
||||
waitUntilStageOneCompleted();
|
||||
stage2();
|
||||
waitUntilStageTwoCompleted();
|
||||
stage3();
|
||||
stage4();
|
||||
}
|
||||
|
||||
/**
|
||||
* Request the current run loop to exit gracefully
|
||||
*/
|
||||
public void stop() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return commitments
|
||||
*/
|
||||
public ArrayList<T> getCommitments() {
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return g
|
||||
*/
|
||||
public T getGenerator() {
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return group
|
||||
*/
|
||||
public Group<T> getGroup() {
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return share
|
||||
*/
|
||||
public Polynomial.Point getShare() {
|
||||
return share;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return id
|
||||
*/
|
||||
public int getID() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return n
|
||||
*/
|
||||
public int getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return t
|
||||
*/
|
||||
public int getT() {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return y
|
||||
*/
|
||||
public T getPublicValue() {
|
||||
return y;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return QUAL
|
||||
*/
|
||||
public Set<Integer> getQUAL() {
|
||||
return QUAL;
|
||||
}
|
||||
|
||||
|
||||
public class MessageHandler implements Communication.MessageHandler{
|
||||
|
||||
public MessageHandler(){
|
||||
|
||||
}
|
||||
/**
|
||||
* commitment message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't sent this commitment before
|
||||
*/
|
||||
protected boolean isValidCommitmentMessage(int sender, boolean isBroadcast, DKGMessages.CommitmentMessage commitmentMessage){
|
||||
int i = sender - 1;
|
||||
int k = commitmentMessage.getK();
|
||||
return isBroadcast && parties[i].commitments.get(k) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the commitment
|
||||
*/
|
||||
@Override
|
||||
public void handleCommitmentMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.CommitmentMessage commitmentMessage = (DKGMessages.CommitmentMessage) message;
|
||||
if(isValidCommitmentMessage(sender,isBroadcast,commitmentMessage)){
|
||||
int i = sender - 1;
|
||||
int k = commitmentMessage.getK();
|
||||
synchronized (parties[i]) {
|
||||
parties[i].commitments.set(k, extractCommitment(commitmentMessage));
|
||||
parties[i].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* secret message is valid if:
|
||||
* 1. it was received in private chanel
|
||||
* 2. the sender didn't sent secret message before
|
||||
* 3. secret.i == i
|
||||
* 4. secret.j == id
|
||||
*/
|
||||
protected boolean isValidSecretMessage(int sender, boolean isBroadcast, DKGMessages.ShareMessage secretMessage){
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
if(sender != i || isBroadcast)
|
||||
return false;
|
||||
else
|
||||
return parties[i - 1].share == null && j == id;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* saves the secret
|
||||
*/
|
||||
@Override
|
||||
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.ShareMessage secretMessage = (DKGMessages.ShareMessage) message;
|
||||
if(isValidSecretMessage(sender,isBroadcast,secretMessage)) {
|
||||
int i = secretMessage.getI();
|
||||
Polynomial.Point secret = extractShare(id,secretMessage.getSecret());
|
||||
synchronized (parties[i -1]) {
|
||||
parties[i - 1].share = secret;
|
||||
parties[i - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* done message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't sent done message before
|
||||
*/
|
||||
protected boolean isValidDoneMessage(int sender, boolean isBroadcast){
|
||||
return isBroadcast && !parties[sender - 1].doneFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was finished sending all his complaints
|
||||
*/
|
||||
@Override
|
||||
public void handleDoneMessage(int sender, boolean isBroadcast, Message message) {
|
||||
if(isValidDoneMessage(sender,isBroadcast)) {
|
||||
synchronized (parties[sender - 1]) {
|
||||
parties[sender - 1].doneFlag = true;
|
||||
parties[sender - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* complaint message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. the sender didn't complained against id before
|
||||
*/
|
||||
protected boolean isValidComplaintMessage(int sender, boolean isBroadcast, DKGMessages.IDMessage complaintMessage){
|
||||
int i = sender;
|
||||
int j = complaintMessage.getId();
|
||||
return isBroadcast && parties[i - 1].complaints[j - 1].equals( ComplaintState.OK);
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was complained against id
|
||||
*/
|
||||
@Override
|
||||
public void handleComplaintMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.IDMessage complaintMessage = (DKGMessages.IDMessage)message;
|
||||
if(isValidComplaintMessage(sender,isBroadcast,complaintMessage)){
|
||||
int i = sender;
|
||||
int j = complaintMessage.getId();
|
||||
synchronized (parties[j - 1]) {
|
||||
parties[j - 1].complaints[i - 1] = ComplaintState.Waiting;
|
||||
parties[j - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* answer message is valid if:
|
||||
* 1. it was received in broadcast chanel
|
||||
* 2. secret.i == i
|
||||
* 3. 1 <= secret.j <= n
|
||||
* 4. it is marked that j complained against i and i didn't received
|
||||
*/
|
||||
protected boolean isValidAnswerMessage(int sender, boolean isBroadcast, DKGMessages.ShareMessage secretMessage){
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
if(sender != i || !isBroadcast)
|
||||
return false;
|
||||
else
|
||||
return j >= 1 && j <= n && parties[i - 1].complaints[j - 1].equals(ComplaintState.Waiting);
|
||||
}
|
||||
|
||||
/**
|
||||
* if the secret is valid, marks the complaint as NonDisqualified
|
||||
* else marks it as Disqualified
|
||||
* in case that the complainer is id ( j == id ), saves the secret
|
||||
*/
|
||||
@Override
|
||||
public void handleAnswerMessage(int sender, boolean isBroadcast, Message message) {
|
||||
DKGMessages.ShareMessage secretMessage = (DKGMessages.ShareMessage) message;
|
||||
if(isValidAnswerMessage(sender,isBroadcast,secretMessage)) {
|
||||
int i = secretMessage.getI();
|
||||
int j = secretMessage.getJ();
|
||||
Polynomial.Point secret = extractShare(j,secretMessage.getSecret());
|
||||
synchronized (parties[i - 1]) {
|
||||
if (dkg.isValidShare(secret, parties[i - 1].commitments, j)) {
|
||||
parties[i - 1].complaints[j - 1] = ComplaintState.NonDisqualified;
|
||||
} else {
|
||||
parties[i - 1].complaints[j - 1] = ComplaintState.Disqualified;
|
||||
}
|
||||
if (j == id) {
|
||||
parties[i - 1].share = secret;
|
||||
}
|
||||
parties[i - 1].notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* marks that the sender was aborted
|
||||
*/
|
||||
@Override
|
||||
public void handleAbortMessage(int sender, boolean isBroadcast, Message message) {
|
||||
synchronized (parties[sender - 1]) {
|
||||
parties[sender - 1].aborted = true;
|
||||
parties[sender - 1].notify();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* extract share value from ByteString
|
||||
* @param i
|
||||
* @param share
|
||||
* @return new Point (i,share)
|
||||
*/
|
||||
public Polynomial.Point extractShare(int i, ByteString share){
|
||||
BigInteger x = BigInteger.valueOf(i);
|
||||
BigInteger y = new BigInteger(share.toByteArray());
|
||||
return new Polynomial.Point(x,y);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param commitmentMessage
|
||||
* @return
|
||||
*/
|
||||
public T extractCommitment(DKGMessages.CommitmentMessage commitmentMessage){
|
||||
return dkg.decodeCommitment(commitmentMessage.getCommitment().toByteArray());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package meerkat.crypto.concrete.secret_shring.feldman_verifiable;
|
||||
|
||||
import meerkat.crypto.concrete.secret_shring.ShamirSecretSharing.Polynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.ShamirSecretSharing.SecretSharing;
|
||||
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*
|
||||
* an implementation of Feldman's verifiable secret sharing scheme.
|
||||
*
|
||||
* allows trusted dealer to share a key x among n parties.
|
||||
*
|
||||
*/
|
||||
public class VerifiableSecretSharing<T> extends SecretSharing {
|
||||
protected final Group<T> group;
|
||||
protected final T g; // public generator of group
|
||||
protected final ArrayList<T> commitmentsArrayList;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param q a large 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 zi secret, chosen from Zq
|
||||
* @param random use for generate random polynomial
|
||||
* @param group
|
||||
* @param q a large prime dividing group order.
|
||||
* @param g a generator of cyclic group of order q.
|
||||
* the generated group is a subgroup of the given group.
|
||||
* it must be chosen such that computing discrete logarithms is hard in this group.
|
||||
*/
|
||||
public VerifiableSecretSharing(int t, int n, BigInteger zi, Random random, BigInteger q, T g
|
||||
, Group<T> group) {
|
||||
super(t, n, zi, random,q);
|
||||
this.g = g;
|
||||
this.group = group;
|
||||
assert (this.group.contains(g));
|
||||
this.commitmentsArrayList = generateCommitments();
|
||||
}
|
||||
|
||||
/**
|
||||
* commitments[i] = g ^ polynomial.coefficients[i]
|
||||
* @return commitments
|
||||
*/
|
||||
private ArrayList<T> generateCommitments() {
|
||||
|
||||
Polynomial polynomial = getPolynomial();
|
||||
BigInteger[] coefficients = polynomial.getCoefficients();
|
||||
ArrayList<T> commitments = new ArrayList<T>(t + 1);
|
||||
for (int i = 0 ; i <= t;i++){
|
||||
commitments.add(i,group.multiply(g,coefficients[i]));
|
||||
}
|
||||
return commitments;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compute verification value (g^{share value}) using coefficient commitments sent by dealer and my share id.
|
||||
* @param j my share holder id
|
||||
* @param commitments commitments to polynomial coefficients of share (received from dealer)
|
||||
* @param group
|
||||
*
|
||||
* @return product of Aik ^ (j ^ k) == g ^ polynomial(i)
|
||||
*/
|
||||
public static <T> T computeVerificationValue(int j, ArrayList<T> commitments, Group<T> group) {
|
||||
T v = group.zero();
|
||||
BigInteger power = BigInteger.ONE;
|
||||
BigInteger J = BigInteger.valueOf(j);
|
||||
for (int k = 0 ; k < commitments.size() ; k ++){
|
||||
v = group.add(v,group.multiply(commitments.get(k),power));
|
||||
power = power.multiply(J);
|
||||
}
|
||||
return v;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return generator of group
|
||||
*/
|
||||
public T getGenerator() {
|
||||
return g;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return group
|
||||
*/
|
||||
public Group<T> getGroup(){
|
||||
return group;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return commitmentsArrayList
|
||||
*/
|
||||
public ArrayList<T> getCommitmentsArrayList() {
|
||||
return commitmentsArrayList;
|
||||
}
|
||||
|
||||
}
|
|
@ -1,66 +1,66 @@
|
|||
package ShamirSecretSharing;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/28/2016.
|
||||
*
|
||||
* container of lagrange polynomial
|
||||
*
|
||||
* Constructor is private (use {@link #lagrangePolynomials(Polynomial.Point[], Arithmetic)} to construct)
|
||||
*
|
||||
* l = (evaluate/divisor)* polynomial
|
||||
*
|
||||
* Note : image and divisor stored separately for avoiding lose of information by division
|
||||
*/
|
||||
class LagrangePolynomial{
|
||||
public final Polynomial polynomial;
|
||||
public final BigInteger image;
|
||||
public final BigInteger divisor;
|
||||
|
||||
/**
|
||||
* inner constructor, stores all given parameters
|
||||
* @param polynomial
|
||||
* @param image
|
||||
* @param divisor
|
||||
*/
|
||||
private LagrangePolynomial(Polynomial polynomial, BigInteger image, BigInteger divisor) {
|
||||
this.polynomial = polynomial;
|
||||
this.image = image;
|
||||
this.divisor = divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* in case there exists i != j s.t points[i].x == points[j].x returns null.
|
||||
*/
|
||||
public static LagrangePolynomial[] lagrangePolynomials(Polynomial.Point[] points,Arithmetic<BigInteger> arithmetic) {
|
||||
Polynomial one = new Polynomial(new BigInteger[]{BigInteger.ONE},arithmetic);
|
||||
LagrangePolynomial[] lagrangePolynomials = new LagrangePolynomial[points.length];
|
||||
Polynomial[] factors = new Polynomial[points.length];
|
||||
for (int i = 0 ; i < factors.length ; i++){
|
||||
factors[i] = new Polynomial(new BigInteger[]{points[i].x.negate(),BigInteger.ONE},arithmetic); // X - Xi
|
||||
}
|
||||
Polynomial product;
|
||||
BigInteger divisor;
|
||||
for(int i = 0; i < points.length; i ++) {
|
||||
product = one;
|
||||
divisor = BigInteger.ONE;
|
||||
for (int j = 0; j < points.length; j++) {
|
||||
if (i != j) {
|
||||
divisor = arithmetic.mul(divisor,arithmetic.sub(points[i].x,points[j].x));
|
||||
product = product.mul(factors[j]);
|
||||
}
|
||||
}
|
||||
if(divisor.equals(BigInteger.ZERO))
|
||||
return null;
|
||||
lagrangePolynomials[i] = new LagrangePolynomial(product,points[i].y,divisor);
|
||||
}
|
||||
return lagrangePolynomials;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/28/2016.
|
||||
*
|
||||
* container of lagrange polynomial
|
||||
*
|
||||
* Constructor is private (use {@link #lagrangePolynomials(Polynomial.Point[], Arithmetic)} to construct)
|
||||
*
|
||||
* l = (evaluate/divisor)* polynomial
|
||||
*
|
||||
* Note : image and divisor stored separately for avoiding lose of information by division
|
||||
*/
|
||||
class LagrangePolynomial{
|
||||
public final Polynomial polynomial;
|
||||
public final BigInteger image;
|
||||
public final BigInteger divisor;
|
||||
|
||||
/**
|
||||
* inner constructor, stores all given parameters
|
||||
* @param polynomial
|
||||
* @param image
|
||||
* @param divisor
|
||||
*/
|
||||
private LagrangePolynomial(Polynomial polynomial, BigInteger image, BigInteger divisor) {
|
||||
this.polynomial = polynomial;
|
||||
this.image = image;
|
||||
this.divisor = divisor;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* in case there exists i != j s.t points[i].x == points[j].x returns null.
|
||||
*/
|
||||
public static LagrangePolynomial[] lagrangePolynomials(Polynomial.Point[] points,Arithmetic<BigInteger> arithmetic) {
|
||||
Polynomial one = new Polynomial(new BigInteger[]{BigInteger.ONE},arithmetic);
|
||||
LagrangePolynomial[] lagrangePolynomials = new LagrangePolynomial[points.length];
|
||||
Polynomial[] factors = new Polynomial[points.length];
|
||||
for (int i = 0 ; i < factors.length ; i++){
|
||||
factors[i] = new Polynomial(new BigInteger[]{points[i].x.negate(),BigInteger.ONE},arithmetic); // X - Xi
|
||||
}
|
||||
Polynomial product;
|
||||
BigInteger divisor;
|
||||
for(int i = 0; i < points.length; i ++) {
|
||||
product = one;
|
||||
divisor = BigInteger.ONE;
|
||||
for (int j = 0; j < points.length; j++) {
|
||||
if (i != j) {
|
||||
divisor = arithmetic.mul(divisor,arithmetic.sub(points[i].x,points[j].x));
|
||||
product = product.mul(factors[j]);
|
||||
}
|
||||
}
|
||||
if(divisor.equals(BigInteger.ZERO))
|
||||
return null;
|
||||
lagrangePolynomials[i] = new LagrangePolynomial(product,points[i].y,divisor);
|
||||
}
|
||||
return lagrangePolynomials;
|
||||
}
|
||||
}
|
|
@ -1,208 +1,208 @@
|
|||
package ShamirSecretSharing;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class Polynomial implements Comparable<Polynomial> {
|
||||
private final int degree;
|
||||
private final BigInteger[] coefficients;
|
||||
private final Arithmetic<BigInteger> arithmetic;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param coefficients
|
||||
* @param arithmetic
|
||||
* degree set as max index such that coefficients[degree] not equals zero
|
||||
*/
|
||||
public Polynomial(BigInteger[] coefficients,Arithmetic<BigInteger> arithmetic) {
|
||||
int d = coefficients.length - 1;
|
||||
while (d > 0 && coefficients[d].equals(BigInteger.ZERO)){
|
||||
d--;
|
||||
}
|
||||
this.degree = d;
|
||||
this.coefficients = coefficients;
|
||||
this.arithmetic = arithmetic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare to another polynomial (order by degree, then coefficients).
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Polynomial other) {
|
||||
if (this.degree != other.degree)
|
||||
return this.degree - other.degree;
|
||||
int compare;
|
||||
for (int i = degree; i >= degree ; i--){
|
||||
compare = this.coefficients[i].compareTo(other.coefficients[i]);
|
||||
if (compare != 0){
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @return sum of coefficients[i] * (x ^ i)
|
||||
*/
|
||||
public BigInteger evaluate(BigInteger x){
|
||||
BigInteger result = BigInteger.ZERO;
|
||||
BigInteger power = BigInteger.ONE;
|
||||
for(int i = 0 ; i <= degree ; i++){
|
||||
result = arithmetic.add(result,arithmetic.mul(coefficients[i],power));
|
||||
power = power.multiply(x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param points
|
||||
* @return polynomial of minimal degree which goes through all points.
|
||||
* If there exists i != j s.t points[i].x == points[j].x, method returns null.
|
||||
*/
|
||||
public static Polynomial interpolation(Point[] points, Arithmetic<BigInteger> arithmetic) {
|
||||
LagrangePolynomial[] l = LagrangePolynomial.lagrangePolynomials(points,arithmetic);
|
||||
if (l == null){
|
||||
return null;
|
||||
}
|
||||
// product = product of l[i].divisor
|
||||
BigInteger product = BigInteger.ONE;
|
||||
for (int i = 0; i < l.length;i++){
|
||||
product = arithmetic.mul(product,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];
|
||||
for (int i = 0; i < l.length;i++){
|
||||
factors[i] = arithmetic.div(product,l[i].divisor);
|
||||
}
|
||||
int degree = l[0].polynomial.degree;
|
||||
|
||||
// coefficients[j] = (sum of l[i].evaluate * factor[i] * l[i].coefficients[j] s.t i!=j) divide by product =
|
||||
// = sum of l[i].evaluate * l[i].coefficients[j] / l[i].divisor s.t i!=j
|
||||
BigInteger[] coefficients = new BigInteger[degree + 1];
|
||||
for (int j = 0; j < coefficients.length;j++){
|
||||
coefficients[j] = BigInteger.ZERO;
|
||||
for (int i = 0; i < l.length; i++){
|
||||
BigInteger current = arithmetic.mul(l[i].image,factors[i]);
|
||||
current = arithmetic.mul(current,l[i].polynomial.coefficients[j]);
|
||||
coefficients[j] = arithmetic.add(coefficients[j],current);
|
||||
}
|
||||
coefficients[j] = arithmetic.div(coefficients[j],product);
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return new ShamirSecretSharing.PolynomialTests of degree max(this degree,other degree) s.t for all x in Z
|
||||
* new.evaluate(x) = this.evaluate(x) + other.evaluate(x)
|
||||
*/
|
||||
public Polynomial add(Polynomial other){
|
||||
Polynomial bigger,smaller;
|
||||
if(this.degree < other.degree){
|
||||
bigger = other;
|
||||
smaller = this;
|
||||
}else{
|
||||
bigger = this;
|
||||
smaller = other;
|
||||
}
|
||||
BigInteger[] coefficients = bigger.getCoefficients();
|
||||
|
||||
for (int i = 0; i <= smaller.degree ; i++){
|
||||
coefficients[i] = arithmetic.add(smaller.coefficients[i],bigger.coefficients[i]);
|
||||
}
|
||||
return new Polynomial(coefficients,other.arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constant
|
||||
* @return new Polynomial of degree this.degree s.t for all x in Z
|
||||
* new.evaluate(x) = constant * this.evaluate(x)
|
||||
*/
|
||||
public Polynomial mul(BigInteger constant){
|
||||
|
||||
BigInteger[] coefficients = this.getCoefficients();
|
||||
|
||||
for (int i = 0; i <= this.degree ; i++){
|
||||
coefficients[i] = arithmetic.mul(constant,coefficients[i]);
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return new Polynomial of degree this degree + other degree + 1 s.t for all x in Z
|
||||
* new.evaluate(x) = this.evaluate(x) * other.evaluate(x)
|
||||
*/
|
||||
public Polynomial mul(Polynomial other){
|
||||
|
||||
BigInteger[] coefficients = new BigInteger[this.degree + other.degree + 1];
|
||||
Arrays.fill(coefficients,BigInteger.ZERO);
|
||||
|
||||
for (int i = 0; i <= this.degree ; i++){
|
||||
for (int j = 0; j <= other.degree; j++){
|
||||
coefficients[i+j] = arithmetic.add(coefficients[i+j],arithmetic.mul(this.coefficients[i],other.coefficients[j]));
|
||||
}
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
|
||||
/** getter
|
||||
* @return copy of coefficients
|
||||
*/
|
||||
public BigInteger[] getCoefficients() {
|
||||
return Arrays.copyOf(coefficients,coefficients.length);
|
||||
}
|
||||
|
||||
/** getter
|
||||
* @return degree
|
||||
*/
|
||||
public int getDegree() {
|
||||
return degree;
|
||||
}
|
||||
|
||||
/**
|
||||
* inner class
|
||||
* container for (x,y) x from range and y from evaluate of polynomial
|
||||
*/
|
||||
public static class Point implements java.io.Serializable {
|
||||
public final BigInteger x;
|
||||
public final BigInteger y;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param x
|
||||
* @param polynomial y = polynomial.evaluate(x)
|
||||
*/
|
||||
public Point(BigInteger x, Polynomial polynomial) {
|
||||
this.x = x;
|
||||
this.y = polynomial.evaluate(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
public Point(BigInteger x,BigInteger y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!super.equals(obj))
|
||||
return false;
|
||||
Point other = (Point)obj;
|
||||
return this.x.equals(other.x) && this.y.equals(other.y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class Polynomial implements Comparable<Polynomial> {
|
||||
private final int degree;
|
||||
private final BigInteger[] coefficients;
|
||||
private final Arithmetic<BigInteger> arithmetic;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param coefficients
|
||||
* @param arithmetic
|
||||
* degree set as max index such that coefficients[degree] not equals zero
|
||||
*/
|
||||
public Polynomial(BigInteger[] coefficients,Arithmetic<BigInteger> arithmetic) {
|
||||
int d = coefficients.length - 1;
|
||||
while (d > 0 && coefficients[d].equals(BigInteger.ZERO)){
|
||||
d--;
|
||||
}
|
||||
this.degree = d;
|
||||
this.coefficients = coefficients;
|
||||
this.arithmetic = arithmetic;
|
||||
}
|
||||
|
||||
/**
|
||||
* Compare to another polynomial (order by degree, then coefficients).
|
||||
*/
|
||||
@Override
|
||||
public int compareTo(Polynomial other) {
|
||||
if (this.degree != other.degree)
|
||||
return this.degree - other.degree;
|
||||
int compare;
|
||||
for (int i = degree; i >= degree ; i--){
|
||||
compare = this.coefficients[i].compareTo(other.coefficients[i]);
|
||||
if (compare != 0){
|
||||
return compare;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @return sum of coefficients[i] * (x ^ i)
|
||||
*/
|
||||
public BigInteger evaluate(BigInteger x){
|
||||
BigInteger result = BigInteger.ZERO;
|
||||
BigInteger power = BigInteger.ONE;
|
||||
for(int i = 0 ; i <= degree ; i++){
|
||||
result = arithmetic.add(result,arithmetic.mul(coefficients[i],power));
|
||||
power = power.multiply(x);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param points
|
||||
* @return polynomial of minimal degree which goes through all points.
|
||||
* If there exists i != j s.t points[i].x == points[j].x, method returns null.
|
||||
*/
|
||||
public static Polynomial interpolation(Point[] points, Arithmetic<BigInteger> arithmetic) {
|
||||
LagrangePolynomial[] l = LagrangePolynomial.lagrangePolynomials(points,arithmetic);
|
||||
if (l == null){
|
||||
return null;
|
||||
}
|
||||
// product = product of l[i].divisor
|
||||
BigInteger product = BigInteger.ONE;
|
||||
for (int i = 0; i < l.length;i++){
|
||||
product = arithmetic.mul(product,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];
|
||||
for (int i = 0; i < l.length;i++){
|
||||
factors[i] = arithmetic.div(product,l[i].divisor);
|
||||
}
|
||||
int degree = l[0].polynomial.degree;
|
||||
|
||||
// coefficients[j] = (sum of l[i].evaluate * factor[i] * l[i].coefficients[j] s.t i!=j) divide by product =
|
||||
// = sum of l[i].evaluate * l[i].coefficients[j] / l[i].divisor s.t i!=j
|
||||
BigInteger[] coefficients = new BigInteger[degree + 1];
|
||||
for (int j = 0; j < coefficients.length;j++){
|
||||
coefficients[j] = BigInteger.ZERO;
|
||||
for (int i = 0; i < l.length; i++){
|
||||
BigInteger current = arithmetic.mul(l[i].image,factors[i]);
|
||||
current = arithmetic.mul(current,l[i].polynomial.coefficients[j]);
|
||||
coefficients[j] = arithmetic.add(coefficients[j],current);
|
||||
}
|
||||
coefficients[j] = arithmetic.div(coefficients[j],product);
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return new meerkat.crypto.concrete.secret_shring.shamir.Polynomial of degree max(this degree,other degree) s.t for all x
|
||||
* new.evaluate(x) = this.evaluate(x) + other.evaluate(x)
|
||||
*/
|
||||
public Polynomial add(Polynomial other){
|
||||
Polynomial bigger,smaller;
|
||||
if(this.degree < other.degree){
|
||||
bigger = other;
|
||||
smaller = this;
|
||||
}else{
|
||||
bigger = this;
|
||||
smaller = other;
|
||||
}
|
||||
BigInteger[] coefficients = bigger.getCoefficients();
|
||||
|
||||
for (int i = 0; i <= smaller.degree ; i++){
|
||||
coefficients[i] = arithmetic.add(smaller.coefficients[i],bigger.coefficients[i]);
|
||||
}
|
||||
return new Polynomial(coefficients,other.arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param constant
|
||||
* @return new Polynomial of degree this.degree s.t for all x
|
||||
* new.evaluate(x) = constant * this.evaluate(x)
|
||||
*/
|
||||
public Polynomial mul(BigInteger constant){
|
||||
|
||||
BigInteger[] coefficients = this.getCoefficients();
|
||||
|
||||
for (int i = 0; i <= this.degree ; i++){
|
||||
coefficients[i] = arithmetic.mul(constant,coefficients[i]);
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param other
|
||||
* @return new Polynomial of degree this degree + other degree + 1 s.t for all x
|
||||
* new.evaluate(x) = this.evaluate(x) * other.evaluate(x)
|
||||
*/
|
||||
public Polynomial mul(Polynomial other){
|
||||
|
||||
BigInteger[] coefficients = new BigInteger[this.degree + other.degree + 1];
|
||||
Arrays.fill(coefficients,BigInteger.ZERO);
|
||||
|
||||
for (int i = 0; i <= this.degree ; i++){
|
||||
for (int j = 0; j <= other.degree; j++){
|
||||
coefficients[i+j] = arithmetic.add(coefficients[i+j],arithmetic.mul(this.coefficients[i],other.coefficients[j]));
|
||||
}
|
||||
}
|
||||
return new Polynomial(coefficients,arithmetic);
|
||||
}
|
||||
|
||||
|
||||
/** getter
|
||||
* @return copy of coefficients
|
||||
*/
|
||||
public BigInteger[] getCoefficients() {
|
||||
return Arrays.copyOf(coefficients,coefficients.length);
|
||||
}
|
||||
|
||||
/** getter
|
||||
* @return degree
|
||||
*/
|
||||
public int getDegree() {
|
||||
return degree;
|
||||
}
|
||||
|
||||
/**
|
||||
* inner class
|
||||
* container for (x,y) x from range and y from evaluate of polynomial
|
||||
*/
|
||||
public static class Point implements java.io.Serializable {
|
||||
public final BigInteger x;
|
||||
public final BigInteger y;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param x
|
||||
* @param polynomial y = polynomial.evaluate(x)
|
||||
*/
|
||||
public Point(BigInteger x, Polynomial polynomial) {
|
||||
this.x = x;
|
||||
this.y = polynomial.evaluate(x);
|
||||
}
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param x
|
||||
* @param y
|
||||
*/
|
||||
public Point(BigInteger x,BigInteger y) {
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if(!super.equals(obj))
|
||||
return false;
|
||||
Point other = (Point)obj;
|
||||
return this.x.equals(other.x) && this.y.equals(other.y);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,111 +1,111 @@
|
|||
package ShamirSecretSharing;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
import Arithmetics.Fp;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
* an implementation of Shamire's secret sharing scheme
|
||||
*/
|
||||
public class SecretSharing{
|
||||
protected final int t;
|
||||
protected final int n;
|
||||
protected final BigInteger q;
|
||||
protected final Polynomial polynomial;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param q a large 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 x secret, chosen from Zq
|
||||
* @param random use for generate random polynomial
|
||||
*/
|
||||
public SecretSharing(int t, int n, BigInteger x, Random random, BigInteger q) {
|
||||
this.q = q;
|
||||
this.t = t;
|
||||
this.n = n;
|
||||
this.polynomial = generateRandomPolynomial(x,random);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @param random
|
||||
* @return new Polynomial polynomial of degree t ,such that
|
||||
* 1. polynomial(0) = x
|
||||
* 2. polynomial coefficients randomly chosen from Zq (except of coefficients[0] = x)
|
||||
*/
|
||||
private Polynomial generateRandomPolynomial(BigInteger x, Random random) {
|
||||
BigInteger[] coefficients = new BigInteger[t + 1];
|
||||
coefficients[0] = x.mod(q);
|
||||
int bits = q.bitLength();
|
||||
for (int i = 1 ; i <= t; i++ ){
|
||||
coefficients[i] = new BigInteger(bits,random).mod(q);
|
||||
}
|
||||
return new Polynomial(coefficients,new Fp(q));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i in range of [1,...n]
|
||||
*
|
||||
* @return polynomial.evaluate(i)%q
|
||||
*/
|
||||
public Polynomial.Point getShare(int i){
|
||||
assert (i > 0 && i <= n);
|
||||
return new Polynomial.Point(BigInteger.valueOf(i), polynomial);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shares - subset of the original shares
|
||||
*
|
||||
* @return evaluate of interpolation(shares) at x = 0
|
||||
*/
|
||||
public static BigInteger recoverSecret(Polynomial.Point[] shares, Arithmetic<BigInteger> arithmetic) throws Exception {
|
||||
return recoverPolynomial(shares,arithmetic).evaluate(BigInteger.ZERO);
|
||||
}
|
||||
/**
|
||||
* @param shares - subset of the original shares
|
||||
*
|
||||
* @return interpolation(shares)
|
||||
*/
|
||||
public static Polynomial recoverPolynomial(Polynomial.Point[] shares, Arithmetic<BigInteger> arithmetic) {
|
||||
return Polynomial.interpolation(shares,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return threshold
|
||||
*/
|
||||
public int getT() {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return number of share holders
|
||||
*/
|
||||
public int getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return the prime was given in the constructor
|
||||
*/
|
||||
public BigInteger getQ() {
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return the polynomial was generated in constructor
|
||||
*/
|
||||
public Polynomial getPolynomial() {
|
||||
return polynomial;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
* an implementation of Shamire's secret sharing scheme
|
||||
*/
|
||||
public class SecretSharing{
|
||||
protected final int t;
|
||||
protected final int n;
|
||||
protected final BigInteger q;
|
||||
protected final Polynomial polynomial;
|
||||
|
||||
/**
|
||||
* constructor
|
||||
* @param q a large 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 zi secret, chosen from Zq
|
||||
* @param random use for generate random polynomial
|
||||
*/
|
||||
public SecretSharing(int t, int n, BigInteger zi, Random random, BigInteger q) {
|
||||
this.q = q;
|
||||
this.t = t;
|
||||
this.n = n;
|
||||
this.polynomial = generateRandomPolynomial(zi,random);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x
|
||||
* @param random
|
||||
* @return new Polynomial polynomial of degree t ,such that
|
||||
* 1. polynomial(0) = x
|
||||
* 2. polynomial coefficients randomly chosen from Zq (except of coefficients[0] = x)
|
||||
*/
|
||||
private Polynomial generateRandomPolynomial(BigInteger x, Random random) {
|
||||
BigInteger[] coefficients = new BigInteger[t + 1];
|
||||
coefficients[0] = x.mod(q);
|
||||
int bits = q.bitLength();
|
||||
for (int i = 1 ; i <= t; i++ ){
|
||||
coefficients[i] = new BigInteger(bits,random).mod(q);
|
||||
}
|
||||
return new Polynomial(coefficients,new Fp(q));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i in range of [1,...n]
|
||||
*
|
||||
* @return polynomial.evaluate(i)
|
||||
*/
|
||||
public Polynomial.Point getShare(int i){
|
||||
assert (i > 0 && i <= n);
|
||||
return new Polynomial.Point(BigInteger.valueOf(i), polynomial);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param shares - subset of the original shares
|
||||
*
|
||||
* @return evaluate of interpolation(shares) at x = 0
|
||||
*/
|
||||
public static BigInteger recoverSecret(Polynomial.Point[] shares, Arithmetic<BigInteger> arithmetic) {
|
||||
return recoverPolynomial(shares,arithmetic).evaluate(BigInteger.ZERO);
|
||||
}
|
||||
/**
|
||||
* @param shares - subset of the original shares
|
||||
*
|
||||
* @return interpolation(shares)
|
||||
*/
|
||||
public static Polynomial recoverPolynomial(Polynomial.Point[] shares, Arithmetic<BigInteger> arithmetic) {
|
||||
return Polynomial.interpolation(shares,arithmetic);
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return threshold
|
||||
*/
|
||||
public int getT() {
|
||||
return t;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return number of share holders
|
||||
*/
|
||||
public int getN() {
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return the prime was given in the constructor
|
||||
*/
|
||||
public BigInteger getQ() {
|
||||
return q;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* getter
|
||||
* @return the polynomial was generated in constructor
|
||||
*/
|
||||
public Polynomial getPolynomial() {
|
||||
return polynomial;
|
||||
}
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
package Arithmetics;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/17/2016.
|
||||
*/
|
||||
public interface Arithmetic<T> {
|
||||
/**
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
T add(T a, T b);
|
||||
T sub(T a, T b);
|
||||
T mul(T a, T b);
|
||||
T div(T a, T b);
|
||||
|
||||
}
|
||||
package meerkat.crypto.utilitis;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/17/2016.
|
||||
*/
|
||||
public interface Arithmetic<T> {
|
||||
/**
|
||||
*
|
||||
* @param a
|
||||
* @param b
|
||||
* @return
|
||||
*/
|
||||
T add(T a, T b);
|
||||
T sub(T a, T b);
|
||||
T mul(T a, T b);
|
||||
T div(T a, T b);
|
||||
|
||||
}
|
|
@ -0,0 +1,26 @@
|
|||
package meerkat.crypto.utilitis;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* A generic commmunication channel that supports point-to-point and broadcast operation
|
||||
*/
|
||||
|
||||
public interface Channel {
|
||||
public interface ReceiverCallback {
|
||||
public void receiveMail(DKGMessages.Mail mail);
|
||||
}
|
||||
|
||||
public void sendMessage(int destUser, DKGMessages.Mail.Type type, Message msg);
|
||||
|
||||
public void broadcastMessage(DKGMessages.Mail.Type type, Message msg);
|
||||
|
||||
/**
|
||||
* Register a callback to handle received messages.
|
||||
* The callback is called in the <b>Channel</b> thread, so no long processing should
|
||||
* occur in the callback method.
|
||||
* @param callback
|
||||
*/
|
||||
public void registerReceiverCallback(ReceiverCallback callback);
|
||||
}
|
|
@ -1,38 +1,39 @@
|
|||
package Arithmetics;
|
||||
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/17/2016.
|
||||
*/
|
||||
public class Fp implements Arithmetic<BigInteger> {
|
||||
public final BigInteger p;
|
||||
private final Zpstar zp;
|
||||
|
||||
public Fp(BigInteger p) {
|
||||
this.p = p;
|
||||
this.zp = new Zpstar(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger add(BigInteger a, BigInteger b){
|
||||
return a.add(b).mod(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger sub(BigInteger a, BigInteger b){
|
||||
return a.add(p).subtract(b).mod(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger mul(BigInteger a, BigInteger b){
|
||||
return zp.add(a,b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger div(BigInteger a, BigInteger b){
|
||||
return mul(a,zp.negate(b));
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.utilitis.concrete;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/17/2016.
|
||||
*/
|
||||
public class Fp implements Arithmetic<BigInteger> {
|
||||
public final BigInteger p;
|
||||
private final Zpstar zp;
|
||||
|
||||
public Fp(BigInteger p) {
|
||||
this.p = p;
|
||||
this.zp = new Zpstar(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger add(BigInteger a, BigInteger b){
|
||||
return a.add(b).mod(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger sub(BigInteger a, BigInteger b){
|
||||
return a.add(p).subtract(b).mod(p);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger mul(BigInteger a, BigInteger b){
|
||||
return zp.add(a,b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger div(BigInteger a, BigInteger b){
|
||||
return mul(a,zp.negate(b));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
package Utils;
|
||||
|
||||
import com.google.protobuf.Message;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
import java.util.Queue;
|
||||
import java.util.concurrent.ArrayBlockingQueue;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 2/14/2016.
|
||||
*/
|
||||
// TODO: Change nane to network
|
||||
|
||||
public class ChannelImpl implements Channel {
|
||||
|
||||
public static int BROADCAST = 0;
|
||||
private static ChannelImpl[] channels = null;
|
||||
|
||||
protected final Queue<DKGMessages.Mail> mailbox;
|
||||
protected final int id;
|
||||
protected final int n;
|
||||
protected Thread receiverThread;
|
||||
|
||||
|
||||
public ChannelImpl(int id, int n) {
|
||||
if (channels == null){
|
||||
channels = new ChannelImpl[n];
|
||||
}
|
||||
this.mailbox = new ArrayBlockingQueue<DKGMessages.Mail>( n * n * n);
|
||||
this.id = id;
|
||||
this.n = n;
|
||||
channels[id - 1] = this;
|
||||
}
|
||||
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendMessage(int destUser, DKGMessages.Mail.Type type, Message msg) {
|
||||
if(destUser < 1 || destUser > n)
|
||||
return;
|
||||
ChannelImpl channel = channels[destUser - 1];
|
||||
if (channel == null)
|
||||
return;
|
||||
DKGMessages.Mail mail = DKGMessages.Mail.newBuilder()
|
||||
.setSender(id)
|
||||
.setDestination(destUser)
|
||||
.setIsPrivate(true)
|
||||
.setType(type)
|
||||
.setMessage(msg.toByteString())
|
||||
.build();
|
||||
synchronized (channel.mailbox) {
|
||||
channel.mailbox.add(mail);
|
||||
channel.mailbox.notify();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void broadcastMessage(DKGMessages.Mail.Type type,Message msg) {
|
||||
ChannelImpl channel;
|
||||
DKGMessages.Mail mail = DKGMessages.Mail.newBuilder()
|
||||
.setSender(id)
|
||||
.setDestination(BROADCAST)
|
||||
.setIsPrivate(false)
|
||||
.setType(type)
|
||||
.setMessage(msg.toByteString())
|
||||
.build();
|
||||
for (int i = 0 ; i < n ; i++){
|
||||
channel = channels[i];
|
||||
synchronized (channel.mailbox) {
|
||||
channel.mailbox.add(mail);
|
||||
channel.mailbox.notify();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerReceiverCallback(final ReceiverCallback callback) {
|
||||
try{
|
||||
receiverThread.interrupt();
|
||||
}catch (Exception e){
|
||||
//do nothing
|
||||
}
|
||||
receiverThread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true){
|
||||
try {
|
||||
synchronized (mailbox) {
|
||||
while (!mailbox.isEmpty()) {
|
||||
callback.receiveMail(mailbox.remove());
|
||||
}
|
||||
mailbox.wait();
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
//do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
receiverThread.start();
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
|
@ -1,29 +1,30 @@
|
|||
package Arithmetics;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/17/2016.
|
||||
*/
|
||||
public class Z implements Arithmetic<BigInteger> {
|
||||
|
||||
@Override
|
||||
public BigInteger add(BigInteger a, BigInteger b) {
|
||||
return a.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger sub(BigInteger a, BigInteger b) {
|
||||
return a.subtract(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger mul(BigInteger a, BigInteger b) {
|
||||
return a.multiply(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger div(BigInteger a, BigInteger b) {
|
||||
return a.divide(b);
|
||||
}
|
||||
}
|
||||
package Utils;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 4/8/2016.
|
||||
*/
|
||||
public class Z implements Arithmetic<BigInteger> {
|
||||
@Override
|
||||
public BigInteger add(BigInteger a, BigInteger b) {
|
||||
return a.add(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger sub(BigInteger a, BigInteger b) {
|
||||
return a.subtract(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger mul(BigInteger a, BigInteger b) {
|
||||
return a.multiply(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BigInteger div(BigInteger a, BigInteger b) {
|
||||
return a.divide(b);
|
||||
}
|
||||
}
|
|
@ -1,61 +1,62 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Communication.Network;
|
||||
import JointFeldmanProtocol.DistributedKeyGeneration;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/29/2016.
|
||||
*/
|
||||
public class SDKGMaliciousUserImpl extends SecureDistributedKeyGenerationUserImpl {
|
||||
|
||||
private final DistributedKeyGeneration maliciousSDKG;
|
||||
private final Set<Integer> falls;
|
||||
public SDKGMaliciousUserImpl(SecureDistributedKeyGeneration sdkg,SecureDistributedKeyGeneration maliciousSDKG
|
||||
, Network network,Set<Integer> falls) {
|
||||
super(sdkg, network);
|
||||
this.falls = falls;
|
||||
this.maliciousSDKG = maliciousSDKG;
|
||||
maliciousSDKG.setParties(parties);
|
||||
}
|
||||
|
||||
public static SecureDistributedKeyGeneration generateMaliciousSDKG(SecureDistributedKeyGeneration sdkg,Random random){
|
||||
BigInteger q = sdkg.getQ();
|
||||
BigInteger zi = new BigInteger(q.bitLength(), random).mod(q);
|
||||
return new SecureDistributedKeyGeneration(sdkg.getT(),sdkg.getN(),zi,random,sdkg.getQ()
|
||||
,sdkg.getGenerator(),sdkg.getH(),sdkg.getGroup(),sdkg.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage1() {
|
||||
sdkg.broadcastVerificationValues(user);
|
||||
sendSecrets(); //insteadof dkg.sendSecrets(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage3() {
|
||||
stopReceiver();
|
||||
maliciousSDKG.answerAllComplainingPlayers(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage4(){
|
||||
//do nothing
|
||||
}
|
||||
|
||||
private void sendSecrets(){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
if(falls.contains(j)){
|
||||
maliciousSDKG.sendSecret(user,j);
|
||||
}else {
|
||||
sdkg.sendSecret(user, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.DistributedKeyGeneration;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/29/2016.
|
||||
*/
|
||||
public class SDKGMaliciousUserImpl extends SecureDistributedKeyGenerationUser {
|
||||
|
||||
private final DistributedKeyGeneration maliciousSDKG;
|
||||
private final Set<Integer> falls;
|
||||
public SDKGMaliciousUserImpl(SecureDistributedKeyGeneration sdkg, SecureDistributedKeyGeneration maliciousSDKG
|
||||
, Channel channel, Set<Integer> falls) {
|
||||
super(sdkg, channel);
|
||||
this.falls = falls;
|
||||
this.maliciousSDKG = maliciousSDKG;
|
||||
maliciousSDKG.setParties(parties);
|
||||
}
|
||||
|
||||
public static SecureDistributedKeyGeneration generateMaliciousSDKG(SecureDistributedKeyGeneration sdkg,Channel channel,Random random){
|
||||
BigInteger q = sdkg.getQ();
|
||||
BigInteger zi = new BigInteger(q.bitLength(), random).mod(q);
|
||||
SecureDistributedKeyGeneration malicious = new SecureDistributedKeyGeneration(sdkg.getT(),sdkg.getN(),zi,random,sdkg.getQ()
|
||||
,sdkg.getGenerator(),sdkg.getH(),sdkg.getGroup(),sdkg.getId(),sdkg.getEncoder());
|
||||
malicious.setChannel(channel);
|
||||
return malicious;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage1() {
|
||||
sdkg.computeAndBroadcastVerificationValues();
|
||||
sendSecrets(); //insteadof dkg.sendSecrets(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage3() {
|
||||
maliciousSDKG.answerAllComplainingPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage4(){
|
||||
//do nothing
|
||||
}
|
||||
|
||||
private void sendSecrets(){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
if(falls.contains(j)){
|
||||
maliciousSDKG.sendSecret(j);
|
||||
}else {
|
||||
sdkg.sendSecret(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -1,177 +1,181 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
import Arithmetics.Fp;
|
||||
import Communication.Network;
|
||||
import FeldmanVerifiableSecretSharing.VerifiableSecretSharing;
|
||||
import JointFeldmanProtocol.DKGMaliciousUserImpl;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import ShamirSecretSharing.SecretSharing;
|
||||
import UserInterface.DistributedKeyGenerationUser;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/29/2016.
|
||||
*/
|
||||
public class SDKGTest {
|
||||
|
||||
int tests = 10;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
Group<BigInteger> group = new Zpstar(p);
|
||||
Arithmetic<BigInteger> arithmetic = new Fp(q);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
Testable[] testables;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
testables = new Testable[tests];
|
||||
for (int i = 0; i < tests; i++){
|
||||
testables[i] = new Testable(new Random());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(int test) throws Exception {
|
||||
Testable testable = testables[test];
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].join();
|
||||
}
|
||||
|
||||
// got the right public value
|
||||
BigInteger publicValue = group.multiply(testable.g,testable.secret);
|
||||
for (int i: testable.valids){
|
||||
assert (testable.sdkgs[i - 1].getPublicValue().equals(publicValue));
|
||||
}
|
||||
|
||||
// assert valid verification values
|
||||
BigInteger expected,verification;
|
||||
for (int i: testable.valids){
|
||||
expected = group.multiply(testable.g, testable.sdkgs[i - 1].getShare().y);
|
||||
verification = VerifiableSecretSharing.computeVerificationValue(i, testable.sdkgs[i - 1].getCommitments(), group);
|
||||
assert (expected.equals(verification));
|
||||
}
|
||||
|
||||
|
||||
// restore the secret from shares
|
||||
ArrayList<Polynomial.Point> sharesList = new ArrayList<Polynomial.Point>();
|
||||
|
||||
for (int i: testable.valids){
|
||||
sharesList.add(testable.sdkgs[i - 1].getShare());
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[sharesList.size()];
|
||||
for (int i = 0; i < shares.length; i ++){
|
||||
shares[i] = sharesList.get(i);
|
||||
}
|
||||
|
||||
BigInteger calculatedSecret = SecretSharing.recoverSecret(shares,arithmetic);
|
||||
assert (calculatedSecret.equals(testable.secret));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
for (int i = 0; i < tests; i++){
|
||||
oneTest(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Testable{
|
||||
Set<Integer> valids;
|
||||
Set<Integer> QUAL;
|
||||
Set<Integer> aborted;
|
||||
Set<Integer> malicious;
|
||||
DistributedKeyGenerationUser[] sdkgs;
|
||||
Thread[] threads;
|
||||
BigInteger g;
|
||||
BigInteger h;
|
||||
BigInteger secret;
|
||||
|
||||
public Testable(Random random) {
|
||||
this.sdkgs = new SecureDistributedKeyGenerationUserImpl[n];
|
||||
this.valids = new HashSet<Integer>();
|
||||
this.QUAL = new HashSet<Integer>();
|
||||
this.aborted = new HashSet<Integer>();
|
||||
this.malicious = new HashSet<Integer>();
|
||||
this.threads = new Thread[n];
|
||||
this.g = sampleGenerator(random);
|
||||
this.h = group.multiply(g,randomIntModQ(random));
|
||||
ArrayList<Integer> ids = new ArrayList<Integer>();
|
||||
for (int id = 1; id<= n ; id++){
|
||||
ids.add(id);
|
||||
}
|
||||
Network network = new Network(n);
|
||||
int id;
|
||||
BigInteger s;
|
||||
SecureDistributedKeyGeneration sdkg;
|
||||
this.secret = BigInteger.ZERO;
|
||||
while (!ids.isEmpty()) {
|
||||
id = ids.remove(random.nextInt(ids.size()));
|
||||
s = randomIntModQ(random);
|
||||
sdkg = new SecureDistributedKeyGeneration(t, n, s, random, q, g , h, group, id);
|
||||
sdkgs[id - 1] = randomSDKGUser(id,network,sdkg,random);
|
||||
threads[id - 1] = new Thread(sdkgs[id - 1]);
|
||||
if(QUAL.contains(id)){
|
||||
this.secret = this.secret.add(s).mod(q);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SecureDistributedKeyGenerationUserImpl randomSDKGUser(int id,Network network, SecureDistributedKeyGeneration sdkg,Random random){
|
||||
if (QUAL.size() <= t) {
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new SecureDistributedKeyGenerationUserImpl(sdkg,network);
|
||||
}else{
|
||||
int type = random.nextInt(3);
|
||||
switch (type){
|
||||
case 0:// regular
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new SecureDistributedKeyGenerationUserImpl(sdkg,network);
|
||||
case 1:// abort
|
||||
int abortStage = random.nextInt(3) + 1; // 1 or 2 or 3
|
||||
aborted.add(id);
|
||||
if (abortStage > 1){
|
||||
QUAL.add(id);
|
||||
}
|
||||
return new SDKGUserImplAbort(sdkg,network,abortStage);
|
||||
case 2:// malicious
|
||||
malicious.add(id);
|
||||
Set<Integer> falls = DKGMaliciousUserImpl.selectFallsRandomly(valids,random);
|
||||
SecureDistributedKeyGeneration maliciousSDKG = SDKGMaliciousUserImpl.generateMaliciousSDKG(sdkg,random);
|
||||
return new SDKGMaliciousUserImpl(sdkg,maliciousSDKG,network,falls);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger sampleGenerator(Random random){
|
||||
BigInteger ZERO = group.zero();
|
||||
BigInteger g;
|
||||
do {
|
||||
g = group.sample(random);
|
||||
} while (!g.equals(ZERO) && !group.multiply(g, q).equals(ZERO));
|
||||
return g;
|
||||
}
|
||||
|
||||
public BigInteger randomIntModQ(Random random){
|
||||
return new BigInteger(q.bitLength(), random).mod(q);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import Communication.ChannelImpl;
|
||||
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
|
||||
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.DKGMaliciousUser;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing;
|
||||
import Utils.BigIntegerByteEncoder;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
import org.factcenter.qilin.util.ByteEncoder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/29/2016.
|
||||
*/
|
||||
public class SDKGTest {
|
||||
|
||||
int tests = 1;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
Group<BigInteger> group = new Zpstar(p);
|
||||
Arithmetic<BigInteger> arithmetic = new Fp(q);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
Testable[] testables;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
testables = new Testable[tests];
|
||||
for (int i = 0; i < tests; i++){
|
||||
testables[i] = new Testable(new Random());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(int test) throws Exception {
|
||||
Testable testable = testables[test];
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].join();
|
||||
}
|
||||
|
||||
// got the right public value
|
||||
BigInteger publicValue = group.multiply(testable.g,testable.secret);
|
||||
for (int i: testable.valids){
|
||||
assert (testable.sdkgs[i - 1].getPublicValue().equals(publicValue));
|
||||
}
|
||||
|
||||
// assert valid verification values
|
||||
BigInteger expected,verification;
|
||||
for (int i: testable.valids){
|
||||
expected = group.multiply(testable.g, testable.sdkgs[i - 1].getShare().y);
|
||||
verification = VerifiableSecretSharing.computeVerificationValue(i, testable.sdkgs[i - 1].getCommitments(), group);
|
||||
assert (expected.equals(verification));
|
||||
}
|
||||
|
||||
|
||||
// restore the secret from shares
|
||||
ArrayList<Polynomial.Point> sharesList = new ArrayList<Polynomial.Point>();
|
||||
|
||||
for (int i: testable.valids){
|
||||
sharesList.add(testable.sdkgs[i - 1].getShare());
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[sharesList.size()];
|
||||
for (int i = 0; i < shares.length; i ++){
|
||||
shares[i] = sharesList.get(i);
|
||||
}
|
||||
|
||||
BigInteger calculatedSecret = SecretSharing.recoverSecret(shares,arithmetic);
|
||||
assert (calculatedSecret.equals(testable.secret));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
for (int i = 0; i < tests; i++){
|
||||
oneTest(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Testable{
|
||||
Set<Integer> valids;
|
||||
Set<Integer> QUAL;
|
||||
Set<Integer> aborted;
|
||||
Set<Integer> malicious;
|
||||
SecureDistributedKeyGenerationUser[] sdkgs;
|
||||
Thread[] threads;
|
||||
BigInteger g;
|
||||
BigInteger h;
|
||||
BigInteger secret;
|
||||
|
||||
public Testable(Random random) {
|
||||
this.sdkgs = new SecureDistributedKeyGenerationUser[n];
|
||||
this.valids = new HashSet<Integer>();
|
||||
this.QUAL = new HashSet<Integer>();
|
||||
this.aborted = new HashSet<Integer>();
|
||||
this.malicious = new HashSet<Integer>();
|
||||
this.threads = new Thread[n];
|
||||
this.g = sampleGenerator(random);
|
||||
this.h = group.multiply(g,randomIntModQ(random));
|
||||
ArrayList<Integer> ids = new ArrayList<Integer>();
|
||||
for (int id = 1; id<= n ; id++){
|
||||
ids.add(id);
|
||||
}
|
||||
int id;
|
||||
BigInteger s;
|
||||
Channel channel;
|
||||
SecureDistributedKeyGeneration sdkg;
|
||||
this.secret = BigInteger.ZERO;
|
||||
ByteEncoder<BigInteger> encoder = new BigIntegerByteEncoder();
|
||||
while (!ids.isEmpty()) {
|
||||
id = ids.remove(random.nextInt(ids.size()));
|
||||
s = randomIntModQ(random);
|
||||
channel = new ChannelImpl(id,n);
|
||||
sdkg = new SecureDistributedKeyGeneration(t, n, s, random, q, g , h, group, id,encoder);
|
||||
sdkgs[id - 1] = randomSDKGUser(id,channel,sdkg,random);
|
||||
threads[id - 1] = new Thread(sdkgs[id - 1]);
|
||||
if(QUAL.contains(id)){
|
||||
this.secret = this.secret.add(s).mod(q);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SecureDistributedKeyGenerationUser randomSDKGUser(int id, Channel channel, SecureDistributedKeyGeneration sdkg, Random random){
|
||||
if (QUAL.size() <= t) {
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new SecureDistributedKeyGenerationUser(sdkg,channel);
|
||||
}else{
|
||||
int type = random.nextInt(3);
|
||||
switch (type){
|
||||
case 0:// regular
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new SecureDistributedKeyGenerationUser(sdkg,channel);
|
||||
case 1:// abort
|
||||
int abortStage = random.nextInt(3) + 1; // 1 or 2 or 3
|
||||
aborted.add(id);
|
||||
if (abortStage > 1){
|
||||
QUAL.add(id);
|
||||
}
|
||||
return new SDKGUserImplAbort(sdkg,channel,abortStage);
|
||||
case 2:// malicious
|
||||
malicious.add(id);
|
||||
Set<Integer> falls = DKGMaliciousUser.selectFallsRandomly(valids,random);
|
||||
SecureDistributedKeyGeneration maliciousSDKG = SDKGMaliciousUserImpl.generateMaliciousSDKG(sdkg,channel,random);
|
||||
return new SDKGMaliciousUserImpl(sdkg,maliciousSDKG,channel,falls);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger sampleGenerator(Random random){
|
||||
BigInteger ZERO = group.zero();
|
||||
BigInteger g;
|
||||
do {
|
||||
g = group.sample(random);
|
||||
} while (!g.equals(ZERO) && !group.multiply(g, q).equals(ZERO));
|
||||
return g;
|
||||
}
|
||||
|
||||
public BigInteger randomIntModQ(Random random){
|
||||
return new BigInteger(q.bitLength(), random).mod(q);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,65 +1,63 @@
|
|||
package SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem;
|
||||
|
||||
import Communication.Network;
|
||||
import SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem.SecureDistributedKeyGeneration;
|
||||
import SecureDistributedKeyGenerationForDiscreteLogBasedCryptosystem.SecureDistributedKeyGenerationUserImpl;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*/
|
||||
public class SDKGUserImplAbort extends SecureDistributedKeyGenerationUserImpl {
|
||||
|
||||
final int abortStage;
|
||||
int stage;
|
||||
public SDKGUserImplAbort(SecureDistributedKeyGeneration sdkg, Network network, int abortStage) {
|
||||
super(sdkg, network);
|
||||
this.abortStage = abortStage;// 1 - 4
|
||||
this.stage = 1;
|
||||
}
|
||||
|
||||
private void abort(){
|
||||
stopReceiver();
|
||||
user.broadcast(DKGMessages.Mail.Type.ABORT,DKGMessages.EmptyMessage.getDefaultInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage1() {
|
||||
if(stage < abortStage)
|
||||
super.stage1();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage2() {
|
||||
if(stage < abortStage)
|
||||
super.stage2();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage3() {
|
||||
if(stage < abortStage)
|
||||
super.stage3();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
if(stage < abortStage)
|
||||
super.stage4();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*/
|
||||
public class SDKGUserImplAbort extends SecureDistributedKeyGenerationUser {
|
||||
|
||||
final int abortStage;
|
||||
int stage;
|
||||
public SDKGUserImplAbort(SecureDistributedKeyGeneration sdkg, Channel channel, int abortStage) {
|
||||
super(sdkg, channel);
|
||||
this.abortStage = abortStage;// 1 - 4
|
||||
this.stage = 1;
|
||||
}
|
||||
|
||||
private void abort(){
|
||||
//stopReceiver();
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.ABORT,DKGMessages.EmptyMessage.getDefaultInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage1() {
|
||||
if(stage < abortStage)
|
||||
super.stage1();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage2() {
|
||||
if(stage < abortStage)
|
||||
super.stage2();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage3() {
|
||||
if(stage < abortStage)
|
||||
super.stage3();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
if(stage < abortStage)
|
||||
super.stage4();
|
||||
else if(stage == abortStage){
|
||||
abort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
}
|
|
@ -1,72 +1,73 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Communication.MailHandler;
|
||||
import Communication.Network;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/21/2016.
|
||||
*/
|
||||
public class DKGMaliciousUserImpl extends DistributedKeyGenerationUserImpl {
|
||||
|
||||
private final DistributedKeyGeneration maliciousDkg;
|
||||
private final Set<Integer> falls;
|
||||
public DKGMaliciousUserImpl(DistributedKeyGeneration dkg,DistributedKeyGeneration maliciousDKG, Network network,Set<Integer> falls) {
|
||||
super(dkg, network);
|
||||
this.falls = falls;
|
||||
this.maliciousDkg = maliciousDKG;
|
||||
maliciousDKG.setParties(parties);
|
||||
}
|
||||
|
||||
public static Set<Integer> selectFallsRandomly(Set<Integer> ids, Random random){
|
||||
Set<Integer> falls = new HashSet<Integer>();
|
||||
ArrayList<Integer> idsList = new ArrayList<Integer>();
|
||||
for (int id : ids){
|
||||
idsList.add(id);
|
||||
}
|
||||
int fallsSize = random.nextInt(idsList.size()) + 1;// 1 - (n-1)
|
||||
while (falls.size() < fallsSize){
|
||||
falls.add(idsList.remove(random.nextInt(idsList.size())));
|
||||
}
|
||||
return falls;
|
||||
}
|
||||
|
||||
public static DistributedKeyGeneration generateMaliciousDKG(DistributedKeyGeneration dkg,Random random){
|
||||
BigInteger q = dkg.getQ();
|
||||
BigInteger zi = new BigInteger(q.bitLength(), random).mod(q);
|
||||
return new DistributedKeyGeneration(dkg.getT(),dkg.getN(),zi,random,dkg.getQ()
|
||||
,dkg.getGenerator(),dkg.getGroup(),dkg.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage1() {
|
||||
dkg.broadcastCommitments(user);
|
||||
sendSecrets(); //insteadof dkg.sendSecrets(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage3() {
|
||||
maliciousDkg.answerAllComplainingPlayers(user);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage4(){
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private void sendSecrets(){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
if(falls.contains(j)){
|
||||
maliciousDkg.sendSecret(user,j);
|
||||
}else {
|
||||
dkg.sendSecret(user, j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/21/2016.
|
||||
*/
|
||||
public class DKGMaliciousUser extends DistributedKeyGenerationUser {
|
||||
|
||||
private final DistributedKeyGeneration maliciousDkg;
|
||||
private final Set<Integer> falls;
|
||||
public DKGMaliciousUser(DistributedKeyGeneration dkg, DistributedKeyGeneration maliciousDKG, Channel channel, Set<Integer> falls) {
|
||||
super(dkg, channel);
|
||||
this.falls = falls;
|
||||
this.maliciousDkg = maliciousDKG;
|
||||
maliciousDKG.setParties(parties);
|
||||
}
|
||||
|
||||
public static Set<Integer> selectFallsRandomly(Set<Integer> ids, Random random){
|
||||
Set<Integer> falls = new HashSet<Integer>();
|
||||
ArrayList<Integer> idsList = new ArrayList<Integer>();
|
||||
for (int id : ids){
|
||||
idsList.add(id);
|
||||
}
|
||||
int fallsSize = random.nextInt(idsList.size()) + 1;// 1 - (n-1)
|
||||
while (falls.size() < fallsSize){
|
||||
falls.add(idsList.remove(random.nextInt(idsList.size())));
|
||||
}
|
||||
return falls;
|
||||
}
|
||||
|
||||
public static DistributedKeyGeneration generateMaliciousDKG(DistributedKeyGeneration dkg,Channel channel,Random random){
|
||||
BigInteger q = dkg.getQ();
|
||||
BigInteger zi = new BigInteger(q.bitLength(), random).mod(q);
|
||||
DistributedKeyGeneration malicious = new DistributedKeyGeneration(dkg.getT(),dkg.getN(),zi,random,dkg.getQ()
|
||||
,dkg.getGenerator(),dkg.getGroup(),dkg.getId(),dkg.getEncoder());
|
||||
malicious.setChannel(channel);
|
||||
return malicious;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage1() {
|
||||
dkg.broadcastCommitments();
|
||||
sendSecrets(); //insteadof dkg.sendSecrets(channel);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage3() {
|
||||
maliciousDkg.answerAllComplainingPlayers();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stage4(){
|
||||
// do nothing
|
||||
}
|
||||
|
||||
private void sendSecrets(){
|
||||
for (int j = 1; j <= n ; j++){
|
||||
if(j != id){
|
||||
if(falls.contains(j)){
|
||||
maliciousDkg.sendSecret(j);
|
||||
}else {
|
||||
dkg.sendSecret(j);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,175 +1,179 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
import Arithmetics.Fp;
|
||||
import Communication.Network;
|
||||
import FeldmanVerifiableSecretSharing.VerifiableSecretSharing;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import ShamirSecretSharing.SecretSharing;
|
||||
import UserInterface.DistributedKeyGenerationUser;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/21/2016.
|
||||
*/
|
||||
public class DKGTest {
|
||||
|
||||
int tests = 10;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
Group<BigInteger> group = new Zpstar(p);
|
||||
Arithmetic<BigInteger> arithmetic = new Fp(q);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
|
||||
Testable[] testables;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
testables = new Testable[tests];
|
||||
for (int i = 0; i < tests; i++){
|
||||
testables[i] = new Testable(new Random());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(int test) throws Exception {
|
||||
Testable testable = testables[test];
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].join();
|
||||
}
|
||||
|
||||
// got the right public value
|
||||
BigInteger publicValue = group.multiply(testable.g,testable.secret);
|
||||
for (int i: testable.valids){
|
||||
assert (testable.dkgs[i - 1].getPublicValue().equals(publicValue));
|
||||
}
|
||||
|
||||
// assert valid verification values
|
||||
BigInteger expected,verification;
|
||||
for (int i: testable.valids){
|
||||
expected = group.multiply(testable.g, testable.dkgs[i - 1].getShare().y);
|
||||
verification = VerifiableSecretSharing.computeVerificationValue(i, testable.dkgs[i - 1].getCommitments(), group);
|
||||
assert (expected.equals(verification));
|
||||
}
|
||||
|
||||
|
||||
// restore the secret from shares
|
||||
ArrayList<Polynomial.Point> sharesList = new ArrayList<Polynomial.Point>();
|
||||
|
||||
for (int i: testable.valids){
|
||||
sharesList.add(testable.dkgs[i - 1].getShare());
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[sharesList.size()];
|
||||
for (int i = 0; i < shares.length; i ++){
|
||||
shares[i] = sharesList.get(i);
|
||||
}
|
||||
|
||||
BigInteger calculatedSecret = SecretSharing.recoverSecret(shares,arithmetic);
|
||||
assert (calculatedSecret.equals(testable.secret));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
for (int i = 0; i < tests; i++){
|
||||
oneTest(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Testable{
|
||||
Set<Integer> valids;
|
||||
Set<Integer> QUAL;
|
||||
Set<Integer> aborted;
|
||||
Set<Integer> malicious;
|
||||
DistributedKeyGenerationUser[] dkgs;
|
||||
Thread[] threads;
|
||||
BigInteger g;
|
||||
BigInteger secret;
|
||||
|
||||
public Testable(Random random) {
|
||||
this.dkgs = new DistributedKeyGenerationUserImpl[n];
|
||||
this.valids = new HashSet<Integer>();
|
||||
this.QUAL = new HashSet<Integer>();
|
||||
this.aborted = new HashSet<Integer>();
|
||||
this.malicious = new HashSet<Integer>();
|
||||
this.threads = new Thread[n];
|
||||
this.g = sampleGenerator(random);
|
||||
ArrayList<Integer> ids = new ArrayList<Integer>();
|
||||
for (int id = 1; id<= n ; id++){
|
||||
ids.add(id);
|
||||
}
|
||||
Network network = new Network(n);
|
||||
int id;
|
||||
BigInteger s;
|
||||
DistributedKeyGeneration dkg;
|
||||
this.secret = BigInteger.ZERO;
|
||||
while (!ids.isEmpty()) {
|
||||
id = ids.remove(random.nextInt(ids.size()));
|
||||
s = randomIntModQ(random);
|
||||
dkg = new DistributedKeyGeneration(t, n, s, random, q, g, group, id);
|
||||
dkgs[id - 1] = randomDKGUser(id,network,dkg,random);
|
||||
threads[id - 1] = new Thread(dkgs[id - 1]);
|
||||
if(QUAL.contains(id)){
|
||||
this.secret = this.secret.add(s).mod(q);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DistributedKeyGenerationUser randomDKGUser(int id,Network network, DistributedKeyGeneration dkg,Random random){
|
||||
if (QUAL.size() <= t) {
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new DistributedKeyGenerationUserImpl(dkg,network);
|
||||
}else{
|
||||
int type = random.nextInt(3);
|
||||
switch (type){
|
||||
case 0:// regular
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new DistributedKeyGenerationUserImpl(dkg,network);
|
||||
case 1:// abort
|
||||
int abortStage = random.nextInt(2) + 1; // 1 or 2
|
||||
aborted.add(id);
|
||||
if (abortStage == 2){
|
||||
QUAL.add(id);
|
||||
}
|
||||
return new DKGUserImplAbort(dkg,network,abortStage);
|
||||
case 2:// malicious
|
||||
malicious.add(id);
|
||||
Set<Integer> falls = DKGMaliciousUserImpl.selectFallsRandomly(valids,random);
|
||||
DistributedKeyGeneration maliciousDKG = DKGMaliciousUserImpl.generateMaliciousDKG(dkg,random);
|
||||
return new DKGMaliciousUserImpl(dkg,maliciousDKG,network,falls);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger sampleGenerator(Random random){
|
||||
BigInteger ZERO = group.zero();
|
||||
BigInteger g;
|
||||
do {
|
||||
g = group.sample(random);
|
||||
} while (!g.equals(ZERO) && !group.multiply(g, q).equals(ZERO));
|
||||
return g;
|
||||
}
|
||||
|
||||
public BigInteger randomIntModQ(Random random){
|
||||
return new BigInteger(q.bitLength(), random).mod(q);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import Communication.ChannelImpl;
|
||||
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing;
|
||||
import Utils.BigIntegerByteEncoder;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
import org.factcenter.qilin.util.ByteEncoder;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/21/2016.
|
||||
*/
|
||||
public class DKGTest {
|
||||
|
||||
int tests = 1;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
Group<BigInteger> group = new Zpstar(p);
|
||||
Arithmetic<BigInteger> arithmetic = new Fp(q);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
|
||||
Testable[] testables;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
testables = new Testable[tests];
|
||||
for (int i = 0; i < tests; i++){
|
||||
testables[i] = new Testable(new Random());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(int test) throws Exception {
|
||||
Testable testable = testables[test];
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].start();
|
||||
}
|
||||
for (int i = 0; i < testable.threads.length ; i++){
|
||||
testable.threads[i].join();
|
||||
}
|
||||
|
||||
// got the right public value
|
||||
BigInteger publicValue = group.multiply(testable.g,testable.secret);
|
||||
for (int i: testable.valids){
|
||||
assert (testable.dkgs[i - 1].getPublicValue().equals(publicValue));
|
||||
}
|
||||
|
||||
// assert valid verification values
|
||||
BigInteger expected,verification;
|
||||
for (int i: testable.valids){
|
||||
expected = group.multiply(testable.g, testable.dkgs[i - 1].getShare().y);
|
||||
verification = VerifiableSecretSharing.computeVerificationValue(i, testable.dkgs[i - 1].getCommitments(), group);
|
||||
assert (expected.equals(verification));
|
||||
}
|
||||
|
||||
|
||||
// restore the secret from shares
|
||||
ArrayList<Polynomial.Point> sharesList = new ArrayList<Polynomial.Point>();
|
||||
|
||||
for (int i: testable.valids){
|
||||
sharesList.add(testable.dkgs[i - 1].getShare());
|
||||
}
|
||||
Polynomial.Point[] shares = new Polynomial.Point[sharesList.size()];
|
||||
for (int i = 0; i < shares.length; i ++){
|
||||
shares[i] = sharesList.get(i);
|
||||
}
|
||||
|
||||
BigInteger calculatedSecret = SecretSharing.recoverSecret(shares,arithmetic);
|
||||
assert (calculatedSecret.equals(testable.secret));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test() throws Exception {
|
||||
for (int i = 0; i < tests; i++){
|
||||
oneTest(i);
|
||||
}
|
||||
}
|
||||
|
||||
class Testable{
|
||||
Set<Integer> valids;
|
||||
Set<Integer> QUAL;
|
||||
Set<Integer> aborted;
|
||||
Set<Integer> malicious;
|
||||
DistributedKeyGenerationUser[] dkgs;
|
||||
Thread[] threads;
|
||||
BigInteger g;
|
||||
BigInteger secret;
|
||||
|
||||
public Testable(Random random) {
|
||||
this.dkgs = new DistributedKeyGenerationUser[n];
|
||||
this.valids = new HashSet<Integer>();
|
||||
this.QUAL = new HashSet<Integer>();
|
||||
this.aborted = new HashSet<Integer>();
|
||||
this.malicious = new HashSet<Integer>();
|
||||
this.threads = new Thread[n];
|
||||
this.g = sampleGenerator(random);
|
||||
ArrayList<Integer> ids = new ArrayList<Integer>();
|
||||
for (int id = 1; id<= n ; id++){
|
||||
ids.add(id);
|
||||
}
|
||||
int id;
|
||||
BigInteger s;
|
||||
DistributedKeyGeneration dkg;
|
||||
this.secret = BigInteger.ZERO;
|
||||
Channel channel;
|
||||
ByteEncoder<BigInteger> byteEncoder = new BigIntegerByteEncoder();
|
||||
while (!ids.isEmpty()) {
|
||||
id = ids.remove(random.nextInt(ids.size()));
|
||||
channel = new ChannelImpl(id,n);
|
||||
s = randomIntModQ(random);
|
||||
dkg = new DistributedKeyGeneration(t, n, s, random, q, g, group, id,byteEncoder);
|
||||
dkgs[id - 1] = randomDKGUser(id,channel,dkg,random);
|
||||
threads[id - 1] = new Thread(dkgs[id - 1]);
|
||||
if(QUAL.contains(id)){
|
||||
this.secret = this.secret.add(s).mod(q);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public DistributedKeyGenerationUser randomDKGUser(int id, Channel channel, DistributedKeyGeneration dkg, Random random){
|
||||
if (QUAL.size() <= t) {
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new DistributedKeyGenerationUser(dkg,channel);
|
||||
}else{
|
||||
int type = random.nextInt(3);
|
||||
switch (type){
|
||||
case 0:// regular
|
||||
valids.add(id);
|
||||
QUAL.add(id);
|
||||
return new DistributedKeyGenerationUser(dkg,channel);
|
||||
case 1:// abort
|
||||
int abortStage = random.nextInt(2) + 1; // 1 or 2
|
||||
aborted.add(id);
|
||||
if (abortStage == 2){
|
||||
QUAL.add(id);
|
||||
}
|
||||
return new DKGUserImplAbort(dkg,channel,abortStage);
|
||||
case 2:// malicious
|
||||
malicious.add(id);
|
||||
Set<Integer> falls = DKGMaliciousUser.selectFallsRandomly(valids,random);
|
||||
DistributedKeyGeneration maliciousDKG = DKGMaliciousUser.generateMaliciousDKG(dkg,channel,random);
|
||||
return new DKGMaliciousUser(dkg,maliciousDKG,channel,falls);
|
||||
default:
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BigInteger sampleGenerator(Random random){
|
||||
BigInteger ZERO = group.zero();
|
||||
BigInteger g;
|
||||
do {
|
||||
g = group.sample(random);
|
||||
} while (!g.equals(ZERO) && !group.multiply(g, q).equals(ZERO));
|
||||
return g;
|
||||
}
|
||||
|
||||
public BigInteger randomIntModQ(Random random){
|
||||
return new BigInteger(q.bitLength(), random).mod(q);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,63 +1,63 @@
|
|||
package JointFeldmanProtocol;
|
||||
|
||||
import Communication.Network;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*/
|
||||
public class DKGUserImplAbort extends DistributedKeyGenerationUserImpl {
|
||||
|
||||
final int abortStage;
|
||||
int stage;
|
||||
public DKGUserImplAbort(DistributedKeyGeneration dkg, Network network, int abortStage) {
|
||||
super(dkg, network);
|
||||
this.abortStage = abortStage;// 1 - 2
|
||||
this.stage = 1;
|
||||
}
|
||||
|
||||
|
||||
private void sendAbort(){
|
||||
user.broadcast(DKGMessages.Mail.Type.ABORT,DKGMessages.EmptyMessage.getDefaultInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage1() {
|
||||
if(stage < abortStage)
|
||||
super.stage1();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage2() {
|
||||
if(stage < abortStage)
|
||||
super.stage2();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage3() {
|
||||
if(stage < abortStage)
|
||||
super.stage3();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
if(stage < abortStage)
|
||||
super.stage4();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol;
|
||||
|
||||
import meerkat.crypto.utilitis.Channel;
|
||||
import meerkat.protobuf.DKGMessages;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 3/14/2016.
|
||||
*/
|
||||
public class DKGUserImplAbort extends DistributedKeyGenerationUser {
|
||||
|
||||
final int abortStage;
|
||||
int stage;
|
||||
public DKGUserImplAbort(DistributedKeyGeneration dkg, Channel channel, int abortStage) {
|
||||
super(dkg, channel);
|
||||
this.abortStage = abortStage;// 1 - 2
|
||||
this.stage = 1;
|
||||
}
|
||||
|
||||
|
||||
private void sendAbort(){
|
||||
channel.broadcastMessage(DKGMessages.Mail.Type.ABORT,DKGMessages.EmptyMessage.getDefaultInstance());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage1() {
|
||||
if(stage < abortStage)
|
||||
super.stage1();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage2() {
|
||||
if(stage < abortStage)
|
||||
super.stage2();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage3() {
|
||||
if(stage < abortStage)
|
||||
super.stage3();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void stage4() {
|
||||
if(stage < abortStage)
|
||||
super.stage4();
|
||||
else if(stage == abortStage){
|
||||
sendAbort();
|
||||
}
|
||||
stage++;
|
||||
}
|
||||
}
|
|
@ -1,67 +1,68 @@
|
|||
package FeldmanVerifiableSecretSharing;
|
||||
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
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 1/29/2016.
|
||||
*/
|
||||
public class VerifiableSecretSharingTest {
|
||||
|
||||
|
||||
VerifiableSecretSharing[] verifiableSecretSharingArray;
|
||||
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;
|
||||
verifiableSecretSharingArray = new VerifiableSecretSharing[tests];
|
||||
for (int i = 0; i < verifiableSecretSharingArray.length; i++){
|
||||
verifiableSecretSharingArray[i] = new VerifiableSecretSharing(t,n
|
||||
,new BigInteger(q.bitLength(),random).mod(q),random,q,g,zpstar);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(VerifiableSecretSharing verifiableSecretSharing) throws Exception {
|
||||
int n = verifiableSecretSharing.getN();
|
||||
Group<BigInteger> zpstar = verifiableSecretSharing.getGroup();
|
||||
BigInteger g = verifiableSecretSharing.getGenerator();
|
||||
Polynomial.Point[] shares = new Polynomial.Point[n];
|
||||
BigInteger[] commitments = verifiableSecretSharing.getCommitmentsArray();
|
||||
BigInteger[] verifications = new BigInteger[n];
|
||||
for (int i = 1 ; i <= shares.length; i ++){
|
||||
shares[i - 1] = verifiableSecretSharing.getShare(i);
|
||||
verifications[i - 1] = VerifiableSecretSharing.computeVerificationValue(i,commitments,zpstar);
|
||||
}
|
||||
BigInteger expected;
|
||||
for (int i = 0 ; i < shares.length ; i++){
|
||||
expected = zpstar.multiply(g,shares[i].y);
|
||||
assert (expected.equals(verifications[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secretSharingTest() throws Exception {
|
||||
for (int i = 0 ; i < verifiableSecretSharingArray.length; i ++){
|
||||
oneTest(verifiableSecretSharingArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.feldman_verifiable;
|
||||
|
||||
import meerkat.crypto.concrete.secret_shring.ShamirSecretSharing.Polynomial;
|
||||
import org.factcenter.qilin.primitives.Group;
|
||||
import org.factcenter.qilin.primitives.concrete.Zpstar;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/29/2016.
|
||||
*/
|
||||
public class VerifiableSecretSharingTest {
|
||||
|
||||
|
||||
VerifiableSecretSharing[] verifiableSecretSharingArray;
|
||||
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;
|
||||
verifiableSecretSharingArray = new VerifiableSecretSharing[tests];
|
||||
for (int i = 0; i < verifiableSecretSharingArray.length; i++){
|
||||
verifiableSecretSharingArray[i] = new VerifiableSecretSharing(t,n
|
||||
,new BigInteger(q.bitLength(),random).mod(q),random,q,g,zpstar);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(VerifiableSecretSharing<BigInteger> verifiableSecretSharing) throws Exception {
|
||||
int n = verifiableSecretSharing.getN();
|
||||
Group<BigInteger> zpstar = verifiableSecretSharing.getGroup();
|
||||
BigInteger g = verifiableSecretSharing.getGenerator();
|
||||
Polynomial.Point[] shares = new Polynomial.Point[n];
|
||||
ArrayList<BigInteger> commitments = verifiableSecretSharing.getCommitmentsArrayList();
|
||||
BigInteger[] verifications = new BigInteger[n];
|
||||
for (int i = 1 ; i <= shares.length; i ++){
|
||||
shares[i - 1] = verifiableSecretSharing.getShare(i);
|
||||
verifications[i - 1] = VerifiableSecretSharing.computeVerificationValue(i,commitments,zpstar);
|
||||
}
|
||||
BigInteger expected;
|
||||
for (int i = 0 ; i < shares.length ; i++){
|
||||
expected = zpstar.multiply(g,shares[i].y);
|
||||
assert (expected.equals(verifications[i]));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secretSharingTest() throws Exception {
|
||||
for (int i = 0 ; i < verifiableSecretSharingArray.length; i ++){
|
||||
oneTest(verifiableSecretSharingArray[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,46 +1,46 @@
|
|||
package ShamirSecretSharing.PolynomialTests;
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class AddTest {
|
||||
|
||||
Polynomial[] arr1;
|
||||
Polynomial[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new Polynomial[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p1, Polynomial p2){
|
||||
Polynomial sum = p1.add(p2);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(sum.evaluate(x).equals(p1.evaluate(x).add(p2.evaluate(x))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests;
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class AddTest {
|
||||
|
||||
Polynomial[] arr1;
|
||||
Polynomial[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new Polynomial[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p1, Polynomial p2){
|
||||
Polynomial sum = p1.add(p2);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(sum.evaluate(x).equals(p1.evaluate(x).add(p2.evaluate(x))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,68 +1,68 @@
|
|||
package ShamirSecretSharing.PolynomialTests;
|
||||
|
||||
import Arithmetics.Arithmetic;
|
||||
import Arithmetics.Fp;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class InterpolationTest {
|
||||
Polynomial[] polynomials;
|
||||
int tests = 1 << 10;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
Polynomial.Point[][] pointsArrays;
|
||||
Arithmetic<BigInteger> arithmetic;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
polynomials = new Polynomial[tests];
|
||||
pointsArrays = new Polynomial.Point[tests][];
|
||||
for (int i = 0; i < polynomials.length; i++){
|
||||
polynomials[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,p);
|
||||
pointsArrays[i] = randomPoints(polynomials[i]);
|
||||
}
|
||||
arithmetic = new Fp(p);
|
||||
}
|
||||
|
||||
public Polynomial.Point[] randomPoints(Polynomial polynomial){
|
||||
Polynomial.Point[] points = new Polynomial.Point[polynomial.getDegree() + 1];
|
||||
BigInteger x;
|
||||
Set<BigInteger> set = new HashSet();
|
||||
for (int i = 0; i < points.length; i++){
|
||||
x = new BigInteger(bits,random).mod(p);
|
||||
if(set.contains(x)){
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
set.add(x);
|
||||
points[i] = new Polynomial.Point(x,polynomial);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p, Polynomial.Point[] points) throws Exception {
|
||||
Polynomial interpolation = Polynomial.interpolation(points,arithmetic);
|
||||
assert (p.compareTo(interpolation) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolationTest() throws Exception {
|
||||
for (int i = 0; i < polynomials.length; i ++){
|
||||
oneTest(polynomials[i],pointsArrays[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests;
|
||||
|
||||
import meerkat.crypto.utilitis.Arithmetic;
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.HashSet;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class InterpolationTest {
|
||||
Polynomial[] polynomials;
|
||||
int tests = 1 << 10;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
Polynomial.Point[][] pointsArrays;
|
||||
Arithmetic<BigInteger> arithmetic;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
polynomials = new Polynomial[tests];
|
||||
pointsArrays = new Polynomial.Point[tests][];
|
||||
arithmetic = new Fp(p);
|
||||
for (int i = 0; i < polynomials.length; i++){
|
||||
polynomials[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,p);
|
||||
pointsArrays[i] = randomPoints(polynomials[i]);
|
||||
}
|
||||
}
|
||||
|
||||
public Polynomial.Point[] randomPoints(Polynomial polynomial){
|
||||
Polynomial.Point[] points = new Polynomial.Point[polynomial.getDegree() + 1];
|
||||
BigInteger x;
|
||||
Set<BigInteger> set = new HashSet();
|
||||
for (int i = 0; i < points.length; i++){
|
||||
x = new BigInteger(bits,random).mod(p);
|
||||
if(set.contains(x)){
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
set.add(x);
|
||||
points[i] = new Polynomial.Point(x,polynomial);
|
||||
}
|
||||
return points;
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p, Polynomial.Point[] points) throws Exception {
|
||||
Polynomial interpolation = Polynomial.interpolation(points,arithmetic);
|
||||
assert (p.compareTo(interpolation) == 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void interpolationTest() throws Exception {
|
||||
for (int i = 0; i < polynomials.length; i ++){
|
||||
oneTest(polynomials[i],pointsArrays[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +1,48 @@
|
|||
package ShamirSecretSharing.PolynomialTests;
|
||||
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class MulByConstTest {
|
||||
|
||||
|
||||
Polynomial[] arr1;
|
||||
BigInteger[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new BigInteger[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = new BigInteger(bits,random);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p, BigInteger c){
|
||||
Polynomial product = p.mul(c);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(product.evaluate(x).equals(p.evaluate(x).multiply(c)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulByConstTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests;
|
||||
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class MulByConstTest {
|
||||
|
||||
|
||||
Polynomial[] arr1;
|
||||
BigInteger[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new BigInteger[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = new BigInteger(bits,random);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p, BigInteger c){
|
||||
Polynomial product = p.mul(c);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(product.evaluate(x).equals(p.evaluate(x).multiply(c)));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulByConstTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,48 +1,48 @@
|
|||
package ShamirSecretSharing.PolynomialTests;
|
||||
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import ShamirSecretSharing.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class MulTest {
|
||||
|
||||
|
||||
Polynomial[] arr1;
|
||||
Polynomial[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new Polynomial[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p1, Polynomial p2){
|
||||
Polynomial product = p1.mul(p2);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(product.evaluate(x).equals(p1.evaluate(x).multiply(p2.evaluate(x))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests;
|
||||
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPolynomial;
|
||||
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/27/2016.
|
||||
*/
|
||||
public class MulTest {
|
||||
|
||||
|
||||
Polynomial[] arr1;
|
||||
Polynomial[] arr2;
|
||||
int tests = 1 << 12;
|
||||
int maxDegree = 15;
|
||||
int bits = 128;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
random = new Random();
|
||||
arr1 = new Polynomial[tests];
|
||||
arr2 = new Polynomial[tests];
|
||||
for (int i = 0; i < arr1.length; i++){
|
||||
arr1[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
arr2[i] = GenerateRandomPolynomial.generateRandomPolynomial(random.nextInt(maxDegree),bits,random,new Z());
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(Polynomial p1, Polynomial p2){
|
||||
Polynomial product = p1.mul(p2);
|
||||
BigInteger x = new BigInteger(bits,random);
|
||||
assert(product.evaluate(x).equals(p1.evaluate(x).multiply(p2.evaluate(x))));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void mulTest(){
|
||||
for (int i = 0 ; i < arr1.length; i ++){
|
||||
oneTest(arr1[i],arr2[i]);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,63 +1,64 @@
|
|||
package ShamirSecretSharing;
|
||||
|
||||
import Arithmetics.Z;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.CyclicGroup;
|
||||
import org.factcenter.qilin.primitives.concrete.Zn;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/29/2016.
|
||||
*/
|
||||
public class SecretSharingTest {
|
||||
|
||||
SecretSharing[] secretSharingArray;
|
||||
BigInteger[] secrets;
|
||||
CyclicGroup<BigInteger> group;
|
||||
int tests = 1 << 10;
|
||||
Random random;
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
group = new Zn(p);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
random = new Random();
|
||||
secretSharingArray = new SecretSharing[tests];
|
||||
secrets = new BigInteger[tests];
|
||||
|
||||
for (int i = 0; i < secretSharingArray.length; i++){
|
||||
secrets[i] = group.sample(random);
|
||||
secretSharingArray[i] = new SecretSharing(t,n,secrets[i],random,q);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(SecretSharing secretSharing, BigInteger secret) throws Exception {
|
||||
int t = secretSharing.getT();
|
||||
int n = secretSharing.getN();
|
||||
Polynomial.Point[] shares = new Polynomial.Point[t + 1];
|
||||
List<Integer> indexes = new ArrayList<Integer>(n);
|
||||
for (int i = 1 ; i <= n; i ++){
|
||||
indexes.add(i);
|
||||
}
|
||||
for (int i = 0 ; i < shares.length ; i++){
|
||||
shares[i] = secretSharing.getShare(indexes.remove(random.nextInt(indexes.size())));
|
||||
}
|
||||
assert(secret.equals(SecretSharing.recoverSecret(shares,new Z())));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secretSharingTest() throws Exception {
|
||||
for (int i = 0 ; i < secretSharingArray.length; i ++){
|
||||
oneTest(secretSharingArray[i],secrets[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
package meerkat.crypto.concrete.secret_shring.shamir;
|
||||
|
||||
import meerkat.crypto.utilitis.concrete.Fp;
|
||||
import Utils.GenerateRandomPrime;
|
||||
import org.factcenter.qilin.primitives.CyclicGroup;
|
||||
import org.factcenter.qilin.primitives.concrete.Zn;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Created by Tzlil on 1/29/2016.
|
||||
*/
|
||||
public class SecretSharingTest {
|
||||
|
||||
SecretSharing[] secretSharingArray;
|
||||
BigInteger[] secrets;
|
||||
CyclicGroup<BigInteger> group;
|
||||
int tests = 1 << 10;
|
||||
Random random;
|
||||
BigInteger p = GenerateRandomPrime.SafePrime100Bits;
|
||||
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
||||
|
||||
@Before
|
||||
public void settings(){
|
||||
group = new Zn(q);
|
||||
int t = 9;
|
||||
int n = 20;
|
||||
random = new Random();
|
||||
secretSharingArray = new SecretSharing[tests];
|
||||
secrets = new BigInteger[tests];
|
||||
|
||||
for (int i = 0; i < secretSharingArray.length; i++){
|
||||
secrets[i] = group.sample(random);
|
||||
secretSharingArray[i] = new SecretSharing(t,n,secrets[i],random,q);
|
||||
}
|
||||
}
|
||||
|
||||
public void oneTest(SecretSharing secretSharing, BigInteger secret) throws Exception {
|
||||
int t = secretSharing.getT();
|
||||
int n = secretSharing.getN();
|
||||
Polynomial.Point[] shares = new Polynomial.Point[t + 1];
|
||||
List<Integer> indexes = new ArrayList<Integer>(n);
|
||||
for (int i = 1 ; i <= n; i ++){
|
||||
indexes.add(i);
|
||||
}
|
||||
for (int i = 0 ; i < shares.length ; i++){
|
||||
shares[i] = secretSharing.getShare(indexes.remove(random.nextInt(indexes.size())));
|
||||
}
|
||||
BigInteger calculated = SecretSharing.recoverSecret(shares,new Fp(q));
|
||||
assert (secret.equals(calculated));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void secretSharingTest() throws Exception {
|
||||
for (int i = 0 ; i < secretSharingArray.length; i ++){
|
||||
oneTest(secretSharingArray[i],secrets[i]);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue