tzlil.gon 2016-04-08 21:48:08 +03:00
parent 3e1f59ec2b
commit d0951f8644
59 changed files with 1974 additions and 1750 deletions

View File

@ -2,8 +2,8 @@ package meerkat.bulletinboard;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.comm.CommunicationException; import meerkat.comm.CommunicationException;
import meerkat.crypto.Digest; import meerkat.destributed_key_generation.Digest;
import meerkat.crypto.concrete.SHA256Digest; import meerkat.destributed_key_generation.concrete.SHA256Digest;
import meerkat.protobuf.BulletinBoardAPI.*; import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.rest.Constants; import meerkat.rest.Constants;
import meerkat.rest.ProtobufMessageBodyReader; import meerkat.rest.ProtobufMessageBodyReader;

View File

@ -2,8 +2,8 @@ package meerkat.bulletinboard;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.comm.CommunicationException; import meerkat.comm.CommunicationException;
import meerkat.crypto.Digest; import meerkat.destributed_key_generation.Digest;
import meerkat.crypto.concrete.SHA256Digest; import meerkat.destributed_key_generation.concrete.SHA256Digest;
import meerkat.protobuf.BulletinBoardAPI.*; import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.protobuf.Voting; import meerkat.protobuf.Voting;
import meerkat.protobuf.Voting.BulletinBoardClientParams; import meerkat.protobuf.Voting.BulletinBoardClientParams;

View File

@ -6,8 +6,8 @@ import meerkat.bulletinboard.callbacks.GetRedundancyFutureCallback;
import meerkat.bulletinboard.callbacks.PostMessageFutureCallback; import meerkat.bulletinboard.callbacks.PostMessageFutureCallback;
import meerkat.bulletinboard.callbacks.ReadMessagesFutureCallback; import meerkat.bulletinboard.callbacks.ReadMessagesFutureCallback;
import meerkat.comm.CommunicationException; import meerkat.comm.CommunicationException;
import meerkat.crypto.Digest; import meerkat.destributed_key_generation.Digest;
import meerkat.crypto.concrete.SHA256Digest; import meerkat.destributed_key_generation.concrete.SHA256Digest;
import meerkat.protobuf.BulletinBoardAPI.*; import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.protobuf.Voting; import meerkat.protobuf.Voting;

View File

@ -13,8 +13,8 @@ import meerkat.comm.CommunicationException;
import meerkat.protobuf.BulletinBoardAPI.*; import meerkat.protobuf.BulletinBoardAPI.*;
import meerkat.protobuf.Crypto.Signature; import meerkat.protobuf.Crypto.Signature;
import meerkat.protobuf.Crypto.SignatureVerificationKey; import meerkat.protobuf.Crypto.SignatureVerificationKey;
import meerkat.crypto.Digest; import meerkat.destributed_key_generation.Digest;
import meerkat.crypto.concrete.SHA256Digest; import meerkat.destributed_key_generation.concrete.SHA256Digest;
import javax.sql.DataSource; import javax.sql.DataSource;

View File

@ -18,7 +18,7 @@ import java.util.Random;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.comm.CommunicationException; import meerkat.comm.CommunicationException;
import meerkat.crypto.concrete.ECDSASignature; import meerkat.destributed_key_generation.concrete.ECDSASignature;
import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage; import meerkat.protobuf.BulletinBoardAPI.BulletinBoardMessage;
import meerkat.protobuf.BulletinBoardAPI.FilterType; import meerkat.protobuf.BulletinBoardAPI.FilterType;
import meerkat.protobuf.BulletinBoardAPI.MessageFilter; import meerkat.protobuf.BulletinBoardAPI.MessageFilter;

View File

@ -1,11 +0,0 @@
package meerkat.crypto;
import java.util.Random;
/**
* Created by Tzlil on 4/8/2016.
*/
public interface KeyGeneration<T> {
T generateKey(Random random);
}

View File

@ -1,7 +0,0 @@
package meerkat.crypto;
/**
* Created by Tzlil on 4/8/2016.
*/
public class SecretSharing {
}

View File

@ -1,18 +0,0 @@
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);
}

View File

@ -1,36 +1,59 @@
package meerkat.crypto.concrete.distributed_key_generation.communication; package meerkat.destributed_key_generation.concrete.distributed_key_generation.communication;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**
* Created by Tzlil on 2/14/2016. * Created by Tzlil on 2/14/2016.
*
* an implementation of ReceiverCallback
*/ */
public abstract class MailHandler implements Channel.ReceiverCallback{ public abstract class MailHandler implements Channel.ReceiverCallback{
/**
* fixed value for broadcasting
*/
public static final int BROADCAST = 0; public static final int BROADCAST = 0;
/**
* message handler
*/
private MessageHandler messageHandler; private MessageHandler messageHandler;
/**
* constructor
* @param messageHandler
*/
public MailHandler(MessageHandler messageHandler){ public MailHandler(MessageHandler messageHandler){
this.messageHandler = messageHandler; this.messageHandler = messageHandler;
} }
/**
* extract message from mail
* @param mail
* @return
*/
public abstract Message extractMessage(DKGMessages.Mail mail); public abstract Message extractMessage(DKGMessages.Mail mail);
/**
* is this mail was received by broadcast channel
* @param mail
* @return mail user destination == BROADCAST
*/
public boolean isBroadcast(DKGMessages.Mail mail){ public boolean isBroadcast(DKGMessages.Mail mail){
return mail.getDestination() == BROADCAST; return mail.getDestination() == BROADCAST;
} }
@Override
public void receiveMail(DKGMessages.Mail mail){ public void receiveMail(DKGMessages.Mail mail){
Message message = extractMessage(mail); Message message = extractMessage(mail);
if (message == null) if (message == null)
return; return;
switch (mail.getType()) { switch (mail.getType()) {
case SHARE: case SHARE:
messageHandler.handleSecretMessage(mail.getSender(), isBroadcast(mail),message); messageHandler.handleShareMessage(mail.getSender(), isBroadcast(mail),message);
break; break;
case COMMITMENT: case COMMITMENT:
messageHandler.handleCommitmentMessage(mail.getSender(), isBroadcast(mail),message); messageHandler.handleCommitmentMessage(mail.getSender(), isBroadcast(mail),message);

View File

@ -1,15 +1,39 @@
package meerkat.crypto.concrete.distributed_key_generation.communication; package meerkat.destributed_key_generation.concrete.distributed_key_generation.communication;
import com.google.protobuf.Message; import com.google.protobuf.Message;
/** /**
* Created by Tzlil on 2/14/2016. * Created by Tzlil on 2/14/2016.
* an interface for handling received messages
*/ */
public interface MessageHandler { public interface MessageHandler {
void handleSecretMessage(int sender, boolean isBroadcast, Message message); /**
* handle share message
*/
void handleShareMessage(int sender, boolean isBroadcast, Message message);
/**
* handle commitment message
*/
void handleCommitmentMessage(int sender, boolean isBroadcast, Message message); void handleCommitmentMessage(int sender, boolean isBroadcast, Message message);
/**
* handle complaint message
*/
void handleComplaintMessage(int sender, boolean isBroadcast, Message message); void handleComplaintMessage(int sender, boolean isBroadcast, Message message);
/**
* handle done message
*/
void handleDoneMessage(int sender, boolean isBroadcast, Message message); void handleDoneMessage(int sender, boolean isBroadcast, Message message);
/**
* handle answer message
*/
void handleAnswerMessage(int sender, boolean isBroadcast, Message message); void handleAnswerMessage(int sender, boolean isBroadcast, Message message);
/**
* handle abort message
*/
void handleAbortMessage(int sender, boolean isBroadcast, Message message); void handleAbortMessage(int sender, boolean isBroadcast, Message message);
} }

View File

@ -1,17 +1,26 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.concrete.distributed_key_generation.communication.MessageHandler; import meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MessageHandler;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**
* Created by Tzlil on 2/29/2016. * Created by Tzlil on 2/29/2016.
* an extension of MailHandler matching gjkr protocl
*/ */
public class MailHandler extends meerkat.crypto.concrete.distributed_key_generation.communication.MailHandler { public class MailHandler extends meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MailHandler {
/**
* flag that indicants whether the
* current run achieved stage 4 of the protocol or not
*/
private boolean isStage4; private boolean isStage4;
/**
* constructor
* @param messageHandler
*/
public MailHandler(MessageHandler messageHandler) { public MailHandler(MessageHandler messageHandler) {
super(messageHandler); super(messageHandler);
this.isStage4 = false; this.isStage4 = false;
@ -52,10 +61,10 @@ public class MailHandler extends meerkat.crypto.concrete.distributed_key_generat
} }
} }
public boolean isStage4() { /**
return isStage4; * setter
} * @param stage4
*/
public void setStage4(boolean stage4) { public void setStage4(boolean stage4) {
isStage4 = stage4; isStage4 = stage4;
} }

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -13,7 +13,7 @@ import java.util.Set;
* contains all relevant information on specific party during * contains all relevant information on specific party during
* the run of the safe protocol * the run of the safe protocol
*/ */
public class Party<T> extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Party<T> { public class Party<T> extends meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.Party<T> {
public Polynomial.Point shareT; public Polynomial.Point shareT;
public boolean ysDoneFlag; public boolean ysDoneFlag;
public ArrayList<T> verifiableValues; public ArrayList<T> verifiableValues;

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
@ -17,7 +17,7 @@ import java.util.Set;
* TODO: comments * TODO: comments
* TODO: put Channel (ChannelImpl) in constructor * TODO: put Channel (ChannelImpl) in constructor
*/ */
public class Protocol<T> extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol<T> { public class Protocol<T> extends meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.Protocol<T> {
private VerifiableSecretSharing<T> maskingShares; private VerifiableSecretSharing<T> maskingShares;
private final T h; private final T h;

View File

@ -1,10 +1,10 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.SecretSharing;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
@ -13,25 +13,48 @@ import java.util.ArrayList;
/** /**
* Created by Tzlil on 3/16/2016. * Created by Tzlil on 3/16/2016.
*
* implementation of gjkr protocol user.
*
* this protocol extends joint feldman protocol by splitting the protocol to commitment stage (stages 1,2,3)
* and reviling stage (stage 4).
*
* as in joint feldman, each party in QUAL has his own share of the generated random key.
* this key can be recover by any subset of QUAL of size at least t + 1.
*/ */
public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.User<T> { public class User<T> extends meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.User<T> {
/**
* All parties participating in key generation.
* parties[id-1] has my info.
*/
protected Party<T>[] parties; protected Party<T>[] parties;
protected final Protocol<T> sdkg;
private Arithmetic<BigInteger> arithmetic;
private boolean isStage4;
/**
* gjkr secure protocol object
*/
protected final Protocol<T> sdkg;
/**
* message handler
*/
private MessageHandler messageHandler;
/**
* constructor
* @param sdkg gjkr protocol object
* @param channel channel object
*/
public User(Protocol<T> sdkg, Channel channel) { public User(Protocol<T> sdkg, Channel channel) {
super(sdkg, channel); super(sdkg, channel);
this.sdkg = sdkg; this.sdkg = sdkg;
this.parties = sdkg.getParties(); this.parties = sdkg.getParties();
this.arithmetic = new Fp(sdkg.getQ());
this.isStage4 = false;
} }
@Override @Override
protected void registerReceiverCallback(){ protected void registerReceiverCallback(){
this.mailHandler = new MailHandler(new MessageHandler()); this.messageHandler = new MessageHandler();
this.mailHandler = new MailHandler(messageHandler);
this.channel.registerReceiverCallback(mailHandler); this.channel.registerReceiverCallback(mailHandler);
} }
/** /**
@ -84,7 +107,7 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
try { try {
parties[i - 1].wait(); parties[i - 1].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
@ -102,7 +125,7 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
try { try {
parties[i - 1].wait(); parties[i - 1].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
@ -122,13 +145,13 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
try { try {
parties[i - 1].wait(); parties[i - 1].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
} }
} }
Arithmetic<BigInteger> arithmetic = new Fp(sdkg.getQ());
// restore necessary information // restore necessary information
for (int i = 0; i < n ; i++) { for (int i = 0; i < n ; i++) {
if(parties[i].recoverSharesSet.isEmpty()){ if(parties[i].recoverSharesSet.isEmpty()){
@ -152,10 +175,10 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
} }
/** /**
* notifies mail handler that stage 4 was started * notifies mail handler and message handler that stage 4 was started
*/ */
protected void setStage4(){ protected void setStage4(){
this.isStage4 = true; this.messageHandler.isStage4 = true;
((MailHandler)this.mailHandler).setStage4(true); ((MailHandler)this.mailHandler).setStage4(true);
} }
@ -163,11 +186,13 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
protected void stage4() { protected void stage4() {
setStage4(); setStage4();
resolveQualifyingPublicKey(); resolveQualifyingPublicKey();
if (stop) return;
super.stage4(); super.stage4();
} }
private class MessageHandler extends meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.User.MessageHandler { private class MessageHandler extends meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.User.MessageHandler {
boolean isStage4;
/** /**
* as in super, with extension to double secret message * as in super, with extension to double secret message
*/ */
@ -184,7 +209,7 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
* as in super, with extension to double secret message * as in super, with extension to double secret message
*/ */
@Override @Override
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) { public void handleShareMessage(int sender, boolean isBroadcast, Message message) {
DKGMessages.DoubleShareMessage doubleSecretMessage = (DKGMessages.DoubleShareMessage)message; DKGMessages.DoubleShareMessage doubleSecretMessage = (DKGMessages.DoubleShareMessage)message;
if (isValidSecretMessage(sender,isBroadcast,doubleSecretMessage)) { if (isValidSecretMessage(sender,isBroadcast,doubleSecretMessage)) {
int i = doubleSecretMessage.getI(); int i = doubleSecretMessage.getI();
@ -234,10 +259,10 @@ public class User<T> extends meerkat.crypto.concrete.distributed_key_generation.
synchronized (parties[i - 1]) { synchronized (parties[i - 1]) {
if (!isStage4) { if (!isStage4) {
if (sdkg.isValidShare(secret, secretT, parties[j - 1].verifiableValues, i)) { 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; parties[i - 1].complaints[j - 1] = meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.Protocol.ComplaintState.NonDisqualified;
} else { } else {
parties[i - 1].complaints[j - 1] = meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol.ComplaintState.Disqualified; parties[i - 1].complaints[j - 1] = meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.Protocol.ComplaintState.Disqualified;
} }
if (j == id) { if (j == id) {
parties[i - 1].share = secret; parties[i - 1].share = secret;

View File

@ -1,15 +1,20 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.concrete.distributed_key_generation.communication.MessageHandler; import meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MessageHandler;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**
* Created by Tzlil on 2/29/2016. * Created by Tzlil on 2/29/2016.
* an extension of MailHandler matching joint feldman protocol
*/ */
public class MailHandler extends meerkat.crypto.concrete.distributed_key_generation.communication.MailHandler { public class MailHandler extends meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MailHandler {
/**
* constructor
* @param messageHandler
*/
public MailHandler(MessageHandler messageHandler) { public MailHandler(MessageHandler messageHandler) {
super(messageHandler); super(messageHandler);
} }

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -19,6 +19,12 @@ public class Party<T> {
public Protocol.ComplaintState[] complaints; public Protocol.ComplaintState[] complaints;
public boolean aborted; public boolean aborted;
/**
*
* @param id party identifier - 1 <= id <= n
* @param n number of parties in current run protocol
* @param t protocol's threshold
*/
public Party(int id, int n, int t) { public Party(int id, int n, int t) {
this.id = id; this.id = id;
this.share = null; this.share = null;

View File

@ -1,8 +1,8 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
@ -57,7 +57,6 @@ public class Protocol<T> extends VerifiableSecretSharing<T> {
*/ */
protected Channel channel; protected Channel channel;
/** /**
* Encode/Decode group elements * Encode/Decode group elements
*/ */
@ -76,9 +75,10 @@ public class Protocol<T> extends VerifiableSecretSharing<T> {
* @param g a generator of cyclic group of order q. * @param g a generator of cyclic group of order q.
* the generated group is a subgroup of the given group. * the generated group is a subgroup of the given group.
* it must be chosen such that computing discrete logarithms is hard in this group. * it must be chosen such that computing discrete logarithms is hard in this group.
* @param encoder Encode/Decode group elements (of type T) to/from byte array
*/ */
public Protocol(int t, int n, BigInteger zi, Random random, BigInteger q, T g public Protocol(int t, int n, BigInteger zi, Random random, BigInteger q, T g
, Group<T> group, int id, ByteEncoder<T> byteEncoder) { , Group<T> group, int id, ByteEncoder<T> encoder) {
super(t, n, zi, random, q, g,group); super(t, n, zi, random, q, g,group);
this.id = id; this.id = id;
this.parties = new Party[n]; this.parties = new Party[n];
@ -86,7 +86,7 @@ public class Protocol<T> extends VerifiableSecretSharing<T> {
this.parties[i - 1] = new Party(i,n,t); this.parties[i - 1] = new Party(i,n,t);
} }
this.parties[id - 1].share = getShare(id); this.parties[id - 1].share = getShare(id);
this.encoder = byteEncoder; this.encoder = encoder;
} }
/** /**

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
@ -13,27 +13,91 @@ import java.util.Set;
/** /**
* Created by Tzlil on 3/14/2016. * Created by Tzlil on 3/14/2016.
* TODO: Comments *
* TODO: Replace polling with monitors/wait/notify (remember synchronization) * implementation of joint feldman protocol user.
*
* according to the protocol, each user run feldman verifiable secret sharing
* as a dealer.
*
* by the end of run(), each party in QUAL has his own share of the generated random key.
* this key can be recover by any subset of QUAL of size at least t + 1.
*/ */
public class User<T> implements Runnable{ public class User<T> implements Runnable{
/**
* joint feldman protocol object
*/
protected final Protocol<T> dkg; protected final Protocol<T> dkg;
/**
* 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.
*/
protected final T g; protected final T g;
/**
* cyclic group contains g.
*/
protected final Group<T> group; protected final Group<T> group;
protected final int n;
protected final int t; /**
* user id
*/
protected final int id; protected final int id;
protected meerkat.crypto.concrete.distributed_key_generation.communication.MailHandler mailHandler;
protected final Channel channel; /**
* threshold
*/
protected final int t;
/**
* number of shares
*/
protected final int n;
/**
* mail handler registered to channel as ReceiverCallback
*/
protected meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MailHandler mailHandler;
/**
* channel object
*/
protected final Channel channel; //
/**
* All parties participating in key generation.
* parties[id-1] has my info.
*/
protected final Party[] parties; 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
/**
* set of all non-disqualified parties
*/
protected Set<Integer> QUAL;
/**
* my own share of the generated random key.
*/
protected Polynomial.Point share;
/**
* public verification values
*/
protected ArrayList<T> commitments;
/**
* public value,
* y = g ^ key
*/
protected T y;
/**
* constructor
* @param dkg joint feldman protocol object
* @param channel channel object
*/
public User(Protocol<T> dkg, Channel channel) { public User(Protocol<T> dkg, Channel channel) {
this.dkg = dkg; this.dkg = dkg;
@ -74,20 +138,23 @@ public class User<T> implements Runnable{
} }
/**
* wait for all shares and commitments will arrive from other parties
*/
protected void waitUntilStageOneCompleted(){ protected void waitUntilStageOneCompleted(){
// all parties send their share or aborted // wait for parties' share
for (int i = 0 ; i < n ; i++){ for (int i = 0 ; i < n ; i++){
synchronized (parties[i]) { synchronized (parties[i]) {
while (parties[i].share == null && !parties[i].aborted) { while (parties[i].share == null && !parties[i].aborted) {
try { try {
parties[i].wait(); parties[i].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
} }
// all parties broadcast their commitments or aborted // wait for parties' commitments
for (int i = 0 ; i < n ; i++){ for (int i = 0 ; i < n ; i++){
for (int k = 0 ; k <= t ; k++) { for (int k = 0 ; k <= t ; k++) {
synchronized (parties[i]) { synchronized (parties[i]) {
@ -95,7 +162,7 @@ public class User<T> implements Runnable{
try { try {
parties[i].wait(); parties[i].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
@ -117,15 +184,17 @@ public class User<T> implements Runnable{
} }
/**
* wait until all other parties done complaining by receiving done message
*/
protected void waitUntilStageTwoCompleted(){ protected void waitUntilStageTwoCompleted(){
// all parties done or aborted
for (int i = 0 ; i < n ; i++){ for (int i = 0 ; i < n ; i++){
synchronized (parties[i]) { synchronized (parties[i]) {
while (!parties[i].doneFlag && !parties[i].aborted) { while (!parties[i].doneFlag && !parties[i].aborted) {
try { try {
parties[i].wait(); parties[i].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
@ -150,7 +219,7 @@ public class User<T> implements Runnable{
try { try {
parties[i].wait(); parties[i].wait();
} catch (InterruptedException e) { } catch (InterruptedException e) {
//do nothing if (stop) return;
} }
} }
} }
@ -173,18 +242,38 @@ public class User<T> implements Runnable{
@Override @Override
public void run() { public void run() {
this.runThread = Thread.currentThread();
stage1(); stage1();
waitUntilStageOneCompleted(); waitUntilStageOneCompleted();
if (stop) return;
stage2(); stage2();
waitUntilStageTwoCompleted(); waitUntilStageTwoCompleted();
if (stop) return;
stage3(); stage3();
if (stop) return;
stage4(); stage4();
} }
/**
* current thread in the main loop
*/
protected Thread runThread;
/**
* flag indicates if there was request to stop the current run of the protocol
*/
protected boolean stop = false;
/** /**
* Request the current run loop to exit gracefully * Request the current run loop to exit gracefully
*/ */
public void stop() { public void stop() {
try {
stop = true;
runThread.interrupt();
}catch (Exception e){
//do nothing
}
} }
@ -260,12 +349,19 @@ public class User<T> implements Runnable{
return QUAL; return QUAL;
} }
/**
* getter
* @return channel
*/
public Channel getChannel() {
return channel;
}
public class MessageHandler implements meerkat.crypto.concrete.distributed_key_generation.communication.MessageHandler{ /**
* an implementation of MessageHandler
*/
public class MessageHandler implements meerkat.destributed_key_generation.concrete.distributed_key_generation.communication.MessageHandler{
public MessageHandler(){
}
/** /**
* commitment message is valid if: * commitment message is valid if:
* 1. it was received in broadcast chanel * 1. it was received in broadcast chanel
@ -314,7 +410,7 @@ public class User<T> implements Runnable{
* saves the secret * saves the secret
*/ */
@Override @Override
public void handleSecretMessage(int sender, boolean isBroadcast, Message message) { public void handleShareMessage(int sender, boolean isBroadcast, Message message) {
DKGMessages.ShareMessage secretMessage = (DKGMessages.ShareMessage) message; DKGMessages.ShareMessage secretMessage = (DKGMessages.ShareMessage) message;
if(isValidSecretMessage(sender,isBroadcast,secretMessage)) { if(isValidSecretMessage(sender,isBroadcast,secretMessage)) {
int i = secretMessage.getI(); int i = secretMessage.getI();

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.secret_shring.feldman_verifiable; package meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.SecretSharing;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
import java.util.ArrayList; import java.util.ArrayList;
@ -17,12 +17,22 @@ import java.util.Random;
* *
*/ */
public class VerifiableSecretSharing<T> extends SecretSharing { public class VerifiableSecretSharing<T> extends SecretSharing {
/**
* cyclic group contains g.
*/
protected final Group<T> group; protected final Group<T> group;
protected final T g; // public generator of group /**
* 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.
*/
protected final T g;
/**
* commitments to polynomial coefficients.
* commitments[k] = g ^ coefficients[k] (group operation)
*/
protected final ArrayList<T> commitmentsArrayList; protected final ArrayList<T> commitmentsArrayList;
/** /**
* constructor * constructor
* @param q a large prime. * @param q a large prime.

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.secret_shring.shamir; package meerkat.destributed_key_generation.concrete.secret_shring.shamir;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import java.math.BigInteger; import java.math.BigInteger;

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.secret_shring.shamir; package meerkat.destributed_key_generation.concrete.secret_shring.shamir;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Arrays; import java.util.Arrays;
@ -100,7 +100,7 @@ public class Polynomial implements Comparable<Polynomial> {
/** /**
* @param other * @param other
* @return new meerkat.crypto.concrete.secret_shring.shamir.Polynomial of degree max(this degree,other degree) s.t for all x * @return new meerkat.destributed_key_generation.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) * new.evaluate(x) = this.evaluate(x) + other.evaluate(x)
*/ */
public Polynomial add(Polynomial other){ public Polynomial add(Polynomial other){

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.secret_shring.shamir; package meerkat.destributed_key_generation.concrete.secret_shring.shamir;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Random; import java.util.Random;
@ -11,9 +11,21 @@ import java.util.Random;
* an implementation of Shamire's secret sharing scheme * an implementation of Shamire's secret sharing scheme
*/ */
public class SecretSharing{ public class SecretSharing{
/**
* threshold
*/
protected final int t; protected final int t;
/**
* number of shares
*/
protected final int n; protected final int n;
/**
* a large prime
*/
protected final BigInteger q; protected final BigInteger q;
/**
* random polynomial of degree s.t polynomial.evaluate(0) = secret
*/
protected final Polynomial polynomial; protected final Polynomial polynomial;
/** /**

View File

@ -0,0 +1,38 @@
package meerkat.destributed_key_generation.utilitis;
/**
* Created by Tzlil on 3/17/2016.
* defines the properties of the traditional operations : add,sub,mul,div
* between two objects of type T
*/
public interface Arithmetic<T> {
/**
* addition
* @param a
* @param b
* @return a + b
*/
T add(T a, T b);
/**
* subtraction
* @param a
* @param b
* @return a - b
*/
T sub(T a, T b);
/**
* multiplication
* @param a
* @param b
* @return a * b
*/
T mul(T a, T b);
/**
* division
* @param a
* @param b
* @return a / b
*/
T div(T a, T b);
}

View File

@ -1,10 +1,10 @@
package meerkat.crypto.utilitis; package meerkat.destributed_key_generation.utilitis;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**
* A generic commmunication channel that supports point-to-point and broadcast operation * A generic communication channel that supports point-to-point and broadcast operation
*/ */
public interface Channel { public interface Channel {
@ -12,8 +12,20 @@ public interface Channel {
public void receiveMail(DKGMessages.Mail mail); public void receiveMail(DKGMessages.Mail mail);
} }
/**
* sends a private message
* @param destUser destination user's identifier
* @param type message type
* @param msg message
*/
public void sendMessage(int destUser, DKGMessages.Mail.Type type, Message msg); public void sendMessage(int destUser, DKGMessages.Mail.Type type, Message msg);
/**
* broadcasts a message to all parties (including the sender)
* @param type message type
* @param msg message
*/
public void broadcastMessage(DKGMessages.Mail.Type type, Message msg); public void broadcastMessage(DKGMessages.Mail.Type type, Message msg);
/** /**

View File

@ -1,17 +1,22 @@
package meerkat.crypto.utilitis.concrete; package meerkat.destributed_key_generation.utilitis.concrete;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import org.factcenter.qilin.primitives.concrete.Zpstar; import org.factcenter.qilin.primitives.concrete.Zpstar;
import java.math.BigInteger; import java.math.BigInteger;
/** /**
* Created by Tzlil on 3/17/2016. * Created by Tzlil on 3/17/2016.
* an implementation of Arithmetic<BigInteger> over prime fields: integers modulo p
*/ */
public class Fp implements Arithmetic<BigInteger> { public class Fp implements Arithmetic<BigInteger> {
public final BigInteger p; public final BigInteger p;
private final Zpstar zp; private final Zpstar zp;
/**
* constructor
* @param p prime
*/
public Fp(BigInteger p) { public Fp(BigInteger p) {
this.p = p; this.p = p;
this.zp = new Zpstar(p); this.zp = new Zpstar(p);

View File

@ -1,7 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol.*; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.utilitis.Channel;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Random; import java.util.Random;

View File

@ -1,15 +1,15 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import Utils.ChannelImpl; import meerkat.destributed_key_generation.utilitis.ChannelImpl;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
import meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.DKGMaliciousUser; import meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.DKGMaliciousUser;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.SecretSharing;
import Utils.BigIntegerByteEncoder; import meerkat.destributed_key_generation.utilitis.BigIntegerByteEncoder;
import Utils.GenerateRandomPrime; import meerkat.destributed_key_generation.utilitis.GenerateRandomPrime;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
import org.factcenter.qilin.primitives.concrete.Zpstar; import org.factcenter.qilin.primitives.concrete.Zpstar;
import org.factcenter.qilin.util.ByteEncoder; import org.factcenter.qilin.util.ByteEncoder;
@ -27,25 +27,16 @@ import java.util.Set;
*/ */
public class SDKGTest { public class SDKGTest {
int tests = 1; int tests = 10;
BigInteger p = GenerateRandomPrime.SafePrime100Bits; BigInteger p = GenerateRandomPrime.SafePrime100Bits;
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)); BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
Group<BigInteger> group = new Zpstar(p); Group<BigInteger> group = new Zpstar(p);
Arithmetic<BigInteger> arithmetic = new Fp(q); Arithmetic<BigInteger> arithmetic = new Fp(q);
int t = 9; int t = 9;
int n = 20; 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 { public void oneTest(Testable testable) throws Exception {
Testable testable = testables[test];
for (int i = 0; i < testable.threads.length ; i++){ for (int i = 0; i < testable.threads.length ; i++){
testable.threads[i].start(); testable.threads[i].start();
} }
@ -83,13 +74,23 @@ public class SDKGTest {
assert (calculatedSecret.equals(testable.secret)); assert (calculatedSecret.equals(testable.secret));
} }
@Test public void stopReceivers(Testable testable){
public void test() throws Exception { ChannelImpl channel;
for (int i = 0; i < tests; i++){ for (int i = 0 ; i < testable.sdkgs.length ; i++){
oneTest(i); channel = (ChannelImpl)testable.sdkgs[i].getChannel();
channel.stop();
} }
} }
@Test
public void test() throws Exception {
Testable testable;
for (int i = 0; i < tests; i++) {
testable = new Testable(new Random());
oneTest(testable);
stopReceivers(testable);
}
}
class Testable{ class Testable{
Set<Integer> valids; Set<Integer> valids;
Set<Integer> QUAL; Set<Integer> QUAL;

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.gjkr_secure_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.gjkr_secure_protocol;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.*; import java.util.*;

View File

@ -1,15 +1,14 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import Utils.ChannelImpl; import meerkat.destributed_key_generation.utilitis.ChannelImpl;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.crypto.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable.VerifiableSecretSharing;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import meerkat.crypto.concrete.secret_shring.shamir.SecretSharing; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.SecretSharing;
import Utils.BigIntegerByteEncoder; import meerkat.destributed_key_generation.utilitis.BigIntegerByteEncoder;
import Utils.GenerateRandomPrime; import meerkat.destributed_key_generation.utilitis.GenerateRandomPrime;
import meerkat.protobuf.Crypto;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
import org.factcenter.qilin.primitives.concrete.Zpstar; import org.factcenter.qilin.primitives.concrete.Zpstar;
import org.factcenter.qilin.util.ByteEncoder; import org.factcenter.qilin.util.ByteEncoder;
@ -27,7 +26,7 @@ import java.util.Set;
*/ */
public class DKGTest { public class DKGTest {
int tests = 1; int tests = 10;
BigInteger p = GenerateRandomPrime.SafePrime100Bits; BigInteger p = GenerateRandomPrime.SafePrime100Bits;
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)); BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
Group<BigInteger> group = new Zpstar(p); Group<BigInteger> group = new Zpstar(p);
@ -35,18 +34,7 @@ public class DKGTest {
int t = 9; int t = 9;
int n = 20; int n = 20;
Testable[] testables; public void oneTest(Testable testable) throws Exception {
@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++){ for (int i = 0; i < testable.threads.length ; i++){
testable.threads[i].start(); testable.threads[i].start();
} }
@ -84,10 +72,21 @@ public class DKGTest {
assert (calculatedSecret.equals(testable.secret)); assert (calculatedSecret.equals(testable.secret));
} }
public void stopReceivers(Testable testable){
ChannelImpl channel;
for (int i = 0 ; i < testable.dkgs.length ; i++){
channel = (ChannelImpl)testable.dkgs[i].getChannel();
channel.stop();
}
}
@Test @Test
public void test() throws Exception { public void test() throws Exception {
Testable testable;
for (int i = 0; i < tests; i++){ for (int i = 0; i < tests; i++){
oneTest(i); testable = new Testable(new Random());
oneTest(testable);
stopReceivers(testable);
} }
} }
@ -117,13 +116,13 @@ public class DKGTest {
BigInteger s; BigInteger s;
Protocol<BigInteger> dkg; Protocol<BigInteger> dkg;
this.secret = BigInteger.ZERO; this.secret = BigInteger.ZERO;
Channel channel; ChannelImpl channel;
ByteEncoder<BigInteger> byteEncoder = new BigIntegerByteEncoder(); ByteEncoder<BigInteger> byteEncoder = new BigIntegerByteEncoder();
while (!ids.isEmpty()) { while (!ids.isEmpty()) {
id = ids.remove(random.nextInt(ids.size())); id = ids.remove(random.nextInt(ids.size()));
channel = new ChannelImpl(id,n); channel = new ChannelImpl(id,n);
s = randomIntModQ(random); s = randomIntModQ(random);
dkg = new meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol.Protocol<BigInteger>(t, n, s, random, q, g, group, id,byteEncoder); dkg = new meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol.Protocol<BigInteger>(t, n, s, random, q, g, group, id,byteEncoder);
dkgs[id - 1] = randomDKGUser(id,channel,dkg,random); dkgs[id - 1] = randomDKGUser(id,channel,dkg,random);
threads[id - 1] = new Thread(dkgs[id - 1]); threads[id - 1] = new Thread(dkgs[id - 1]);
if(QUAL.contains(id)){ if(QUAL.contains(id)){

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.distributed_key_generation.joint_feldman_protocol; package meerkat.destributed_key_generation.concrete.distributed_key_generation.joint_feldman_protocol;
import meerkat.crypto.utilitis.Channel; import meerkat.destributed_key_generation.utilitis.Channel;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
/** /**

View File

@ -1,6 +1,6 @@
package meerkat.crypto.concrete.secret_shring.feldman_verifiable; package meerkat.destributed_key_generation.concrete.secret_shring.feldman_verifiable;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import org.factcenter.qilin.primitives.Group; import org.factcenter.qilin.primitives.Group;
import org.factcenter.qilin.primitives.concrete.Zpstar; import org.factcenter.qilin.primitives.concrete.Zpstar;
import org.junit.Before; import org.junit.Before;

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests; package meerkat.destributed_key_generation.concrete.secret_shring.shamir.PolynomialTests;
import Utils.GenerateRandomPolynomial; import meerkat.destributed_key_generation.utilitis.GenerateRandomPolynomial;
import Utils.Z; import meerkat.destributed_key_generation.utilitis.Z;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -1,10 +1,10 @@
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests; package meerkat.destributed_key_generation.concrete.secret_shring.shamir.PolynomialTests;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.Arithmetic;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import Utils.GenerateRandomPolynomial; import meerkat.destributed_key_generation.utilitis.GenerateRandomPolynomial;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import Utils.GenerateRandomPrime; import meerkat.destributed_key_generation.utilitis.GenerateRandomPrime;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -1,8 +1,8 @@
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests; package meerkat.destributed_key_generation.concrete.secret_shring.shamir.PolynomialTests;
import Utils.GenerateRandomPolynomial; import meerkat.destributed_key_generation.utilitis.GenerateRandomPolynomial;
import Utils.Z; import meerkat.destributed_key_generation.utilitis.Z;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -1,8 +1,8 @@
package meerkat.crypto.concrete.secret_shring.shamir.PolynomialTests; package meerkat.destributed_key_generation.concrete.secret_shring.shamir.PolynomialTests;
import Utils.GenerateRandomPolynomial; import meerkat.destributed_key_generation.utilitis.GenerateRandomPolynomial;
import Utils.Z; import meerkat.destributed_key_generation.utilitis.Z;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;

View File

@ -1,7 +1,7 @@
package meerkat.crypto.concrete.secret_shring.shamir; package meerkat.destributed_key_generation.concrete.secret_shring.shamir;
import meerkat.crypto.utilitis.concrete.Fp; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import Utils.GenerateRandomPrime; import meerkat.destributed_key_generation.utilitis.GenerateRandomPrime;
import org.factcenter.qilin.primitives.CyclicGroup; import org.factcenter.qilin.primitives.CyclicGroup;
import org.factcenter.qilin.primitives.concrete.Zn; import org.factcenter.qilin.primitives.concrete.Zn;
import org.junit.Before; import org.junit.Before;

View File

@ -1,4 +1,4 @@
package Utils; package meerkat.destributed_key_generation.utilitis;
import java.math.BigInteger; import java.math.BigInteger;

View File

@ -1,7 +1,6 @@
package Utils; package meerkat.destributed_key_generation.utilitis;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.utilitis.Channel;
import meerkat.protobuf.DKGMessages; import meerkat.protobuf.DKGMessages;
import java.util.Queue; import java.util.Queue;
@ -76,13 +75,17 @@ public class ChannelImpl implements Channel {
} }
} }
@Override public void stop(){
public void registerReceiverCallback(final ReceiverCallback callback) {
try{ try{
receiverThread.interrupt(); receiverThread.interrupt();
}catch (Exception e){ }catch (Exception e){
//do nothing //do nothing
} }
}
@Override
public void registerReceiverCallback(final ReceiverCallback callback) {
stop();
receiverThread = new Thread(new Runnable() { receiverThread = new Thread(new Runnable() {
@Override @Override
public void run() { public void run() {

View File

@ -1,31 +1,30 @@
package Utils; package meerkat.destributed_key_generation.utilitis;
import meerkat.crypto.concrete.secret_shring.shamir.Polynomial; import meerkat.destributed_key_generation.concrete.secret_shring.shamir.Polynomial;
import meerkat.crypto.utilitis.Arithmetic; import meerkat.destributed_key_generation.utilitis.concrete.Fp;
import meerkat.crypto.utilitis.concrete.Fp;
import java.math.BigInteger;
import java.math.BigInteger; import java.util.Random;
import java.util.Random;
/**
/** * Created by Tzlil on 1/27/2016.
* Created by Tzlil on 1/27/2016. */
*/ public class GenerateRandomPolynomial {
public class GenerateRandomPolynomial {
public static Polynomial generateRandomPolynomial(int degree, int bits, Random random, Arithmetic<BigInteger> arithmetic) {
public static Polynomial generateRandomPolynomial(int degree, int bits, Random random, Arithmetic<BigInteger> arithmetic) { BigInteger[] coefficients = new BigInteger[degree + 1];
BigInteger[] coefficients = new BigInteger[degree + 1];
for (int i = 0 ; i <= degree; i++ ){
for (int i = 0 ; i <= degree; i++ ){ coefficients[i] = new BigInteger(bits,random); // sample from Zp [0,... q-1]
coefficients[i] = new BigInteger(bits,random); // sample from Zp [0,... q-1] }
} return new Polynomial(coefficients,arithmetic);
return new Polynomial(coefficients,arithmetic); }
}
public static Polynomial generateRandomPolynomial(int degree,int bits,Random random,BigInteger p) {
public static Polynomial generateRandomPolynomial(int degree,int bits,Random random,BigInteger p) { BigInteger[] coefficients = generateRandomPolynomial(degree,bits,random,new Fp(p)).getCoefficients();
BigInteger[] coefficients = generateRandomPolynomial(degree,bits,random,new Fp(p)).getCoefficients(); for (int i = 0; i<coefficients.length;i++){
for (int i = 0; i<coefficients.length;i++){ coefficients[i] = coefficients[i].mod(p);
coefficients[i] = coefficients[i].mod(p); }
} return new Polynomial(coefficients,new Fp(p));
return new Polynomial(coefficients,new Fp(p)); }
} }
}

View File

@ -1,32 +1,30 @@
package Utils; package meerkat.destributed_key_generation.utilitis;
import org.junit.Test; import java.math.BigInteger;
import java.util.Random;
import java.math.BigInteger;
import java.util.Random; /**
* Created by Tzlil on 3/28/2016.
/** */
* Created by Tzlil on 3/28/2016. public class GenerateRandomPrime {
*/ private final static int Certainty = 10000;
public class GenerateRandomPrime { public final static BigInteger SafePrime100Bits = new BigInteger("146407324427772525685319783363");
private final static int Certainty = 10000;
public final static BigInteger SafePrime100Bits = new BigInteger("146407324427772525685319783363"); public static BigInteger generateRandomPrime(int bits, Random random) {
BigInteger p;
public static BigInteger generateRandomPrime(int bits, Random random) { do {
BigInteger p; p = new BigInteger(bits, random);
do { } while (!p.isProbablePrime(Certainty));
p = new BigInteger(bits, random); return p;
} while (!p.isProbablePrime(Certainty)); }
return p;
} public static BigInteger generateRandomSafePrime(int bits, Random random) {
BigInteger p;
public static BigInteger generateRandomSafePrime(int bits, Random random) { BigInteger q;
BigInteger p; do {
BigInteger q; p = generateRandomPrime(bits, random);
do { q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
p = generateRandomPrime(bits, random); } while (!q.isProbablePrime(Certainty));
q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2)); return q;
} while (!q.isProbablePrime(Certainty)); }
return q; }
}
}

View File

@ -1,6 +1,4 @@
package Utils; package meerkat.destributed_key_generation.utilitis;
import meerkat.crypto.utilitis.Arithmetic;
import java.math.BigInteger; import java.math.BigInteger;

View File

@ -1,38 +1,38 @@
package meerkat.crypto; package meerkat.destributed_key_generation;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import java.security.MessageDigest; import java.security.MessageDigest;
/** /**
* Created by talm on 11/9/15. * Created by talm on 11/9/15.
*/ */
public interface Digest { public interface Digest {
/** /**
* Completes the hash computation by performing final operations such as padding. * Completes the hash computation by performing final operations such as padding.
* (copied from {@link MessageDigest#digest()}) * (copied from {@link MessageDigest#digest()})
* @return * @return
*/ */
byte[] digest(); byte[] digest();
/** /**
* Updates the digest using the specified message (in serialized wire form) * Updates the digest using the specified message (in serialized wire form)
* *
* Each message is (automatically) prepended with its length as a 32-bit big-endian unsigned integer. * Each message is (automatically) prepended with its length as a 32-bit big-endian unsigned integer.
* @param msg * @param msg
* @return * @return
*/ */
void update(Message msg); void update(Message msg);
/** /**
* Resets the digest for further use. * Resets the digest for further use.
*/ */
void reset(); void reset();
/** /**
* Clone the current digest state * Clone the current digest state
* @return * @return
*/ */
public Digest clone() throws CloneNotSupportedException; public Digest clone() throws CloneNotSupportedException;
} }

View File

@ -1,96 +1,96 @@
package meerkat.crypto; package meerkat.destributed_key_generation;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.security.InvalidKeyException; import java.security.InvalidKeyException;
import java.security.KeyStore; import java.security.KeyStore;
import java.security.SignatureException; import java.security.SignatureException;
import java.security.UnrecoverableKeyException; import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException; import java.security.cert.CertificateException;
import static meerkat.protobuf.Crypto.*; import static meerkat.protobuf.Crypto.*;
/** /**
* Created by talm on 25/10/15. * Created by talm on 25/10/15.
* *
* Sign and verify arrays of messages * Sign and verify arrays of messages
*/ */
public interface DigitalSignature { public interface DigitalSignature {
final public static String CERTIFICATE_ENCODING_X509 = "X.509"; final public static String CERTIFICATE_ENCODING_X509 = "X.509";
/** /**
* Load a set of certificates from an input stream. * Load a set of certificates from an input stream.
* This will consume the entire stream. * This will consume the entire stream.
* Certificates can be either DER-encoded (binary) or PEM (base64) encoded. * Certificates can be either DER-encoded (binary) or PEM (base64) encoded.
* This may be called multiple times to load several different certificates. * This may be called multiple times to load several different certificates.
* It must be called before calling {@link #verify()}. * It must be called before calling {@link #verify()}.
* @param certStream source from which certificates are loaded * @param certStream source from which certificates are loaded
* @throws CertificateException on parsing errors * @throws CertificateException on parsing errors
*/ */
public void loadVerificationCertificates(InputStream certStream) public void loadVerificationCertificates(InputStream certStream)
throws CertificateException; throws CertificateException;
/** /**
* Clear the loaded verification certificates. * Clear the loaded verification certificates.
*/ */
public void clearVerificationCertificates(); public void clearVerificationCertificates();
/** /**
* Add msg to the content stream to be verified / signed. Each message is (automatically) * Add msg to the content stream to be verified / signed. Each message is (automatically)
* prepended with its length as a 32-bit big-endian unsigned integer. * prepended with its length as a 32-bit big-endian unsigned integer.
* *
* @param msg * @param msg
* @throws SignatureException * @throws SignatureException
*/ */
public void updateContent(Message msg) throws SignatureException; public void updateContent(Message msg) throws SignatureException;
/** /**
* Sign the content that was added using {@link #updateContent(Message)}. * Sign the content that was added using {@link #updateContent(Message)}.
* Reset the DigitalSignature and make it available to sign a new message using the same key. * Reset the DigitalSignature and make it available to sign a new message using the same key.
* @return * @return
* @throws SignatureException * @throws SignatureException
*/ */
Signature sign() throws SignatureException; Signature sign() throws SignatureException;
/** /**
* Initialize the verifier with the certificate whose Id is in sig. * Initialize the verifier with the certificate whose Id is in sig.
* @param sig * @param sig
* @throws CertificateException * @throws CertificateException
* @throws InvalidKeyException * @throws InvalidKeyException
*/ */
void initVerify(Signature sig) void initVerify(Signature sig)
throws CertificateException, InvalidKeyException; throws CertificateException, InvalidKeyException;
/** /**
* Verify the updated content using the initialized signature. * Verify the updated content using the initialized signature.
* @return * @return
*/ */
public boolean verify(); public boolean verify();
/** /**
* Loads a private signing key. The keystore must include both the public and private * Loads a private signing key. The keystore must include both the public and private
* key parts. * key parts.
* This method must be called before calling {@link #sign()} or {@link #updateContent(Message)} * This method must be called before calling {@link #sign()} or {@link #updateContent(Message)}
* Calling this method again will replace the key. * Calling this method again will replace the key.
* *
* @param keyStoreBuilder A keystore builder that can be used to load a keystore. * @param keyStoreBuilder A keystore builder that can be used to load a keystore.
*/ */
public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder)
throws IOException, CertificateException, UnrecoverableKeyException; throws IOException, CertificateException, UnrecoverableKeyException;
/** /**
* @return the signer ID if it exists; null otherwise. * @return the signer ID if it exists; null otherwise.
*/ */
public ByteString getSignerID(); public ByteString getSignerID();
/** /**
* Clear the signing key (will require authentication to use again). * Clear the signing key (will require authentication to use again).
*/ */
public void clearSigningKey(); public void clearSigningKey();
} }

View File

@ -1,40 +1,40 @@
package meerkat.crypto; package meerkat.destributed_key_generation;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import java.io.IOException; import java.io.IOException;
import java.util.Random; import java.util.Random;
import static meerkat.protobuf.Crypto.*; import static meerkat.protobuf.Crypto.*;
/** /**
* Created by talm on 11/2/15. * Created by talm on 11/2/15.
*/ */
public interface Encryption { public interface Encryption {
/** /**
* Encrypt the serialized form of a message plaintext. * Encrypt the serialized form of a message plaintext.
* @param plaintext * @param plaintext
* @param rnd * @param rnd
* @return * @return
*/ */
RerandomizableEncryptedMessage encrypt(Message plaintext, EncryptionRandomness rnd) throws IOException; // TODO: type of exception; throws RerandomizableEncryptedMessage encrypt(Message plaintext, EncryptionRandomness rnd) throws IOException; // TODO: type of exception; throws
/** /**
* Rerandomize a ciphertext using the supplied randomness. * Rerandomize a ciphertext using the supplied randomness.
* @param msg * @param msg
* @param rnd * @param rnd
* @return * @return
* @throws InvalidProtocolBufferException * @throws InvalidProtocolBufferException
*/ */
RerandomizableEncryptedMessage rerandomize(RerandomizableEncryptedMessage msg, EncryptionRandomness rnd) throws InvalidProtocolBufferException; RerandomizableEncryptedMessage rerandomize(RerandomizableEncryptedMessage msg, EncryptionRandomness rnd) throws InvalidProtocolBufferException;
/** /**
* Generate randomness compatible with {@link #encrypt(Message, EncryptionRandomness) and * Generate randomness compatible with {@link #encrypt(Message, EncryptionRandomness) and
* {@link #rerandomize(RerandomizableEncryptedMessage, EncryptionRandomness)}}. * {@link #rerandomize(RerandomizableEncryptedMessage, EncryptionRandomness)}}.
* @param rand * @param rand
* @return * @return
*/ */
EncryptionRandomness generateRandomness(Random rand); EncryptionRandomness generateRandomness(Random rand);
} }

View File

@ -1,134 +1,134 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Crypto.Signature; import meerkat.protobuf.Crypto.Signature;
import org.bouncycastle.asn1.ASN1Integer; import org.bouncycastle.asn1.ASN1Integer;
import org.bouncycastle.asn1.DERSequence; import org.bouncycastle.asn1.DERSequence;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECPrivateKeyParameters; import org.bouncycastle.crypto.params.ECPrivateKeyParameters;
import org.bouncycastle.crypto.signers.DSAKCalculator; import org.bouncycastle.crypto.signers.DSAKCalculator;
import org.bouncycastle.crypto.signers.ECDSASigner; import org.bouncycastle.crypto.signers.ECDSASigner;
import org.bouncycastle.crypto.signers.HMacDSAKCalculator; import org.bouncycastle.crypto.signers.HMacDSAKCalculator;
import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil; import org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
import java.security.interfaces.ECPrivateKey; import java.security.interfaces.ECPrivateKey;
/** /**
* Sign and verify digital signatures. * Sign and verify digital signatures.
* *
* Uses deterministic ECDSA signatures as per RFC 6979 * Uses deterministic ECDSA signatures as per RFC 6979
* *
* This class uses BouncyCastle directly, so will not work with arbitrary PKCS11 providers. * This class uses BouncyCastle directly, so will not work with arbitrary PKCS11 providers.
* *
* This class is not thread-safe (each thread should have its own instance). * This class is not thread-safe (each thread should have its own instance).
*/ */
public class ECDSADeterministicSignature extends ECDSASignature { public class ECDSADeterministicSignature extends ECDSASignature {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
/** /**
* Digest of message contents for deterministic signing. * Digest of message contents for deterministic signing.
*/ */
SHA256Digest msgDigest = new SHA256Digest(); SHA256Digest msgDigest = new SHA256Digest();
/** /**
* The actual signing implementation. (used only signing -- superclass is used for verification) * The actual signing implementation. (used only signing -- superclass is used for verification)
*/ */
ECDSASigner deterministicSigner; ECDSASigner deterministicSigner;
/** /**
* Output the DER encoding of the ASN.1 sequence r,s * Output the DER encoding of the ASN.1 sequence r,s
* @param r * @param r
* @param s * @param s
* @return * @return
*/ */
public static byte[] derEncodeSignature(BigInteger r, BigInteger s) { public static byte[] derEncodeSignature(BigInteger r, BigInteger s) {
ASN1Integer[] rs = {new ASN1Integer(r), new ASN1Integer(s)}; ASN1Integer[] rs = {new ASN1Integer(r), new ASN1Integer(s)};
DERSequence seq = new DERSequence(rs); DERSequence seq = new DERSequence(rs);
try { try {
return seq.getEncoded(); return seq.getEncoded();
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException("Should never happen! DER Encoding exception", e); throw new RuntimeException("Should never happen! DER Encoding exception", e);
} }
} }
public ECDSADeterministicSignature() { public ECDSADeterministicSignature() {
DSAKCalculator kCalk = new HMacDSAKCalculator(new org.bouncycastle.crypto.digests.SHA256Digest()); DSAKCalculator kCalk = new HMacDSAKCalculator(new org.bouncycastle.crypto.digests.SHA256Digest());
deterministicSigner = new ECDSASigner(kCalk); deterministicSigner = new ECDSASigner(kCalk);
} }
@Override @Override
public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder)
throws CertificateException, UnrecoverableKeyException, IOException { throws CertificateException, UnrecoverableKeyException, IOException {
super.loadSigningCertificate(keyStoreBuilder); super.loadSigningCertificate(keyStoreBuilder);
if (!(loadedSigningKey instanceof ECPrivateKey)) { if (!(loadedSigningKey instanceof ECPrivateKey)) {
logger.error("Wrong private key type (expected ECPrivateKey, got {})", loadedSigningKey.getClass()); logger.error("Wrong private key type (expected ECPrivateKey, got {})", loadedSigningKey.getClass());
throw new CertificateException("Wrong signing key type!"); throw new CertificateException("Wrong signing key type!");
} }
ECPrivateKey key = (ECPrivateKey) loadedSigningKey; ECPrivateKey key = (ECPrivateKey) loadedSigningKey;
AsymmetricKeyParameter baseParams; AsymmetricKeyParameter baseParams;
try { try {
baseParams = ECUtil.generatePrivateKeyParameter(key); baseParams = ECUtil.generatePrivateKeyParameter(key);
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
throw new UnrecoverableKeyException("Couldn't convert private key"); throw new UnrecoverableKeyException("Couldn't convert private key");
} }
if (!(baseParams instanceof ECPrivateKeyParameters)) { if (!(baseParams instanceof ECPrivateKeyParameters)) {
logger.error("Error converting to bouncycastle type! (got {})", baseParams.getClass()); logger.error("Error converting to bouncycastle type! (got {})", baseParams.getClass());
throw new UnrecoverableKeyException("Wrong signing key type!"); throw new UnrecoverableKeyException("Wrong signing key type!");
} }
ECPrivateKeyParameters params = (ECPrivateKeyParameters) baseParams; ECPrivateKeyParameters params = (ECPrivateKeyParameters) baseParams;
deterministicSigner.init(true, params); deterministicSigner.init(true, params);
} }
/** /**
* Add the list of messages to the stream that is being verified/signed. * Add the list of messages to the stream that is being verified/signed.
* Messages are prepended with their length in 32-bit big-endian format. * Messages are prepended with their length in 32-bit big-endian format.
* *
* @param msg * @param msg
* @throws SignatureException * @throws SignatureException
*/ */
@Override @Override
public void updateContent(Message msg) throws SignatureException { public void updateContent(Message msg) throws SignatureException {
assert msg != null; assert msg != null;
// We're doing twice the digest work so that we also support verification with the same update. // We're doing twice the digest work so that we also support verification with the same update.
// If this becomes a problem, we can decide which way to update based on which init was called. // If this becomes a problem, we can decide which way to update based on which init was called.
super.updateContent(msg); super.updateContent(msg);
msgDigest.update(msg); msgDigest.update(msg);
} }
@Override @Override
public void updateContent(InputStream in) throws IOException, SignatureException { public void updateContent(InputStream in) throws IOException, SignatureException {
ByteString inStr = ByteString.readFrom(in); ByteString inStr = ByteString.readFrom(in);
signer.update(inStr.asReadOnlyByteBuffer()); signer.update(inStr.asReadOnlyByteBuffer());
msgDigest.update(inStr); msgDigest.update(inStr);
} }
@Override @Override
public Signature sign() throws SignatureException { public Signature sign() throws SignatureException {
Signature.Builder sig = Signature.newBuilder(); Signature.Builder sig = Signature.newBuilder();
sig.setType(Crypto.SignatureType.ECDSA); sig.setType(Crypto.SignatureType.ECDSA);
BigInteger[] rawSig = deterministicSigner.generateSignature(msgDigest.digest()); BigInteger[] rawSig = deterministicSigner.generateSignature(msgDigest.digest());
sig.setData(ByteString.copyFrom(derEncodeSignature(rawSig[0], rawSig[1]))); sig.setData(ByteString.copyFrom(derEncodeSignature(rawSig[0], rawSig[1])));
sig.setSignerId(loadedSigningKeyId); sig.setSignerId(loadedSigningKeyId);
return sig.build(); return sig.build();
} }
} }

View File

@ -1,322 +1,322 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.*; import java.security.*;
import java.security.cert.*; import java.security.cert.*;
import java.security.cert.Certificate; import java.security.cert.Certificate;
import java.util.*; import java.util.*;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.util.Hex; import meerkat.util.Hex;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.DigitalSignature; import meerkat.destributed_key_generation.DigitalSignature;
import meerkat.protobuf.Crypto.Signature; import meerkat.protobuf.Crypto.Signature;
import javax.security.auth.callback.Callback; import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler; import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.PasswordCallback; import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.UnsupportedCallbackException; import javax.security.auth.callback.UnsupportedCallbackException;
/** /**
* Sign and verify digital signatures. * Sign and verify digital signatures.
* *
* This class is not thread-safe (each thread should have its own instance). * This class is not thread-safe (each thread should have its own instance).
*/ */
public class ECDSASignature extends GlobalCryptoSetup implements DigitalSignature { public class ECDSASignature extends GlobalCryptoSetup implements DigitalSignature {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
final public static String KEYSTORE_TYPE = "PKCS12"; final public static String KEYSTORE_TYPE = "PKCS12";
final public static String DEFAULT_SIGNATURE_ALGORITHM = "SHA256withECDSA"; final public static String DEFAULT_SIGNATURE_ALGORITHM = "SHA256withECDSA";
SHA256Digest certDigest = new SHA256Digest(); SHA256Digest certDigest = new SHA256Digest();
/** /**
* Buffer used to hold length in for hash update * Buffer used to hold length in for hash update
*/ */
ByteBuffer lenBuf = ByteBuffer.allocate(4); ByteBuffer lenBuf = ByteBuffer.allocate(4);
Map<ByteString, Certificate> loadedCertificates = new HashMap<>(); Map<ByteString, Certificate> loadedCertificates = new HashMap<>();
/** /**
* Signature currently loaded (will be used in calls to {@link #verify()}). * Signature currently loaded (will be used in calls to {@link #verify()}).
*/ */
ByteString loadedSignature = null; ByteString loadedSignature = null;
ByteString loadedSigningKeyId = null; ByteString loadedSigningKeyId = null;
/** /**
* The actual signing implementation. (used for both signing and verifying) * The actual signing implementation. (used for both signing and verifying)
*/ */
java.security.Signature signer; java.security.Signature signer;
/** /**
* The currently loaded signing key. * The currently loaded signing key.
*/ */
PrivateKey loadedSigningKey; PrivateKey loadedSigningKey;
/** /**
* Compute a fingerprint of a cert as a SHA256 hash. * Compute a fingerprint of a cert as a SHA256 hash.
* *
* @param cert * @param cert
* @return * @return
*/ */
public ByteString computeCertificateFingerprint(Certificate cert) { public ByteString computeCertificateFingerprint(Certificate cert) {
try { try {
certDigest.reset(); certDigest.reset();
byte[] data = cert.getEncoded(); byte[] data = cert.getEncoded();
certDigest.update(data); certDigest.update(data);
return ByteString.copyFrom(certDigest.digest()); return ByteString.copyFrom(certDigest.digest());
} catch (CertificateEncodingException e) { } catch (CertificateEncodingException e) {
// Shouldn't happen // Shouldn't happen
logger.error("Certificate encoding error", e); logger.error("Certificate encoding error", e);
throw new RuntimeException("Certificate encoding error", e); throw new RuntimeException("Certificate encoding error", e);
} }
} }
public ECDSASignature(java.security.Signature signer) { public ECDSASignature(java.security.Signature signer) {
this.signer = signer; this.signer = signer;
} }
public ECDSASignature() { public ECDSASignature() {
try { try {
this.signer = java.security.Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM); this.signer = java.security.Signature.getInstance(DEFAULT_SIGNATURE_ALGORITHM);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// Should never happen // Should never happen
logger.error("Couldn't find implementation for " + DEFAULT_SIGNATURE_ALGORITHM + " signatures", e); logger.error("Couldn't find implementation for " + DEFAULT_SIGNATURE_ALGORITHM + " signatures", e);
} }
} }
@Override @Override
public void loadVerificationCertificates(InputStream certStream) public void loadVerificationCertificates(InputStream certStream)
throws CertificateException { throws CertificateException {
CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_ENCODING_X509); CertificateFactory certificateFactory = CertificateFactory.getInstance(CERTIFICATE_ENCODING_X509);
Collection<? extends Certificate> certs = certificateFactory.generateCertificates(certStream); Collection<? extends Certificate> certs = certificateFactory.generateCertificates(certStream);
for (Certificate cert : certs) { for (Certificate cert : certs) {
// Just checking // Just checking
if (!(cert instanceof X509Certificate)) { if (!(cert instanceof X509Certificate)) {
logger.error("Certificate must be in X509 format; got {} instead!", cert.getClass().getCanonicalName()); logger.error("Certificate must be in X509 format; got {} instead!", cert.getClass().getCanonicalName());
continue; continue;
} }
ByteString keyId = computeCertificateFingerprint(cert); ByteString keyId = computeCertificateFingerprint(cert);
loadedCertificates.put(keyId, cert); loadedCertificates.put(keyId, cert);
} }
} }
@Override @Override
public void clearVerificationCertificates() { public void clearVerificationCertificates() {
loadedCertificates.clear(); loadedCertificates.clear();
} }
/** /**
* Add the list of messages to the stream that is being verified/signed. * Add the list of messages to the stream that is being verified/signed.
* Messages are prepended with their length in 32-bit big-endian format. * Messages are prepended with their length in 32-bit big-endian format.
* *
* @param msg * @param msg
* @throws SignatureException * @throws SignatureException
*/ */
@Override @Override
public void updateContent(Message msg) throws SignatureException { public void updateContent(Message msg) throws SignatureException {
assert msg != null; assert msg != null;
lenBuf.clear(); lenBuf.clear();
lenBuf.putInt(msg.getSerializedSize()); lenBuf.putInt(msg.getSerializedSize());
lenBuf.flip(); lenBuf.flip();
signer.update(lenBuf); signer.update(lenBuf);
signer.update(msg.toByteString().asReadOnlyByteBuffer()); signer.update(msg.toByteString().asReadOnlyByteBuffer());
} }
public void updateContent(InputStream in) throws IOException, SignatureException { public void updateContent(InputStream in) throws IOException, SignatureException {
ByteString inStr = ByteString.readFrom(in); ByteString inStr = ByteString.readFrom(in);
signer.update(inStr.asReadOnlyByteBuffer()); signer.update(inStr.asReadOnlyByteBuffer());
} }
@Override @Override
public Signature sign() throws SignatureException { public Signature sign() throws SignatureException {
Signature.Builder sig = Signature.newBuilder(); Signature.Builder sig = Signature.newBuilder();
sig.setType(Crypto.SignatureType.ECDSA); sig.setType(Crypto.SignatureType.ECDSA);
sig.setData(ByteString.copyFrom(signer.sign())); sig.setData(ByteString.copyFrom(signer.sign()));
sig.setSignerId(loadedSigningKeyId); sig.setSignerId(loadedSigningKeyId);
return sig.build(); return sig.build();
} }
@Override @Override
public void initVerify(Signature sig) public void initVerify(Signature sig)
throws CertificateException, InvalidKeyException { throws CertificateException, InvalidKeyException {
Certificate cert = loadedCertificates.get(sig.getSignerId()); Certificate cert = loadedCertificates.get(sig.getSignerId());
if (cert == null) { if (cert == null) {
logger.warn("No certificate loaded for ID {}!", sig.getSignerId()); logger.warn("No certificate loaded for ID {}!", sig.getSignerId());
throw new CertificateException("No certificate loaded for " + sig.getSignerId()); throw new CertificateException("No certificate loaded for " + sig.getSignerId());
} }
signer.initVerify(cert.getPublicKey()); signer.initVerify(cert.getPublicKey());
loadedSignature = sig.getData(); loadedSignature = sig.getData();
loadedSigningKeyId = null; loadedSigningKeyId = null;
} }
@Override @Override
public boolean verify() { public boolean verify() {
try { try {
return signer.verify(loadedSignature.toByteArray()); return signer.verify(loadedSignature.toByteArray());
} catch (SignatureException e) { } catch (SignatureException e) {
// Happens only if signature is invalid! // Happens only if signature is invalid!
logger.error("Signature exception", e); logger.error("Signature exception", e);
return false; return false;
} }
} }
/** /**
* Utility method to more easily deal with simple password-protected files. * Utility method to more easily deal with simple password-protected files.
* *
* @param password * @param password
* @return * @return
*/ */
public CallbackHandler getFixedPasswordHandler(final char[] password) { public CallbackHandler getFixedPasswordHandler(final char[] password) {
return new CallbackHandler() { return new CallbackHandler() {
@Override @Override
public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException { public void handle(Callback[] callbacks) throws IOException, UnsupportedCallbackException {
for (Callback callback : callbacks) { for (Callback callback : callbacks) {
if (callback instanceof PasswordCallback) { if (callback instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback) callback; PasswordCallback passwordCallback = (PasswordCallback) callback;
logger.debug("Requested password ({})", passwordCallback.getPrompt()); logger.debug("Requested password ({})", passwordCallback.getPrompt());
passwordCallback.setPassword(password); passwordCallback.setPassword(password);
} }
} }
} }
}; };
} }
/** /**
* Load a keystore from an input stream in PKCS12 format. * Load a keystore from an input stream in PKCS12 format.
* *
* @param keyStream * @param keyStream
* @param password * @param password
* @return * @return
* @throws IOException * @throws IOException
* @throws CertificateException * @throws CertificateException
* @throws KeyStoreException * @throws KeyStoreException
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public KeyStore.Builder getPKCS12KeyStoreBuilder(InputStream keyStream, char[] password) public KeyStore.Builder getPKCS12KeyStoreBuilder(InputStream keyStream, char[] password)
throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException { throws IOException, CertificateException, KeyStoreException, NoSuchAlgorithmException {
KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE); KeyStore keyStore = KeyStore.getInstance(KEYSTORE_TYPE);
keyStore.load(keyStream, password); keyStore.load(keyStream, password);
return KeyStore.Builder.newInstance(keyStore, new KeyStore.CallbackHandlerProtection(getFixedPasswordHandler(password))); return KeyStore.Builder.newInstance(keyStore, new KeyStore.CallbackHandlerProtection(getFixedPasswordHandler(password)));
} }
/** /**
* For now we only support PKCS12. * For now we only support PKCS12.
* TODO: Support for PKCS11 as well. * TODO: Support for PKCS11 as well.
* *
* @param keyStoreBuilder * @param keyStoreBuilder
* @throws IOException * @throws IOException
* @throws CertificateException * @throws CertificateException
* @throws UnrecoverableKeyException * @throws UnrecoverableKeyException
*/ */
@Override @Override
public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder) public void loadSigningCertificate(KeyStore.Builder keyStoreBuilder)
throws IOException, CertificateException, UnrecoverableKeyException { throws IOException, CertificateException, UnrecoverableKeyException {
try { try {
KeyStore keyStore = keyStoreBuilder.getKeyStore(); KeyStore keyStore = keyStoreBuilder.getKeyStore();
// Iterate through all aliases until we find the first privatekey // Iterate through all aliases until we find the first privatekey
Enumeration<String> aliases = keyStore.aliases(); Enumeration<String> aliases = keyStore.aliases();
while (aliases.hasMoreElements()) { while (aliases.hasMoreElements()) {
String alias = aliases.nextElement(); String alias = aliases.nextElement();
logger.trace("Testing keystore entry {}", alias); logger.trace("Testing keystore entry {}", alias);
try { try {
Certificate cert = keyStore.getCertificate(alias); Certificate cert = keyStore.getCertificate(alias);
logger.trace("keystore entry {}, has cert type {}", alias, cert.getClass()); logger.trace("keystore entry {}, has cert type {}", alias, cert.getClass());
Key key; Key key;
try { try {
key = keyStore.getKey(alias, null); key = keyStore.getKey(alias, null);
} catch (UnrecoverableKeyException e) { } catch (UnrecoverableKeyException e) {
// This might be a keystore that doesn't support callback handlers // This might be a keystore that doesn't support callback handlers
// (e.g., Java 8 PKCS12) // (e.g., Java 8 PKCS12)
// Manually extract password using callback handler // Manually extract password using callback handler
char[] password = null; char[] password = null;
KeyStore.ProtectionParameter prot = keyStoreBuilder.getProtectionParameter(alias); KeyStore.ProtectionParameter prot = keyStoreBuilder.getProtectionParameter(alias);
if (prot instanceof KeyStore.PasswordProtection) { if (prot instanceof KeyStore.PasswordProtection) {
password = ((KeyStore.PasswordProtection) prot).getPassword(); password = ((KeyStore.PasswordProtection) prot).getPassword();
} else if (prot instanceof KeyStore.CallbackHandlerProtection) { } else if (prot instanceof KeyStore.CallbackHandlerProtection) {
PasswordCallback callback = new PasswordCallback("Password for " + alias + "?", false); PasswordCallback callback = new PasswordCallback("Password for " + alias + "?", false);
Callback[] callbacks = { callback }; Callback[] callbacks = { callback };
try { try {
((KeyStore.CallbackHandlerProtection) prot).getCallbackHandler().handle(callbacks); ((KeyStore.CallbackHandlerProtection) prot).getCallbackHandler().handle(callbacks);
password = callback.getPassword(); password = callback.getPassword();
} catch (UnsupportedCallbackException e1) { } catch (UnsupportedCallbackException e1) {
logger.error("PasswordCallback fallback not supported!", e1); logger.error("PasswordCallback fallback not supported!", e1);
throw new UnrecoverableKeyException("Couldn't use password callback to get key"); throw new UnrecoverableKeyException("Couldn't use password callback to get key");
} }
} else { } else {
logger.error("Unrecognized protection handler for keystore: {}", prot.getClass()); logger.error("Unrecognized protection handler for keystore: {}", prot.getClass());
throw new UnrecoverableKeyException("Unrecognized protection handler for keystore"); throw new UnrecoverableKeyException("Unrecognized protection handler for keystore");
} }
key = keyStore.getKey(alias, password); key = keyStore.getKey(alias, password);
} }
logger.trace("keystore entry {}, has key type {}", alias, key.getClass()); logger.trace("keystore entry {}, has key type {}", alias, key.getClass());
if (key instanceof PrivateKey) { if (key instanceof PrivateKey) {
loadedSigningKey = (PrivateKey) key; loadedSigningKey = (PrivateKey) key;
loadedSigningKeyId = computeCertificateFingerprint(cert); loadedSigningKeyId = computeCertificateFingerprint(cert);
signer.initSign(loadedSigningKey); signer.initSign(loadedSigningKey);
logger.debug("Loaded signing key with ID {}", Hex.encode(loadedSigningKeyId)); logger.debug("Loaded signing key with ID {}", Hex.encode(loadedSigningKeyId));
return; return;
} else { } else {
logger.info("Certificate {} in keystore does not have a private key", cert.toString()); logger.info("Certificate {} in keystore does not have a private key", cert.toString());
} }
} catch(InvalidKeyException e) { } catch(InvalidKeyException e) {
logger.info("Read invalid key", e); logger.info("Read invalid key", e);
} catch(UnrecoverableEntryException e) { } catch(UnrecoverableEntryException e) {
logger.info("Read unrecoverable entry", e); logger.info("Read unrecoverable entry", e);
} }
} }
} catch (KeyStoreException e) { } catch (KeyStoreException e) {
logger.error("Keystore exception", e); logger.error("Keystore exception", e);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException exception", e); logger.error("NoSuchAlgorithmException exception", e);
throw new CertificateException(e); throw new CertificateException(e);
} }
logger.error("Didn't find valid private key entry in keystore"); logger.error("Didn't find valid private key entry in keystore");
throw new UnrecoverableKeyException("Didn't find valid private key entry in keystore!"); throw new UnrecoverableKeyException("Didn't find valid private key entry in keystore!");
} }
@Override @Override
public ByteString getSignerID() { public ByteString getSignerID() {
return loadedSigningKeyId; return loadedSigningKeyId;
} }
public void clearSigningKey() { public void clearSigningKey() {
try { try {
// TODO: Check if this really clears the key from memory // TODO: Check if this really clears the key from memory
if (loadedSigningKeyId != null) if (loadedSigningKeyId != null)
signer.initSign(null); signer.initSign(null);
loadedSigningKeyId = null; loadedSigningKeyId = null;
loadedSigningKey = null; loadedSigningKey = null;
// Start garbage collection? // Start garbage collection?
} catch (InvalidKeyException e) { } catch (InvalidKeyException e) {
// Do nothing // Do nothing
} }
} }
} }

View File

@ -1,135 +1,135 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.Encryption; import meerkat.destributed_key_generation.Encryption;
import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import org.bouncycastle.crypto.params.AsymmetricKeyParameter; import org.bouncycastle.crypto.params.AsymmetricKeyParameter;
import org.bouncycastle.crypto.params.ECDomainParameters; import org.bouncycastle.crypto.params.ECDomainParameters;
import org.bouncycastle.crypto.params.ECKeyParameters; import org.bouncycastle.crypto.params.ECKeyParameters;
import org.bouncycastle.crypto.params.ECPublicKeyParameters; import org.bouncycastle.crypto.params.ECPublicKeyParameters;
import org.bouncycastle.crypto.util.PublicKeyFactory; import org.bouncycastle.crypto.util.PublicKeyFactory;
import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.math.ec.ECCurve; import org.bouncycastle.math.ec.ECCurve;
import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.ECPoint;
import org.bouncycastle.util.BigIntegers; import org.bouncycastle.util.BigIntegers;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECElGamal;
import org.factcenter.qilin.primitives.concrete.ECGroup; import org.factcenter.qilin.primitives.concrete.ECGroup;
import org.factcenter.qilin.util.PRGRandom; import org.factcenter.qilin.util.PRGRandom;
import org.factcenter.qilin.util.Pair; import org.factcenter.qilin.util.Pair;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.IOException; import java.io.IOException;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.spec.*; import java.security.spec.*;
import java.util.Random; import java.util.Random;
/** /**
* Created by talm on 17/11/15. * Created by talm on 17/11/15.
*/ */
public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption { public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
public final static String KEY_ALGORITHM = "ECDH"; public final static String KEY_ALGORITHM = "ECDH";
/** /**
* The Qilin format El-Gamal public key * The Qilin format El-Gamal public key
*/ */
ECElGamal.PK elGamalPK; ECElGamal.PK elGamalPK;
ECCurve curve; ECCurve curve;
ECGroup group; ECGroup group;
public ECGroup getGroup() { return group; } public ECGroup getGroup() { return group; }
public ECElGamal.PK getElGamalPK() { public ECElGamal.PK getElGamalPK() {
return elGamalPK; return elGamalPK;
} }
public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException { public void init(ConcreteCrypto.ElGamalPublicKey serializedPk) throws InvalidKeySpecException {
AsymmetricKeyParameter keyParam; AsymmetricKeyParameter keyParam;
try { try {
keyParam = PublicKeyFactory.createKey(serializedPk.getSubjectPublicKeyInfo().toByteArray()); keyParam = PublicKeyFactory.createKey(serializedPk.getSubjectPublicKeyInfo().toByteArray());
} catch (IOException e) { } catch (IOException e) {
// Shouldn't every happen // Shouldn't every happen
logger.error("Invalid Public Key Encoding", e); logger.error("Invalid Public Key Encoding", e);
throw new InvalidKeySpecException("Invalid Public Key Encoding", e); throw new InvalidKeySpecException("Invalid Public Key Encoding", e);
} }
if (!(keyParam instanceof ECPublicKeyParameters)) { if (!(keyParam instanceof ECPublicKeyParameters)) {
logger.error("Public key is a {}, not a valid public EC Key!", keyParam.getClass()); logger.error("Public key is a {}, not a valid public EC Key!", keyParam.getClass());
throw new InvalidKeySpecException("Not a valid EC public key!"); throw new InvalidKeySpecException("Not a valid EC public key!");
} }
ECDomainParameters params = ((ECKeyParameters) keyParam).getParameters(); ECDomainParameters params = ((ECKeyParameters) keyParam).getParameters();
ECParameterSpec ecParams = new ECParameterSpec(params.getCurve(), params.getG(), params.getN(), params.getH(), ECParameterSpec ecParams = new ECParameterSpec(params.getCurve(), params.getG(), params.getN(), params.getH(),
params.getSeed()); params.getSeed());
curve = params.getCurve(); curve = params.getCurve();
group = new ECGroup(ecParams); group = new ECGroup(ecParams);
elGamalPK = new ECElGamal.PK(group, ((ECPublicKeyParameters) keyParam).getQ()); elGamalPK = new ECElGamal.PK(group, ((ECPublicKeyParameters) keyParam).getQ());
} }
@Override @Override
public Crypto.RerandomizableEncryptedMessage encrypt(Message plaintext, Crypto.EncryptionRandomness rnd) { public Crypto.RerandomizableEncryptedMessage encrypt(Message plaintext, Crypto.EncryptionRandomness rnd) {
// We write the message using writeDelimited to so the length gets prepended. // We write the message using writeDelimited to so the length gets prepended.
ByteArrayOutputStream out = new ByteArrayOutputStream(); ByteArrayOutputStream out = new ByteArrayOutputStream();
try { try {
plaintext.writeDelimitedTo(out); plaintext.writeDelimitedTo(out);
} catch (IOException e) { } catch (IOException e) {
logger.error("Should never happen!", e); logger.error("Should never happen!", e);
throw new RuntimeException("Error in ByteArrayOutputStream!", e); throw new RuntimeException("Error in ByteArrayOutputStream!", e);
} }
byte[] msg = out.toByteArray(); byte[] msg = out.toByteArray();
ECPoint encodedMsg = group.injectiveEncode(msg, new PRGRandom(msg)); ECPoint encodedMsg = group.injectiveEncode(msg, new PRGRandom(msg));
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
Pair<ECPoint,ECPoint> cipherText = elGamalPK.encrypt(encodedMsg, rndInt); Pair<ECPoint,ECPoint> cipherText = elGamalPK.encrypt(encodedMsg, rndInt);
ConcreteCrypto.ElGamalCiphertext encodedCipherText = ConcreteCrypto.ElGamalCiphertext.newBuilder() ConcreteCrypto.ElGamalCiphertext encodedCipherText = ConcreteCrypto.ElGamalCiphertext.newBuilder()
.setC1(ByteString.copyFrom(cipherText.a.getEncoded(true))) .setC1(ByteString.copyFrom(cipherText.a.getEncoded(true)))
.setC2(ByteString.copyFrom(cipherText.b.getEncoded(true))) .setC2(ByteString.copyFrom(cipherText.b.getEncoded(true)))
.build(); .build();
return Crypto.RerandomizableEncryptedMessage.newBuilder() return Crypto.RerandomizableEncryptedMessage.newBuilder()
.setData(encodedCipherText.toByteString()) .setData(encodedCipherText.toByteString())
.build(); .build();
} }
@Override @Override
public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException { public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException {
BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray());
Pair<ECPoint,ECPoint> randomizer = elGamalPK.encrypt(curve.getInfinity(), rndInt); Pair<ECPoint,ECPoint> randomizer = elGamalPK.encrypt(curve.getInfinity(), rndInt);
ConcreteCrypto.ElGamalCiphertext originalEncodedCipher= ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData()); ConcreteCrypto.ElGamalCiphertext originalEncodedCipher= ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData());
Pair<ECPoint,ECPoint> originalCipher = new Pair<ECPoint, ECPoint>( Pair<ECPoint,ECPoint> originalCipher = new Pair<ECPoint, ECPoint>(
curve.decodePoint(originalEncodedCipher.getC1().toByteArray()), curve.decodePoint(originalEncodedCipher.getC1().toByteArray()),
curve.decodePoint(originalEncodedCipher.getC2().toByteArray())); curve.decodePoint(originalEncodedCipher.getC2().toByteArray()));
Pair<ECPoint,ECPoint> newCipher = elGamalPK.add(originalCipher, randomizer); Pair<ECPoint,ECPoint> newCipher = elGamalPK.add(originalCipher, randomizer);
return Crypto.RerandomizableEncryptedMessage.newBuilder() return Crypto.RerandomizableEncryptedMessage.newBuilder()
.setData( .setData(
ConcreteCrypto.ElGamalCiphertext.newBuilder() ConcreteCrypto.ElGamalCiphertext.newBuilder()
.setC1(ByteString.copyFrom(newCipher.a.getEncoded(true))) .setC1(ByteString.copyFrom(newCipher.a.getEncoded(true)))
.setC2(ByteString.copyFrom(newCipher.b.getEncoded(true))) .setC2(ByteString.copyFrom(newCipher.b.getEncoded(true)))
.build().toByteString() .build().toByteString()
).build(); ).build();
} }
@Override @Override
public Crypto.EncryptionRandomness generateRandomness(Random rand) { public Crypto.EncryptionRandomness generateRandomness(Random rand) {
BigInteger randomInt = new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand); BigInteger randomInt = new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand);
Crypto.EncryptionRandomness retval = Crypto.EncryptionRandomness.newBuilder() Crypto.EncryptionRandomness retval = Crypto.EncryptionRandomness.newBuilder()
.setData(ByteString.copyFrom(BigIntegers.asUnsignedByteArray(randomInt))).build(); .setData(ByteString.copyFrom(BigIntegers.asUnsignedByteArray(randomInt))).build();
return retval; return retval;
} }
} }

View File

@ -1,43 +1,43 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import org.bouncycastle.jce.provider.BouncyCastleProvider; import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.security.Provider; import java.security.Provider;
import java.security.Security; import java.security.Security;
/** /**
* A class that performs required crypto setup * A class that performs required destributed_key_generation setup
*/ */
public class GlobalCryptoSetup { public class GlobalCryptoSetup {
final static Logger logger = LoggerFactory.getLogger(GlobalCryptoSetup.class); final static Logger logger = LoggerFactory.getLogger(GlobalCryptoSetup.class);
static boolean loadedBouncyCastle = false; static boolean loadedBouncyCastle = false;
static Provider bouncyCastleProvider; static Provider bouncyCastleProvider;
public static boolean hasSecp256k1Curve() { public static boolean hasSecp256k1Curve() {
// For now we just check if the java version is at least 8 // For now we just check if the java version is at least 8
String[] version = System.getProperty("java.version").split("\\."); String[] version = System.getProperty("java.version").split("\\.");
int major = Integer.parseInt(version[0]); int major = Integer.parseInt(version[0]);
int minor = Integer.parseInt(version[1]); int minor = Integer.parseInt(version[1]);
return ((major > 1) || ((major > 0) && (minor > 7))); return ((major > 1) || ((major > 0) && (minor > 7)));
} }
public static Provider getBouncyCastleProvider() { doSetup(); return bouncyCastleProvider; } public static Provider getBouncyCastleProvider() { doSetup(); return bouncyCastleProvider; }
public static synchronized void doSetup() { public static synchronized void doSetup() {
if (bouncyCastleProvider == null) { if (bouncyCastleProvider == null) {
bouncyCastleProvider = new BouncyCastleProvider(); bouncyCastleProvider = new BouncyCastleProvider();
// Make bouncycastle our default provider if we're running on a JVM version < 8 // Make bouncycastle our default provider if we're running on a JVM version < 8
// (earlier version don't support the EC curve we use for signatures) // (earlier version don't support the EC curve we use for signatures)
if (!hasSecp256k1Curve() && !loadedBouncyCastle) { if (!hasSecp256k1Curve() && !loadedBouncyCastle) {
loadedBouncyCastle = true; loadedBouncyCastle = true;
Security.insertProviderAt(bouncyCastleProvider, 1); Security.insertProviderAt(bouncyCastleProvider, 1);
logger.info("Using BouncyCastle instead of native provider to support secp256k1 named curve"); logger.info("Using BouncyCastle instead of native provider to support secp256k1 named curve");
} }
} }
} }
public GlobalCryptoSetup() { doSetup(); } public GlobalCryptoSetup() { doSetup(); }
} }

View File

@ -1,96 +1,96 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.Digest; import meerkat.destributed_key_generation.Digest;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.security.MessageDigest; import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
/** /**
* Created by talm on 11/9/15. * Created by talm on 11/9/15.
*/ */
public class SHA256Digest extends GlobalCryptoSetup implements Digest { public class SHA256Digest extends GlobalCryptoSetup implements Digest {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
public static final String SHA256 = "SHA-256"; public static final String SHA256 = "SHA-256";
MessageDigest hash; MessageDigest hash;
/** /**
* Used to convert length to bytes in proper order. * Used to convert length to bytes in proper order.
*/ */
ByteBuffer lenBuf = ByteBuffer.allocate(4); ByteBuffer lenBuf = ByteBuffer.allocate(4);
/** /**
* Instantiate with a specified algorithm. * Instantiate with a specified algorithm.
* @param algorithm * @param algorithm
* @throws NoSuchAlgorithmException * @throws NoSuchAlgorithmException
*/ */
public SHA256Digest(String algorithm) throws NoSuchAlgorithmException { public SHA256Digest(String algorithm) throws NoSuchAlgorithmException {
hash = MessageDigest.getInstance(algorithm); hash = MessageDigest.getInstance(algorithm);
} }
/** /**
* Instantiate with the default (SHA-256) algorithm * Instantiate with the default (SHA-256) algorithm
*/ */
public SHA256Digest() { this(true); } public SHA256Digest() { this(true); }
/**SHA /**SHA
* Instantiate with the default (SHA-256) algorithm, * Instantiate with the default (SHA-256) algorithm,
* or create an empty class (for cloning) * or create an empty class (for cloning)
*/ */
private SHA256Digest(boolean initHash) { private SHA256Digest(boolean initHash) {
if (initHash) { if (initHash) {
try { try {
hash = MessageDigest.getInstance(SHA256); hash = MessageDigest.getInstance(SHA256);
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
// Should never happen! // Should never happen!
logger.error("Couldn't find default {} algorhtm: {}", SHA256, e); logger.error("Couldn't find default {} algorhtm: {}", SHA256, e);
assert false; assert false;
} }
} }
} }
@Override @Override
public byte[] digest() { public byte[] digest() {
return hash.digest(); return hash.digest();
} }
@Override @Override
public void update(Message msg) { public void update(Message msg) {
lenBuf.clear(); lenBuf.clear();
lenBuf.putInt(msg.getSerializedSize()); lenBuf.putInt(msg.getSerializedSize());
lenBuf.flip(); lenBuf.flip();
hash.update(lenBuf); hash.update(lenBuf);
hash.update(msg.toByteString().asReadOnlyByteBuffer()); hash.update(msg.toByteString().asReadOnlyByteBuffer());
} }
final public void update(ByteString msg) { final public void update(ByteString msg) {
hash.update(msg.asReadOnlyByteBuffer()); hash.update(msg.asReadOnlyByteBuffer());
} }
final public void update(byte[] msg) { final public void update(byte[] msg) {
hash.update(msg); hash.update(msg);
} }
final public void update(ByteBuffer msg) { final public void update(ByteBuffer msg) {
hash.update(msg); hash.update(msg);
} }
@Override @Override
public void reset() { public void reset() {
hash.reset(); hash.reset();
} }
@Override @Override
public SHA256Digest clone() throws CloneNotSupportedException { public SHA256Digest clone() throws CloneNotSupportedException {
SHA256Digest copy = new SHA256Digest(false); SHA256Digest copy = new SHA256Digest(false);
copy.hash = (MessageDigest) hash.clone(); copy.hash = (MessageDigest) hash.clone();
return copy; return copy;
} }
} }

View File

@ -1,18 +1,18 @@
package meerkat.crypto.mixnet; package meerkat.destributed_key_generation.mixnet;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
/** /**
* Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts. * Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts.
*/ */
public interface Mix2ZeroKnowledgeProver { public interface Mix2ZeroKnowledgeProver {
public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
boolean switched, boolean switched,
Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2); Crypto.EncryptionRandomness r2);
} }

View File

@ -1,23 +1,23 @@
package meerkat.crypto.mixnet; package meerkat.destributed_key_generation.mixnet;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
/** /**
* Verify the two-ciphertext mix proof * Verify the two-ciphertext mix proof
*/ */
public interface Mix2ZeroKnowledgeVerifier { public interface Mix2ZeroKnowledgeVerifier {
/** /**
* Return true iff the proof is valid. * Return true iff the proof is valid.
* @param in1 * @param in1
* @param in2 * @param in2
* @param out1 * @param out1
* @param out2 * @param out2
* @return * @return
*/ */
boolean verify(Crypto.RerandomizableEncryptedMessage in1, boolean verify(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
Mixing.ZeroKnowledgeProof proof); Mixing.ZeroKnowledgeProof proof);
} }

View File

@ -1,11 +1,11 @@
package meerkat.crypto.mixnet; package meerkat.destributed_key_generation.mixnet;
import java.util.List; import java.util.List;
import static meerkat.protobuf.Voting.*; import static meerkat.protobuf.Voting.*;
/** /**
* Created by talm on 25/10/15. * Created by talm on 25/10/15.
*/ */
public interface Mixer { public interface Mixer {
public List<EncryptedBallot> mix(List<EncryptedBallot> ballots); public List<EncryptedBallot> mix(List<EncryptedBallot> ballots);
} }

View File

@ -1,7 +1,7 @@
package meerkat.crypto.mixnet; package meerkat.destributed_key_generation.mixnet;
/** /**
* Created by talm on 25/10/15. * Created by talm on 25/10/15.
*/ */
public class Trustee { public class Trustee {
} }

View File

@ -1,7 +1,7 @@
package meerkat.crypto.mixnet; package meerkat.destributed_key_generation.mixnet;
/** /**
* Created by talm on 25/10/15. * Created by talm on 25/10/15.
*/ */
public class Verifier { public class Verifier {
} }

View File

@ -1,50 +1,49 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.crypto.concrete.ECDSASignature; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Crypto; import org.junit.Test;
import org.junit.Test;
import java.math.BigInteger;
import java.math.BigInteger; import static org.junit.Assert.*;
import static org.junit.Assert.*;
/**
/** * Created by talm on 12/11/15.
* Created by talm on 12/11/15. */
*/ public class ECDSADeterministicSignatureTest extends ECDSASignatureTest {
public class ECDSADeterministicSignatureTest extends ECDSASignatureTest {
@Override
@Override protected ECDSASignature getSigner() { return new ECDSADeterministicSignature(); }
protected ECDSASignature getSigner() { return new ECDSADeterministicSignature(); }
/**
/** * Make sure signatures don't vary
* Make sure signatures don't vary */
*/ @Test
@Test public void testDeterministicSigning() throws Exception {
public void testDeterministicSigning() throws Exception { loadSigningKeys();
loadSigningKeys();
for (int i = 0; i < REPEAT_COUNT; ++i) {
for (int i = 0; i < REPEAT_COUNT; ++i) { BigInteger rawMsg = new BigInteger(50, rand);
BigInteger rawMsg = new BigInteger(50, rand); Message msg = Crypto.BigInteger.newBuilder()
Message msg = Crypto.BigInteger.newBuilder() .setData(ByteString.copyFrom(rawMsg.toByteArray())).build();
.setData(ByteString.copyFrom(rawMsg.toByteArray())).build(); Crypto.Signature[] sigs = new Crypto.Signature[REPEAT_COUNT];
Crypto.Signature[] sigs = new Crypto.Signature[REPEAT_COUNT];
signer.updateContent(msg);
signer.updateContent(msg); sigs[0] = signer.sign();
sigs[0] = signer.sign(); byte[] canonicalSig = sigs[0].toByteArray();
byte[] canonicalSig = sigs[0].toByteArray();
for (int j = 1; j < sigs.length; ++j) {
for (int j = 1; j < sigs.length; ++j) { signer.updateContent(msg);
signer.updateContent(msg); sigs[j] = signer.sign();
sigs[j] = signer.sign();
byte[] newSig = sigs[j].toByteArray();
byte[] newSig = sigs[j].toByteArray();
assertArrayEquals("Signatures on same message differ (i="+i+",j="+j+")", canonicalSig, newSig);
assertArrayEquals("Signatures on same message differ (i="+i+",j="+j+")", canonicalSig, newSig); }
} }
} }
} }
}

View File

@ -1,220 +1,219 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.crypto.concrete.ECDSASignature; import org.junit.Before;
import org.junit.Before; import org.junit.Test;
import org.junit.Test;
import java.io.InputStream;
import java.io.InputStream; import java.math.BigInteger;
import java.math.BigInteger; import java.security.KeyStore;
import java.security.KeyStore; import java.util.Random;
import java.util.Random;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertTrue;
/**
/** * Created by talm on 12/11/15.
* Created by talm on 12/11/15. */
*/ public class ECDSASignatureTest {
public class ECDSASignatureTest { public static String KEYFILE_EXAMPLE = "/certs/enduser-certs/user1-key-with-password-secret.p12";
public static String KEYFILE_EXAMPLE = "/certs/enduser-certs/user1-key-with-password-secret.p12"; public static String KEYFILE_PASSWORD = "secret";
public static String KEYFILE_PASSWORD = "secret";
public static String CERT1_PEM_EXAMPLE = "/certs/enduser-certs/user1.crt";
public static String CERT1_PEM_EXAMPLE = "/certs/enduser-certs/user1.crt"; public static String CERT2_DER_EXAMPLE = "/certs/enduser-certs/user2.der";
public static String CERT2_DER_EXAMPLE = "/certs/enduser-certs/user2.der";
public static String MSG_PLAINTEXT_EXAMPLE = "/certs/signed-messages/helloworld.txt";
public static String MSG_PLAINTEXT_EXAMPLE = "/certs/signed-messages/helloworld.txt"; public static String MSG_SIG_EXAMPLE = "/certs/signed-messages/helloworld.txt.sha256sig";
public static String MSG_SIG_EXAMPLE = "/certs/signed-messages/helloworld.txt.sha256sig";
public static String HELLO_WORLD = "hello world!";
public static String HELLO_WORLD = "hello world!";
public final static int REPEAT_COUNT = 10;
public final static int REPEAT_COUNT = 10;
Random rand = new Random(0);
Random rand = new Random(0);
protected ECDSASignature signer;
protected ECDSASignature signer;
protected ECDSASignature getSigner() { return new ECDSASignature(); }
protected ECDSASignature getSigner() { return new ECDSASignature(); }
@Before
@Before public void setup() throws Exception {
public void setup() throws Exception { signer = getSigner();
signer = getSigner(); }
}
@Test
@Test public void loadSignatureKey() throws Exception {
public void loadSignatureKey() throws Exception { InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE);
InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE); char[] password = KEYFILE_PASSWORD.toCharArray();
char[] password = KEYFILE_PASSWORD.toCharArray();
KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password);
KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password); signer.loadSigningCertificate(keyStore);
signer.loadSigningCertificate(keyStore); keyStream.close();
keyStream.close(); }
}
@Test
@Test public void loadPEMVerificationKey() throws Exception {
public void loadPEMVerificationKey() throws Exception { InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
signer.loadVerificationCertificates(certStream);
signer.loadVerificationCertificates(certStream); certStream.close();
certStream.close(); }
}
@Test
@Test public void loadDERVerificationKey() throws Exception {
public void loadDERVerificationKey() throws Exception { InputStream certStream = getClass().getResourceAsStream(CERT2_DER_EXAMPLE);
InputStream certStream = getClass().getResourceAsStream(CERT2_DER_EXAMPLE);
signer.loadVerificationCertificates(certStream);
signer.loadVerificationCertificates(certStream); certStream.close();
certStream.close(); }
}
@Test
@Test public void verifyValidSig() throws Exception {
public void verifyValidSig() throws Exception { InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE);
InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
signer.loadVerificationCertificates(certStream);
signer.loadVerificationCertificates(certStream); certStream.close();
certStream.close();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); sig.setType(Crypto.SignatureType.ECDSA);
sig.setType(Crypto.SignatureType.ECDSA); sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey());
sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); sig.setData(ByteString.readFrom(sigStream));
sig.setData(ByteString.readFrom(sigStream));
Crypto.Signature builtSig = sig.build();
Crypto.Signature builtSig = sig.build(); signer.initVerify(builtSig);
signer.initVerify(builtSig); signer.updateContent(msgStream);
signer.updateContent(msgStream); assertTrue("Signature did not verify!", signer.verify());
assertTrue("Signature did not verify!", signer.verify()); }
}
@Test
@Test public void verifyInvalidSig() throws Exception {
public void verifyInvalidSig() throws Exception { InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE);
InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
signer.loadVerificationCertificates(certStream);
signer.loadVerificationCertificates(certStream); certStream.close();
certStream.close();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); sig.setType(Crypto.SignatureType.ECDSA);
sig.setType(Crypto.SignatureType.ECDSA); sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey());
sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); byte[] sigData = ByteString.readFrom(sigStream).toByteArray();
byte[] sigData = ByteString.readFrom(sigStream).toByteArray(); ++sigData[0];
++sigData[0];
sig.setData(ByteString.copyFrom(sigData));
sig.setData(ByteString.copyFrom(sigData));
Crypto.Signature builtSig = sig.build();
Crypto.Signature builtSig = sig.build(); signer.initVerify(builtSig);
signer.initVerify(builtSig); signer.updateContent(msgStream);
signer.updateContent(msgStream); assertFalse("Bad Signature passed verification!", signer.verify());
assertFalse("Bad Signature passed verification!", signer.verify()); }
}
@Test
@Test public void verifyInvalidMsg() throws Exception {
public void verifyInvalidMsg() throws Exception { InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE);
InputStream certStream = getClass().getResourceAsStream(CERT1_PEM_EXAMPLE); InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE);
InputStream msgStream = getClass().getResourceAsStream(MSG_PLAINTEXT_EXAMPLE); InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
InputStream sigStream = getClass().getResourceAsStream(MSG_SIG_EXAMPLE);
signer.loadVerificationCertificates(certStream);
signer.loadVerificationCertificates(certStream); certStream.close();
certStream.close();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder();
Crypto.Signature.Builder sig = Crypto.Signature.newBuilder(); sig.setType(Crypto.SignatureType.ECDSA);
sig.setType(Crypto.SignatureType.ECDSA); sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey());
sig.setSignerId(signer.loadedCertificates.entrySet().iterator().next().getKey()); sig.setData(ByteString.readFrom(sigStream));
sig.setData(ByteString.readFrom(sigStream)); byte[] msgData = ByteString.readFrom(msgStream).toByteArray();
byte[] msgData = ByteString.readFrom(msgStream).toByteArray(); ++msgData[0];
++msgData[0];
Crypto.Signature builtSig = sig.build();
Crypto.Signature builtSig = sig.build(); signer.initVerify(builtSig);
signer.initVerify(builtSig); signer.updateContent(msgStream);
signer.updateContent(msgStream); assertFalse("Signature doesn't match message but passed verification!", signer.verify());
assertFalse("Signature doesn't match message but passed verification!", signer.verify()); }
}
protected void loadSigningKeys() throws Exception {
protected void loadSigningKeys() throws Exception { InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE);
InputStream keyStream = getClass().getResourceAsStream(KEYFILE_EXAMPLE); char[] password = KEYFILE_PASSWORD.toCharArray();
char[] password = KEYFILE_PASSWORD.toCharArray();
KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password);
KeyStore.Builder keyStore = signer.getPKCS12KeyStoreBuilder(keyStream, password); signer.loadSigningCertificate(keyStore);
signer.loadSigningCertificate(keyStore); }
}
@Test
@Test public void signAndVerify() throws Exception {
public void signAndVerify() throws Exception { loadSigningKeys();
loadSigningKeys();
BigInteger rawMsg = new BigInteger(50, rand);
BigInteger rawMsg = new BigInteger(50, rand); Crypto.BigInteger usMsg = Crypto.BigInteger.newBuilder()
Crypto.BigInteger usMsg = Crypto.BigInteger.newBuilder() .setData(ByteString.copyFrom(rawMsg.toByteArray())).build();
.setData(ByteString.copyFrom(rawMsg.toByteArray())).build();
signer.updateContent(usMsg);
signer.updateContent(usMsg); Crypto.Signature sig = signer.sign();
Crypto.Signature sig = signer.sign();
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
signer.initVerify(sig);
signer.initVerify(sig); signer.updateContent(usMsg);
signer.updateContent(usMsg); assertTrue("Couldn't verify signature on ", signer.verify());
assertTrue("Couldn't verify signature on ", signer.verify()); }
}
@Test
@Test public void signMultipleAndVerify() throws Exception {
public void signMultipleAndVerify() throws Exception { loadSigningKeys();
loadSigningKeys();
Message[] msgs = new Message[REPEAT_COUNT];
Message[] msgs = new Message[REPEAT_COUNT]; for (int i = 0; i < msgs.length; ++i) {
for (int i = 0; i < msgs.length; ++i) {
BigInteger rawMsg = new BigInteger(50, rand);
BigInteger rawMsg = new BigInteger(50, rand); msgs[i] = Crypto.BigInteger.newBuilder()
msgs[i] = Crypto.BigInteger.newBuilder() .setData(ByteString.copyFrom(rawMsg.toByteArray())).build();
.setData(ByteString.copyFrom(rawMsg.toByteArray())).build(); signer.updateContent(msgs[i]);
signer.updateContent(msgs[i]); }
}
Crypto.Signature sig = signer.sign();
Crypto.Signature sig = signer.sign();
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
signer.initVerify(sig);
signer.initVerify(sig); for (int i = 0; i < msgs.length; ++i) {
for (int i = 0; i < msgs.length; ++i) { signer.updateContent(msgs[i]);
signer.updateContent(msgs[i]); }
} assertTrue("Couldn't verify signature on ", signer.verify());
assertTrue("Couldn't verify signature on ", signer.verify()); }
}
@Test
@Test public void multipleSignAndVerify() throws Exception {
public void multipleSignAndVerify() throws Exception { loadSigningKeys();
loadSigningKeys();
Message[] msgs = new Message[REPEAT_COUNT];
Message[] msgs = new Message[REPEAT_COUNT]; Crypto.Signature[] sigs = new Crypto.Signature[REPEAT_COUNT];
Crypto.Signature[] sigs = new Crypto.Signature[REPEAT_COUNT]; for (int i = 0; i < msgs.length; ++i) {
for (int i = 0; i < msgs.length; ++i) { BigInteger rawMsg = new BigInteger(50, rand);
BigInteger rawMsg = new BigInteger(50, rand); msgs[i] = Crypto.BigInteger.newBuilder()
msgs[i] = Crypto.BigInteger.newBuilder() .setData(ByteString.copyFrom(rawMsg.toByteArray())).build();
.setData(ByteString.copyFrom(rawMsg.toByteArray())).build(); signer.updateContent(msgs[i]);
signer.updateContent(msgs[i]); sigs[i] = signer.sign();
sigs[i] = signer.sign(); }
}
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
signer.loadVerificationCertificates(getClass().getResourceAsStream(CERT1_PEM_EXAMPLE));
for (int i = 0; i < msgs.length; ++i) {
for (int i = 0; i < msgs.length; ++i) { signer.initVerify(sigs[i]);
signer.initVerify(sigs[i]); signer.updateContent(msgs[i]);
signer.updateContent(msgs[i]); assertTrue("Couldn't verify signature on ", signer.verify());
assertTrue("Couldn't verify signature on ", signer.verify()); }
}
}
}
}
}

View File

@ -1,122 +1,122 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Voting; import meerkat.protobuf.Voting;
import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.ECPoint;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECElGamal;
import org.factcenter.qilin.primitives.concrete.ECGroup; import org.factcenter.qilin.primitives.concrete.ECGroup;
import org.factcenter.qilin.util.Pair; import org.factcenter.qilin.util.Pair;
import java.math.BigInteger; import java.math.BigInteger;
import java.util.Random; import java.util.Random;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
* Test class for {@link ECElGamalEncryption} * Test class for {@link ECElGamalEncryption}
*/ */
public class ECElGamalEncryptionTest { public class ECElGamalEncryptionTest {
final Logger logger = LoggerFactory.getLogger(getClass()); final Logger logger = LoggerFactory.getLogger(getClass());
/** /**
* Number of times to repeat probabilistic tests. * Number of times to repeat probabilistic tests.
*/ */
public final static int CONFIDENCE = 10; public final static int CONFIDENCE = 10;
Random rand = new Random(0); // Insecure deterministic random for testing. Random rand = new Random(0); // Insecure deterministic random for testing.
ECElGamal.SK key; ECElGamal.SK key;
ECGroup group; ECGroup group;
ECElGamalEncryption enc; ECElGamalEncryption enc;
ConcreteCrypto.ElGamalPublicKey serializedPk; ConcreteCrypto.ElGamalPublicKey serializedPk;
@Before @Before
public void setup() throws Exception { public void setup() throws Exception {
group = new ECGroup("secp256k1"); group = new ECGroup("secp256k1");
BigInteger sk = ECElGamal.generateSecretKey(group, rand); BigInteger sk = ECElGamal.generateSecretKey(group, rand);
key = new ECElGamal.SK(group, sk); key = new ECElGamal.SK(group, sk);
serializedPk = ECElGamalUtils.serializePk(group, key); serializedPk = ECElGamalUtils.serializePk(group, key);
enc = new ECElGamalEncryption(); enc = new ECElGamalEncryption();
enc.init(serializedPk); enc.init(serializedPk);
} }
Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) { Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) {
Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder(); Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder();
ballot.setSerialNumber(rand.nextInt(1000000)); ballot.setSerialNumber(rand.nextInt(1000000));
for (int i = 0; i < numQuestions; ++i) { for (int i = 0; i < numQuestions; ++i) {
Voting.BallotAnswer.Builder answers = ballot.addAnswersBuilder(); Voting.BallotAnswer.Builder answers = ballot.addAnswersBuilder();
for (int j = 0; j < numAnswers; ++j) { for (int j = 0; j < numAnswers; ++j) {
answers.addAnswer(rand.nextInt(maxAnswer)); answers.addAnswer(rand.nextInt(maxAnswer));
} }
} }
return ballot.build(); return ballot.build();
} }
/** /**
* Testing just the key management * Testing just the key management
* @throws Exception * @throws Exception
*/ */
@Test @Test
public void testPkSerialization() throws Exception { public void testPkSerialization() throws Exception {
ECElGamal.PK pk = enc.getElGamalPK(); ECElGamal.PK pk = enc.getElGamalPK();
ECPoint point = enc.getGroup().sample(rand); ECPoint point = enc.getGroup().sample(rand);
Pair<ECPoint, ECPoint> cipher = pk.encrypt(point, pk.getRandom(rand)); Pair<ECPoint, ECPoint> cipher = pk.encrypt(point, pk.getRandom(rand));
ECPoint decrypted = key.decrypt(cipher); ECPoint decrypted = key.decrypt(cipher);
assertEquals("Decrypted value not equal to encrypted value!", point, decrypted); assertEquals("Decrypted value not equal to encrypted value!", point, decrypted);
} }
@Test @Test
public void testEncryption() throws Exception { public void testEncryption() throws Exception {
for (int i = 0; i < CONFIDENCE; ++i) { for (int i = 0; i < CONFIDENCE; ++i) {
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15. Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
if (msg.getSerializedSize() > enc.getGroup().getInjectiveEncodeMsgLength()) { if (msg.getSerializedSize() > enc.getGroup().getInjectiveEncodeMsgLength()) {
logger.error("Test Message too big (|msg|={} > max={}), expect failure.", logger.error("Test Message too big (|msg|={} > max={}), expect failure.",
msg.getSerializedSize(), enc.getGroup().getInjectiveEncodeMsgLength()); msg.getSerializedSize(), enc.getGroup().getInjectiveEncodeMsgLength());
} }
Crypto.RerandomizableEncryptedMessage cipherText = enc.encrypt(msg, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage cipherText = enc.encrypt(msg, enc.generateRandomness(rand));
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, cipherText); Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, cipherText);
assertEquals("Decrypted value differs from encrypted value (i="+i+")!", msg, decrypted); assertEquals("Decrypted value differs from encrypted value (i="+i+")!", msg, decrypted);
} }
} }
@Test @Test
public void testRerandomizeModifiesCiphertext() throws Exception { public void testRerandomizeModifiesCiphertext() throws Exception {
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15. Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
Crypto.RerandomizableEncryptedMessage cipher1 = enc.encrypt(msg, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage cipher1 = enc.encrypt(msg, enc.generateRandomness(rand));
Crypto.RerandomizableEncryptedMessage cipher2 = enc.rerandomize(cipher1, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage cipher2 = enc.rerandomize(cipher1, enc.generateRandomness(rand));
assertNotEquals("Rerandomized cipher identical to original!", cipher1, cipher2); assertNotEquals("Rerandomized cipher identical to original!", cipher1, cipher2);
} }
@Test @Test
public void testRerandomizePreservesPlaintext() throws Exception { public void testRerandomizePreservesPlaintext() throws Exception {
for (int i = 0; i < CONFIDENCE; ++i) { for (int i = 0; i < CONFIDENCE; ++i) {
Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15. Voting.PlaintextBallot msg = genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15.
Crypto.RerandomizableEncryptedMessage cipher = enc.encrypt(msg, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage cipher = enc.encrypt(msg, enc.generateRandomness(rand));
Crypto.RerandomizableEncryptedMessage cipher2 = cipher; Crypto.RerandomizableEncryptedMessage cipher2 = cipher;
for (int j = 0; j < CONFIDENCE; ++j) for (int j = 0; j < CONFIDENCE; ++j)
cipher2 = enc.rerandomize(cipher2, enc.generateRandomness(rand)); cipher2 = enc.rerandomize(cipher2, enc.generateRandomness(rand));
Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group, Voting.PlaintextBallot decrypted = ECElGamalUtils.decrypt(Voting.PlaintextBallot.class, key, group,
cipher2); cipher2);
assertEquals("Decrypted value differs from original encrypted value (i="+i+")!", msg, decrypted); assertEquals("Decrypted value differs from original encrypted value (i="+i+")!", msg, decrypted);
} }
} }
} }

View File

@ -1,89 +1,89 @@
package meerkat.crypto.concrete; package meerkat.destributed_key_generation.concrete;
import com.google.protobuf.ByteString; import com.google.protobuf.ByteString;
import com.google.protobuf.GeneratedMessage; import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message; import com.google.protobuf.Message;
import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECParameterSpec;
import org.bouncycastle.jce.spec.ECPublicKeySpec; import org.bouncycastle.jce.spec.ECPublicKeySpec;
import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.ECPoint;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECElGamal;
import org.factcenter.qilin.primitives.concrete.ECGroup; import org.factcenter.qilin.primitives.concrete.ECGroup;
import org.factcenter.qilin.primitives.generic.ElGamal; import org.factcenter.qilin.primitives.generic.ElGamal;
import org.factcenter.qilin.util.Pair; import org.factcenter.qilin.util.Pair;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.security.KeyFactory; import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException; import java.security.NoSuchAlgorithmException;
import java.security.PublicKey; import java.security.PublicKey;
import java.security.spec.InvalidKeySpecException; import java.security.spec.InvalidKeySpecException;
/** /**
* utilities for ECElgamal * utilities for ECElgamal
*/ */
public class ECElGamalUtils { public class ECElGamalUtils {
final static Logger logger = LoggerFactory.getLogger(ECElGamalUtils.class); final static Logger logger = LoggerFactory.getLogger(ECElGamalUtils.class);
public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH"; public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH";
/** /**
* Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption} * Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption}
* @param pk * @param pk
* @return * @return
*/ */
public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) { public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) {
ECPoint pkPoint = pk.getPK(); ECPoint pkPoint = pk.getPK();
ECParameterSpec params = group.getCurveParams(); ECParameterSpec params = group.getCurveParams();
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params); ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params);
try { try {
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM, KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
GlobalCryptoSetup.getBouncyCastleProvider()); GlobalCryptoSetup.getBouncyCastleProvider());
PublicKey javaPk = fact.generatePublic(pubKeySpec); PublicKey javaPk = fact.generatePublic(pubKeySpec);
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder() ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build(); .setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
return serializedPk; return serializedPk;
} catch (NoSuchAlgorithmException|InvalidKeySpecException e) { } catch (NoSuchAlgorithmException|InvalidKeySpecException e) {
logger.error("Should never happen!", e); logger.error("Should never happen!", e);
throw new RuntimeException("Error converting public key!", e); throw new RuntimeException("Error converting public key!", e);
} }
} }
/** /**
* Standard (non-threshold) decryption for testing purposes. * Standard (non-threshold) decryption for testing purposes.
* @param secretKey * @param secretKey
* @return * @return
*/ */
public static <T extends Message> T decrypt(Class<T> plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher) public static <T extends Message> T decrypt(Class<T> plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher)
throws InvalidProtocolBufferException { throws InvalidProtocolBufferException {
ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData()); ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData());
ByteString c1encoded = cipherText.getC1(); ByteString c1encoded = cipherText.getC1();
ByteString c2encoded = cipherText.getC2(); ByteString c2encoded = cipherText.getC2();
ECPoint c1 = group.decode(c1encoded.toByteArray()); ECPoint c1 = group.decode(c1encoded.toByteArray());
ECPoint c2 = group.decode(c2encoded.toByteArray()); ECPoint c2 = group.decode(c2encoded.toByteArray());
ECPoint plaintextEncoded = secretKey.decrypt(new Pair<ECPoint, ECPoint>(c1, c2)); ECPoint plaintextEncoded = secretKey.decrypt(new Pair<ECPoint, ECPoint>(c1, c2));
byte[] plaintext = group.injectiveDecode(plaintextEncoded); byte[] plaintext = group.injectiveDecode(plaintextEncoded);
ByteArrayInputStream in = new ByteArrayInputStream(plaintext); ByteArrayInputStream in = new ByteArrayInputStream(plaintext);
try { try {
java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder"); java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder");
GeneratedMessage.Builder<?> builder = (GeneratedMessage.Builder<?>) newBuilder.invoke(plaintextMessageType); GeneratedMessage.Builder<?> builder = (GeneratedMessage.Builder<?>) newBuilder.invoke(plaintextMessageType);
builder.mergeDelimitedFrom(in); builder.mergeDelimitedFrom(in);
return plaintextMessageType.cast(builder.build()); return plaintextMessageType.cast(builder.build());
} catch (Exception e) { } catch (Exception e) {
logger.error("Error parsing incoming message", e); logger.error("Error parsing incoming message", e);
throw new InvalidProtocolBufferException("Plaintext protobuf error"); throw new InvalidProtocolBufferException("Plaintext protobuf error");
} }
} }
} }