comments:
parent
b4e5040814
commit
e677355040
|
@ -4,11 +4,12 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by talm on 25/10/15.
|
* Created by talm on 25/10/15.
|
||||||
*/
|
*/
|
||||||
public interface Mixer {
|
public interface Mixer {
|
||||||
public MixerOutput mix(List<Crypto.RerandomizableEncryptedMessage> ciphertexts)
|
public MixerOutput mix(List<Crypto.RerandomizableEncryptedMessage> ciphertexts,Random random)
|
||||||
throws InvalidProtocolBufferException;
|
throws InvalidProtocolBufferException;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,118 @@
|
||||||
|
package meerkat.mixer.main;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.crypto.mixnet.MixerOutput;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by Tzlil on 12/17/2015.
|
||||||
|
* provide convert operation from batch data to meerkat.mixer.mixing output and backwards
|
||||||
|
*/
|
||||||
|
public class BatchConverter {
|
||||||
|
|
||||||
|
private final int n,layers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param n
|
||||||
|
* @param layers
|
||||||
|
*/
|
||||||
|
public BatchConverter(int n,int layers){
|
||||||
|
this.n = n;
|
||||||
|
this.layers = layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert integer to byte string
|
||||||
|
* @param a
|
||||||
|
* @return a as byte string
|
||||||
|
*/
|
||||||
|
private ByteString Integer2ByteString(int a){
|
||||||
|
return ByteString.copyFrom(BigInteger.valueOf(a).toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert byte string to integer
|
||||||
|
* @param bs
|
||||||
|
* @return bs as int
|
||||||
|
*/
|
||||||
|
private int ByteString2Integer(ByteString bs) {
|
||||||
|
return Integer.valueOf(bs.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert meerkat.mixer.mixing output to batch data
|
||||||
|
* @param mixerOutput
|
||||||
|
* @return meerkat.mixer.mixing output as list of batch data
|
||||||
|
*/
|
||||||
|
public List<BulletinBoardAPI.BatchData> MixerOutput2BatchData(MixerOutput mixerOutput) {
|
||||||
|
|
||||||
|
List<BulletinBoardAPI.BatchData> result = new ArrayList<BulletinBoardAPI.BatchData>();
|
||||||
|
|
||||||
|
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||||
|
.setData(Integer2ByteString(n))
|
||||||
|
.build());
|
||||||
|
|
||||||
|
for (Mixing.ZeroKnowledgeProof[] zkpLayer : mixerOutput.getProofs()) {
|
||||||
|
for (Mixing.ZeroKnowledgeProof zkp : zkpLayer) {
|
||||||
|
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||||
|
.setData(zkp.toByteString())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (Crypto.RerandomizableEncryptedMessage[] encryptionLayer : mixerOutput.getEncryptedMessages()) {
|
||||||
|
for (Crypto.RerandomizableEncryptedMessage encryption : encryptionLayer) {
|
||||||
|
result.add(BulletinBoardAPI.BatchData.newBuilder()
|
||||||
|
.setData(encryption.toByteString())
|
||||||
|
.build());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert batch data list to meerkat.mixer.mixing output
|
||||||
|
* @param batchDataList
|
||||||
|
* @return batch data list as MixerOutput
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public MixerOutput BatchDataList2MixerOutput
|
||||||
|
(List<BulletinBoardAPI.BatchData> batchDataList) throws Exception {
|
||||||
|
|
||||||
|
if (n != ByteString2Integer(batchDataList.remove(0).getData())){
|
||||||
|
throw new Exception();
|
||||||
|
}
|
||||||
|
|
||||||
|
int nDiv2 = n >>1;
|
||||||
|
Mixing.ZeroKnowledgeProof[][] proofs = new Mixing.ZeroKnowledgeProof[layers][nDiv2];
|
||||||
|
for (int layer = 0; layer < layers; layer++)
|
||||||
|
{
|
||||||
|
for (int proofIndex = 0 ; proofIndex < nDiv2 ; proofIndex ++)
|
||||||
|
{
|
||||||
|
proofs[layer][proofIndex] = Mixing.ZeroKnowledgeProof.parseFrom(batchDataList.remove(0).getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Crypto.RerandomizableEncryptedMessage[][] encryptions
|
||||||
|
= new Crypto.RerandomizableEncryptedMessage[layers + 1][n];
|
||||||
|
for (int layer = 0; layer < layers + 1; layer++)
|
||||||
|
{
|
||||||
|
for (int encryptionIndex = 0 ; encryptionIndex < n ; encryptionIndex ++)
|
||||||
|
{
|
||||||
|
encryptions[layer][encryptionIndex] = Crypto.RerandomizableEncryptedMessage
|
||||||
|
.parseFrom(batchDataList.remove(0).getData());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new meerkat.mixer.mixing.MixerOutput(n,layers,proofs,encryptions);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
|
@ -1,7 +1,104 @@
|
||||||
package meerkat.mixer.main;
|
package meerkat.mixer.main;
|
||||||
|
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.crypto.mixnet.MixerOutput;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.mixer.necessary.AsyncBulletinBoardClient;
|
||||||
|
import meerkat.mixer.necessary.CompleteBatch;
|
||||||
|
import meerkat.mixer.verifier.VerifyTable;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/17/2015.
|
||||||
|
* implements AsyncBulletinBoardClient.ClientCallback<CompleteBatch>
|
||||||
*/
|
*/
|
||||||
public class BatchHandler {
|
public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<CompleteBatch> {
|
||||||
|
|
||||||
|
private MixerOutput mixerOutput;
|
||||||
|
private boolean msgReceived;
|
||||||
|
private Throwable t;
|
||||||
|
private CompleteBatch msg;
|
||||||
|
|
||||||
|
private final int n, layers;
|
||||||
|
private final Mix2ZeroKnowledgeVerifier verifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param n
|
||||||
|
* @param layers
|
||||||
|
* @param verifier
|
||||||
|
*/
|
||||||
|
public BatchHandler(int n, int layers, Mix2ZeroKnowledgeVerifier verifier) {
|
||||||
|
this.mixerOutput = null;
|
||||||
|
this.n = n;
|
||||||
|
this.layers = layers;
|
||||||
|
this.msgReceived = false;
|
||||||
|
this.t = null;
|
||||||
|
this.verifier = verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleCallback(CompleteBatch msg) {
|
||||||
|
this.msg = msg;
|
||||||
|
synchronized (this) {
|
||||||
|
this.msgReceived = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void handleFailure(Throwable t) {
|
||||||
|
this.t = t;
|
||||||
|
synchronized (this) {
|
||||||
|
this.msgReceived = true;
|
||||||
|
notifyAll();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return true iff msg was received
|
||||||
|
* @return msgReceived
|
||||||
|
*/
|
||||||
|
public boolean isMsgReceived() {
|
||||||
|
return msgReceived;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert batch data to meerkat.mixer.mixing output
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
private void convertMessage() throws Exception {
|
||||||
|
BatchConverter batchConverter = new BatchConverter(n,layers);
|
||||||
|
this.mixerOutput = batchConverter.BatchDataList2MixerOutput(msg.getBatchDataList());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* call convert message, and if succeed verify the table
|
||||||
|
* @return return true iff the given batch message is valid meerkat.mixer.mixing output
|
||||||
|
* @throws Exception
|
||||||
|
*/
|
||||||
|
public boolean verifyTable() throws Exception {
|
||||||
|
if (mixerOutput == null) {
|
||||||
|
convertMessage();
|
||||||
|
}
|
||||||
|
return VerifyTable.verifyTable(verifier, n, mixerOutput);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* extract input for meerkat.mixer.mixing from previous mixers output
|
||||||
|
* @return last layer of encrypted votes as list
|
||||||
|
* @throws Throwable in case if failure
|
||||||
|
*/
|
||||||
|
public List<Crypto.RerandomizableEncryptedMessage> getInputForMixer() throws Throwable {
|
||||||
|
if (t != null) {
|
||||||
|
throw t;
|
||||||
|
}
|
||||||
|
if(!verifyTable()){
|
||||||
|
throw new Exception("in valid table");
|
||||||
|
}
|
||||||
|
return Arrays.asList(mixerOutput.getEncryptedMessages()[layers]);//there are layers + 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,110 @@
|
||||||
package meerkat.mixer.main;
|
package meerkat.mixer.main;
|
||||||
|
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.crypto.mixnet.Mixer;
|
||||||
|
import meerkat.crypto.mixnet.MixerOutput;
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.mixer.mixing.MixNetwork;
|
||||||
|
import meerkat.mixer.necessary.AsyncBulletinBoardClient;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/17/2015.
|
||||||
|
* this class define all the operation meerkat.mixer.mixing party should do:
|
||||||
|
* 1. receive previous mixers output (re encrypted votes + proofs)
|
||||||
|
* 2. verify its input
|
||||||
|
* 3. mix
|
||||||
|
* 4. send the meerkat.mixer.mixing output
|
||||||
*/
|
*/
|
||||||
public class MainMixing {
|
public class MainMixing {
|
||||||
|
|
||||||
|
private final Mixer mixer;
|
||||||
|
private final Mix2ZeroKnowledgeVerifier verifier;
|
||||||
|
private final int n, layers;
|
||||||
|
private final AsyncBulletinBoardClient asyncBulletinBoardClient;
|
||||||
|
private final byte[] id;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param mixer
|
||||||
|
* @param verifier
|
||||||
|
* @param n
|
||||||
|
* @param asyncBulletinBoardClient
|
||||||
|
* @param id
|
||||||
|
*/
|
||||||
|
public MainMixing(Mixer mixer, Mix2ZeroKnowledgeVerifier verifier, int n
|
||||||
|
, AsyncBulletinBoardClient asyncBulletinBoardClient, byte[] id) {
|
||||||
|
this.mixer = mixer;
|
||||||
|
this.verifier = verifier;
|
||||||
|
this.n = n;
|
||||||
|
this.layers = MixNetwork.numberOfLayers(n);
|
||||||
|
this.asyncBulletinBoardClient = asyncBulletinBoardClient;
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param prevBatchIds
|
||||||
|
* @param batchId
|
||||||
|
* @param random
|
||||||
|
* @param callback
|
||||||
|
* @throws Throwable
|
||||||
|
*/
|
||||||
|
public void main(List<Integer> prevBatchIds, int batchId, Random random, AsyncBulletinBoardClient.ClientCallback<?> callback) throws Throwable {
|
||||||
|
|
||||||
|
List<Crypto.RerandomizableEncryptedMessage> mixerInput;
|
||||||
|
|
||||||
|
List<BatchHandler> batchHandlers = new ArrayList<BatchHandler>(prevBatchIds.size());
|
||||||
|
BatchHandler currentBatchHandler;
|
||||||
|
for (Integer prevBatchId : prevBatchIds) {
|
||||||
|
currentBatchHandler = new BatchHandler(n, layers,verifier);
|
||||||
|
asyncBulletinBoardClient.readBatch(id, prevBatchId,currentBatchHandler);
|
||||||
|
batchHandlers.add(currentBatchHandler);
|
||||||
|
}
|
||||||
|
// check all handlers messages were received
|
||||||
|
for (BatchHandler batchHandler : batchHandlers) {
|
||||||
|
synchronized (batchHandler){
|
||||||
|
if(!batchHandler.isMsgReceived())
|
||||||
|
batchHandler.wait();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// assert all handlers succeeded
|
||||||
|
for (BatchHandler batchHandler : batchHandlers) {
|
||||||
|
if(!batchHandler.verifyTable()){
|
||||||
|
throw new Exception("invalid input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BatchHandler lastBatchHandler = batchHandlers.get(batchHandlers.size() - 1);
|
||||||
|
mixerInput = lastBatchHandler.getInputForMixer();
|
||||||
|
|
||||||
|
MixerOutput mixerOutput = mixer.mix(mixerInput,random);
|
||||||
|
updateBB(mixerOutput, batchId, callback);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* send meerkat.mixer.mixing output to BB
|
||||||
|
* @param mixerOutput
|
||||||
|
* @param batchId
|
||||||
|
* @param callback
|
||||||
|
*/
|
||||||
|
private void updateBB(MixerOutput mixerOutput
|
||||||
|
, int batchId, AsyncBulletinBoardClient.ClientCallback<?> callback) {
|
||||||
|
|
||||||
|
BatchConverter batchConverter = new BatchConverter(n,layers);
|
||||||
|
List<BulletinBoardAPI.BatchData> batchDataList = batchConverter.MixerOutput2BatchData(mixerOutput);
|
||||||
|
asyncBulletinBoardClient.postBatch(id, batchId, batchDataList, callback);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,214 @@
|
||||||
package meerkat.mixer.mixing;
|
package meerkat.mixer.mixing;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Queue;
|
||||||
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/15/2015.
|
||||||
|
* contains benes mix network.
|
||||||
|
* the network is generated in the constructor and can't be change
|
||||||
*/
|
*/
|
||||||
public class MixNetwork {
|
public class MixNetwork {
|
||||||
|
|
||||||
|
private final Switch[][] switches;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param randomPermutation
|
||||||
|
*/
|
||||||
|
public MixNetwork(RandomPermutation randomPermutation) {
|
||||||
|
this.switches = generateSwitchesValue(randomPermutation.permutation);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* implements benes mix network algorithm
|
||||||
|
* @param permutation - random permutation
|
||||||
|
* @return switches
|
||||||
|
*/
|
||||||
|
private Switch[][] generateSwitchesValue(int[] permutation){
|
||||||
|
int n = permutation.length;
|
||||||
|
assert ((n & n-1) == 0); //n == 2^k
|
||||||
|
int layers = numberOfLayers(n);
|
||||||
|
|
||||||
|
int[] pi, piL, piR;
|
||||||
|
Queue<int[]> permutationsQueue = new ArrayBlockingQueue<int[]>(n);
|
||||||
|
Graph graph;
|
||||||
|
int iDiv2;
|
||||||
|
int nDiv2 = n >> 1;
|
||||||
|
Switch[][] switches = new Switch[layers][nDiv2];
|
||||||
|
int index1,index2;
|
||||||
|
|
||||||
|
permutationsQueue.add(permutation);
|
||||||
|
for (int i = n, layer = 0; i > 1; i >>= 1, layer++) // i == permutation size
|
||||||
|
{
|
||||||
|
iDiv2 = i >> 1;
|
||||||
|
for (int j = 0; j < nDiv2; j += iDiv2) // j == permutation start index
|
||||||
|
{
|
||||||
|
pi = permutationsQueue.remove();
|
||||||
|
graph = new Graph(pi);
|
||||||
|
piL = new int[iDiv2];
|
||||||
|
piR = new int[iDiv2];
|
||||||
|
for (int k = 0; k < iDiv2; k++){ // k == switch index in permutation j
|
||||||
|
|
||||||
|
index1 = k + (j << 1);
|
||||||
|
index2 = index1 + iDiv2;
|
||||||
|
switches[layers - layer - 1][k + j] = new Switch(index1,index2,layers - layer - 1,graph.getSwitchValue(k, true));
|
||||||
|
switches[layer][k + j] = new Switch(index1,index2,layer,graph.getSwitchValue(k, false));
|
||||||
|
|
||||||
|
if (!switches[layers - layer - 1][k + j].value) {
|
||||||
|
piL[k] = pi[k] % iDiv2;
|
||||||
|
piR[k] = pi[k + iDiv2] % iDiv2;
|
||||||
|
} else {
|
||||||
|
piL[k] = pi[k + iDiv2] % iDiv2;
|
||||||
|
piR[k] = pi[k] % iDiv2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
permutationsQueue.add(piL);
|
||||||
|
permutationsQueue.add(piR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return switches;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter for switches value at layer
|
||||||
|
* @param layer
|
||||||
|
* @return switches[layer]
|
||||||
|
*/
|
||||||
|
public Switch[] getSwitchesByLayer(int layer)
|
||||||
|
{
|
||||||
|
return switches[layer];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* calc number of layers for n values
|
||||||
|
* @param n number of votes
|
||||||
|
* @return layers
|
||||||
|
*/
|
||||||
|
public static int numberOfLayers(int n){
|
||||||
|
return (int) (2 * Math.log(n) / Math.log(2)) - 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inner class
|
||||||
|
* graph object, part of benes mix network algorithm
|
||||||
|
*/
|
||||||
|
private class Graph {
|
||||||
|
private int n;
|
||||||
|
private int nDiv2;
|
||||||
|
private Node[][] nodes;
|
||||||
|
protected Graph(int[] permutation){
|
||||||
|
n = permutation.length; // n = 2^k
|
||||||
|
nDiv2 = n >> 1;
|
||||||
|
createNodes();
|
||||||
|
createEdges(permutation);
|
||||||
|
setSwitches();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* provide an access to algorithm result
|
||||||
|
* index must be less then n/2
|
||||||
|
*/
|
||||||
|
protected boolean getSwitchValue(int index,boolean up) {
|
||||||
|
return up ? nodes[0][index].value : nodes[1][index].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create two lines of nodes size n/2 each
|
||||||
|
* the value of the i th node is (i,i+n/2) if i < n /2 (first line)
|
||||||
|
* otherwise its value is (i - n/2 , i) (second line)
|
||||||
|
*/
|
||||||
|
private void createNodes() {
|
||||||
|
nodes = new Node[2][nDiv2];
|
||||||
|
for (int i = 0; i < nDiv2; i++) {
|
||||||
|
nodes[0][i] = new Node();
|
||||||
|
nodes[1][i] = new Node();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** create an edge between each pair of nodes i,j from different lines (i index of the first line)
|
||||||
|
* if exists k in i th node's value and t in j th node's value
|
||||||
|
* s.t permutation[k] == t
|
||||||
|
* the edge is broken if (k < n/2 and t >= n/2) or (k >= n/2 and t < n/2)
|
||||||
|
* Note: in purpose to avoid edge cases, each node has exactly two edges
|
||||||
|
*/
|
||||||
|
private void createEdges(int[] permutation) {
|
||||||
|
int j;
|
||||||
|
for (int i = 0; i < nDiv2; i++) {
|
||||||
|
j = permutation[i] % nDiv2;
|
||||||
|
nodes[0][i].edges.add(new Edge(nodes[1][j], (permutation[i] >= nDiv2)));
|
||||||
|
nodes[1][j].edges.add(new Edge(nodes[0][i], (permutation[i] >= nDiv2)));
|
||||||
|
|
||||||
|
j = permutation[i + nDiv2] % nDiv2;
|
||||||
|
nodes[0][i].edges.add(new Edge(nodes[1][j], (permutation[i + nDiv2] < nDiv2)));
|
||||||
|
nodes[1][j].edges.add(new Edge(nodes[0][i], (permutation[i + nDiv2] < nDiv2)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* set switch's value (on/off) for each switch (node)
|
||||||
|
* s.t if nodes i,j connected by edge e, i th switch's value
|
||||||
|
* must be equal to j's if e is broken or not equal if e is not broken
|
||||||
|
*/
|
||||||
|
private void setSwitches() {
|
||||||
|
Node node;
|
||||||
|
boolean v;
|
||||||
|
Edge e0,e1;
|
||||||
|
// iterate over first line of nodes
|
||||||
|
for (int i = 0; i < nDiv2; i++) {
|
||||||
|
node = nodes[0][i];
|
||||||
|
if (node.set)
|
||||||
|
continue;
|
||||||
|
//select default value for first node in connected component
|
||||||
|
v = false;
|
||||||
|
// set value to all reachable nodes from node
|
||||||
|
while (true) {
|
||||||
|
node.set = true;
|
||||||
|
node.value = v;
|
||||||
|
e0 = node.edges.get(0); e1 = node.edges.get(1);
|
||||||
|
if (e0.neighbor.set && e1.neighbor.set)
|
||||||
|
break;
|
||||||
|
v ^= (!e0.neighbor.set) ? e0.broken : e1.broken;
|
||||||
|
node = (!e0.neighbor.set) ? e0.neighbor : e1.neighbor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inner class
|
||||||
|
* node object in graph
|
||||||
|
* there are exactly twp edges for each node
|
||||||
|
*/
|
||||||
|
private class Node {
|
||||||
|
public List<Edge> edges;
|
||||||
|
private boolean value;
|
||||||
|
private boolean set;
|
||||||
|
public Node() {
|
||||||
|
edges = new ArrayList<Edge>(2);
|
||||||
|
set = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inner class
|
||||||
|
* edge object in graph
|
||||||
|
*/
|
||||||
|
private class Edge {
|
||||||
|
public Node neighbor;
|
||||||
|
public boolean broken;
|
||||||
|
public Edge(Node neighbor, boolean broken) {
|
||||||
|
this.neighbor = neighbor;
|
||||||
|
this.broken = broken;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,193 @@
|
||||||
package meerkat.mixer.mixing;
|
package meerkat.mixer.mixing;
|
||||||
|
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import meerkat.crypto.Encryption;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
|
import meerkat.crypto.mixnet.MixerOutput;
|
||||||
|
import meerkat.protobuf.Crypto.EncryptionRandomness;
|
||||||
|
import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage;
|
||||||
|
import meerkat.protobuf.Mixing.ZeroKnowledgeProof;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* an implementation of meerkat.crypto.mixnet.Mixer
|
||||||
|
* meerkat.mixer.mixing algorithm on set of n encrypted votes:
|
||||||
|
* 0. asset n is power of two
|
||||||
|
* 1. set switches according to benes network on random permutation
|
||||||
|
* 2. re encrypt and mix with respect to switches values (encryptor.rerandomize)
|
||||||
|
* 3. generate zero knowledge proof on each re encrypted couple
|
||||||
|
* 4. return proofs table + encryption table
|
||||||
|
*
|
||||||
*/
|
*/
|
||||||
public class Mixer {
|
public class Mixer implements meerkat.crypto.mixnet.Mixer {
|
||||||
|
|
||||||
|
private final Mix2ZeroKnowledgeProver prover;
|
||||||
|
private final Encryption encryptor;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param prover
|
||||||
|
* @param encryptor
|
||||||
|
*/
|
||||||
|
public Mixer(Mix2ZeroKnowledgeProver prover, Encryption encryptor) {
|
||||||
|
this.prover = prover;
|
||||||
|
this.encryptor = encryptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* return True iff n == 2 ^ k
|
||||||
|
* @param n
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public static boolean isPowerOfTwo(int n){
|
||||||
|
return (n & (n - 1)) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* initialize encryption table of size (layers + 1)* n
|
||||||
|
* @param n number of votes
|
||||||
|
* @param layers
|
||||||
|
* @param ciphertexts encrypted votes
|
||||||
|
* @return an initialized encryption table s.t first layer == given encrypted votes
|
||||||
|
*/
|
||||||
|
private RerandomizableEncryptedMessage[][] initializeEncryptionTable(int n,int layers,List<RerandomizableEncryptedMessage> ciphertexts){
|
||||||
|
// set first level of encryption
|
||||||
|
RerandomizableEncryptedMessage[][] encryptionTable = new RerandomizableEncryptedMessage[layers + 1][n];
|
||||||
|
for (int j = 0; j < n; j++) {
|
||||||
|
encryptionTable[0][j] = ciphertexts.get(j);
|
||||||
|
}
|
||||||
|
return encryptionTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate randomness for all rerandomize operations
|
||||||
|
* @param n number of votes
|
||||||
|
* @param layers
|
||||||
|
* @return an initialized randomness table of size layers * n
|
||||||
|
*/
|
||||||
|
private EncryptionRandomness[][] generateRandomnessesForRerandomize(int n,int layers,Random random){
|
||||||
|
EncryptionRandomness[][] randomnesses = new EncryptionRandomness[layers][n];
|
||||||
|
for (int layer = 0; layer < layers; layer++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
randomnesses[layer][i] = encryptor.generateRandomness(random);;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return randomnesses;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate new random mix network
|
||||||
|
* @param n number of votes
|
||||||
|
* @param random
|
||||||
|
* @return new random mix network
|
||||||
|
*/
|
||||||
|
private MixNetwork generateMixNetwork(int n,Random random){
|
||||||
|
return new MixNetwork(new RandomPermutation(n,random));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* fills the encryption table with rerandomize encrypted votes.
|
||||||
|
* @param layers
|
||||||
|
* @param mixNetwork switches table (boolean values)
|
||||||
|
* @param encryptionTable an initialized encryption table s.t first layer == given encrypted votes
|
||||||
|
* @param randomnesses an initialized randomness table of size layers * n, use for rerandomize operations
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
private void rerandomize(int layers,MixNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable
|
||||||
|
,EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException {
|
||||||
|
Switch[] switchesLayer;
|
||||||
|
int index1,index2;
|
||||||
|
RerandomizableEncryptedMessage e1,e2;
|
||||||
|
EncryptionRandomness r1,r2;
|
||||||
|
for (int layer = 0; layer < layers; layer++)
|
||||||
|
{
|
||||||
|
switchesLayer = mixNetwork.getSwitchesByLayer(layer);
|
||||||
|
for (Switch sw : switchesLayer) {
|
||||||
|
index1 = sw.i;
|
||||||
|
index2 = sw.j;
|
||||||
|
e1 = encryptionTable[layer][index1];
|
||||||
|
e2 = encryptionTable[layer][index2];
|
||||||
|
|
||||||
|
r1 = randomnesses[layer][index1];
|
||||||
|
r2 = randomnesses[layer][index2];
|
||||||
|
if (!sw.value) {
|
||||||
|
encryptionTable[layer + 1][index1] = encryptor.rerandomize(e1, r1);
|
||||||
|
encryptionTable[layer + 1][index2] = encryptor.rerandomize(e2, r2);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
encryptionTable[layer + 1][index1] = encryptor.rerandomize(e2, r2);
|
||||||
|
encryptionTable[layer + 1][index2] = encryptor.rerandomize(e1, r1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate zero knowledge proof for each rerandomize encrypted votes couple in encryptionTable
|
||||||
|
* @param n number of votes
|
||||||
|
* @param layers
|
||||||
|
* @param mixNetwork switches table (boolean values) used for set encryption table
|
||||||
|
* @param encryptionTable full encryption table
|
||||||
|
* @param randomnesses randomness table of size layers * n, used for set encryption table
|
||||||
|
* @return zero knowledge proofs table
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
private ZeroKnowledgeProof[][] generateZeroKnowledgeProofTable(int n, int layers, MixNetwork mixNetwork
|
||||||
|
, RerandomizableEncryptedMessage[][] encryptionTable
|
||||||
|
, EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException {
|
||||||
|
Switch[] switchesLayer;
|
||||||
|
int index1,index2;
|
||||||
|
int switchIndex = 0;
|
||||||
|
int nDiv2 = n >> 1;
|
||||||
|
ZeroKnowledgeProof[][] proofsTable = new ZeroKnowledgeProof[layers][nDiv2];
|
||||||
|
|
||||||
|
RerandomizableEncryptedMessage e1,e2;
|
||||||
|
EncryptionRandomness r1,r2;
|
||||||
|
for (int layer = 0; layer < layers; layer++)
|
||||||
|
{
|
||||||
|
switchesLayer = mixNetwork.getSwitchesByLayer(layer);
|
||||||
|
for (Switch sw : switchesLayer) {
|
||||||
|
index1 = sw.i;
|
||||||
|
index2 = sw.j;
|
||||||
|
e1 = encryptionTable[layer][index1];
|
||||||
|
e2 = encryptionTable[layer][index2];
|
||||||
|
r1 = randomnesses[layer][index1];
|
||||||
|
r2 = randomnesses[layer][index2];
|
||||||
|
|
||||||
|
proofsTable[layer][switchIndex] =
|
||||||
|
prover.prove(e1, e2, encryptionTable[layer + 1][index1],
|
||||||
|
encryptionTable[layer + 1][index2],
|
||||||
|
sw.value, sw.i, sw.j, sw.layer, r1, r2);
|
||||||
|
|
||||||
|
switchIndex = (switchIndex + 1) % nDiv2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return proofsTable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* mix given encrypted votes using random
|
||||||
|
* @param ciphertexts encrypted votes
|
||||||
|
* @param random
|
||||||
|
* @return meerkat.mixer.mixing result
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
public MixerOutput mix(List<RerandomizableEncryptedMessage> ciphertexts,Random random) throws InvalidProtocolBufferException {
|
||||||
|
|
||||||
|
int n = ciphertexts.size();
|
||||||
|
assert (n > 1 && isPowerOfTwo(n));
|
||||||
|
|
||||||
|
int layers = MixNetwork.numberOfLayers(n); // layers = 2logn -1
|
||||||
|
RerandomizableEncryptedMessage[][] encryptionTable = initializeEncryptionTable(n,layers,ciphertexts);
|
||||||
|
EncryptionRandomness[][] randomnesses = generateRandomnessesForRerandomize(n,layers,random);
|
||||||
|
MixNetwork mixNetwork = generateMixNetwork(n,random);
|
||||||
|
rerandomize(layers,mixNetwork,encryptionTable,randomnesses);
|
||||||
|
ZeroKnowledgeProof[][] proofsTable = generateZeroKnowledgeProofTable(n,layers,mixNetwork,encryptionTable,randomnesses);
|
||||||
|
|
||||||
|
return new meerkat.mixer.mixing.MixerOutput(n,layers,proofsTable, encryptionTable);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -1,7 +1,130 @@
|
||||||
package meerkat.mixer.mixing;
|
package meerkat.mixer.mixing;
|
||||||
|
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileOutputStream;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 1/18/2016.
|
||||||
|
* implements meerkat.crypto.mixnet.MixerOutput interface
|
||||||
|
* container for meerkat.mixer.mixing.mix result.
|
||||||
*/
|
*/
|
||||||
public class MixerOutput {
|
public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{
|
||||||
|
private final Mixing.ZeroKnowledgeProof[][] proofs;
|
||||||
|
private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages;
|
||||||
|
private final int n;
|
||||||
|
private final int layers;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param n number of votes
|
||||||
|
* @param layers
|
||||||
|
* @param encryptedMessages at level 0 , contains the original encrypted votes
|
||||||
|
* at each other level contains the re encrypted votes
|
||||||
|
* @param proofs in each cell (level,switch) contains the match zero knowledge proof
|
||||||
|
*/
|
||||||
|
public MixerOutput(int n,int layers,Mixing.ZeroKnowledgeProof[][] proofs
|
||||||
|
, Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) {
|
||||||
|
this.proofs = proofs;
|
||||||
|
this.encryptedMessages = encryptedMessages;
|
||||||
|
this.n = n;
|
||||||
|
this.layers = layers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Mixing.ZeroKnowledgeProof[][] getProofs() {
|
||||||
|
return proofs;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages() {
|
||||||
|
return encryptedMessages;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getN() {
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* print the output, encrypted messages and proofs, to folder
|
||||||
|
* @param dir - directory
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
public void outToFolder(String dir) throws IOException {
|
||||||
|
|
||||||
|
(new File(dir)).mkdirs();
|
||||||
|
//create files
|
||||||
|
String proofsDir = dir + "/Proofs";
|
||||||
|
String encDir = dir + "/EncryptedMessages";
|
||||||
|
(new File(proofsDir)).mkdir();
|
||||||
|
(new File(encDir)).mkdir();
|
||||||
|
for (int layer = 0; layer < layers; layer++){
|
||||||
|
(new File(proofsDir +"/layer" + layer )).mkdir();
|
||||||
|
(new File(encDir +"/layer" + layer )).mkdir();
|
||||||
|
}
|
||||||
|
(new File(encDir +"/input")).mkdir();
|
||||||
|
|
||||||
|
|
||||||
|
for (int layer = 0; layer < layers; layer++){
|
||||||
|
for(int i = 0; i < proofs[layer].length; i ++){
|
||||||
|
writeProofToFile(proofsDir,proofs[layer][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int layer = 0; layer <= layers; layer++){
|
||||||
|
for(int i = 0; i < encryptedMessages[layer].length; i ++){
|
||||||
|
writeEncToFile(encDir,layer - 1, i,encryptedMessages[layer][i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create new file contains single proof
|
||||||
|
* @param proofsDir
|
||||||
|
* @param proof
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void writeProofToFile(String proofsDir, Mixing.ZeroKnowledgeProof proof) throws IOException {
|
||||||
|
Mixing.ZeroKnowledgeProof.Location location = proof.getLocation();
|
||||||
|
int layer = location.getLayer();
|
||||||
|
int i = location.getI();
|
||||||
|
int j = location.getJ();
|
||||||
|
String fileName = proofsDir+"/layer" + layer +"/" + i +"_" + j;
|
||||||
|
|
||||||
|
File file = new File(fileName);
|
||||||
|
file.createNewFile();
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
fos.write(proof.toByteArray());
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* create new file contains single encrypted message
|
||||||
|
* @param encDir
|
||||||
|
* @param layer
|
||||||
|
* @param i
|
||||||
|
* @param enc
|
||||||
|
* @throws IOException
|
||||||
|
*/
|
||||||
|
private void writeEncToFile(String encDir,int layer,int i, Crypto.RerandomizableEncryptedMessage enc) throws IOException {
|
||||||
|
|
||||||
|
String fileName;
|
||||||
|
if(layer >= 0)
|
||||||
|
fileName = encDir+"/layer" + layer +"/" + i;
|
||||||
|
else
|
||||||
|
fileName = encDir+"/input/" + i;
|
||||||
|
|
||||||
|
File file = new File(fileName);
|
||||||
|
file.createNewFile();
|
||||||
|
FileOutputStream fos = new FileOutputStream(file);
|
||||||
|
fos.write(enc.toByteArray());
|
||||||
|
fos.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,45 @@
|
||||||
package meerkat.mixer.mixing;
|
package meerkat.mixer.mixing;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/17/2015.
|
||||||
|
* container for random permutation
|
||||||
|
* the permutation is sated in constructor and can't be change
|
||||||
*/
|
*/
|
||||||
public class RandomPermutation {
|
public class RandomPermutation {
|
||||||
|
public final int[] permutation;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param n permutation size
|
||||||
|
* @param random
|
||||||
|
*/
|
||||||
|
public RandomPermutation(int n,Random random) {
|
||||||
|
this.permutation = generatePermutation(n,random);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* generate random permutation ovver [0,n)
|
||||||
|
* @param n permutation size
|
||||||
|
* @param random
|
||||||
|
* @return permutation
|
||||||
|
*/
|
||||||
|
private int[] generatePermutation(int n,Random random){
|
||||||
|
List<Integer> numbers= new ArrayList<Integer>(n);
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
numbers.add(i);
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] result = new int[n];
|
||||||
|
int index;
|
||||||
|
for (int i = 0; i < n; i++) {
|
||||||
|
index = random.nextInt(n - i);
|
||||||
|
result[i] = numbers.get(index);
|
||||||
|
numbers.remove(index);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,36 @@
|
||||||
package meerkat.mixer.mixing;
|
package meerkat.mixer.mixing;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/15/2015.
|
||||||
|
* container for switch
|
||||||
*/
|
*/
|
||||||
public class Switch{
|
public class Switch{
|
||||||
|
|
||||||
|
public final int i, j, layer;
|
||||||
|
public final boolean value;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param i
|
||||||
|
* @param j
|
||||||
|
* @param layer
|
||||||
|
* @param value the switch is on or off
|
||||||
|
*/
|
||||||
|
public Switch(int i, int j, int layer, boolean value) {
|
||||||
|
this.i = i;
|
||||||
|
this.j = j;
|
||||||
|
this.layer = layer;
|
||||||
|
this.value = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Switch{" +
|
||||||
|
"i=" + i +
|
||||||
|
", j=" + j +
|
||||||
|
", layer=" + layer +
|
||||||
|
", value=" + value +
|
||||||
|
'}';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,80 @@
|
||||||
package meerkat.mixer.necessary;
|
package meerkat.mixer.necessary;
|
||||||
|
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Arbel Deutsch Peled on 14-Dec-15.
|
||||||
|
*
|
||||||
|
* ToDo: this should be replaced by AsyncBulletinBoardClient at BB project
|
||||||
*/
|
*/
|
||||||
public class AsyncBulletinBoardClient {
|
public interface AsyncBulletinBoardClient extends BulletinBoardClient {
|
||||||
|
|
||||||
|
public interface ClientCallback<T> {
|
||||||
|
void handleCallback(T msg);
|
||||||
|
void handleFailure(Throwable t);
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface MessageHandler {
|
||||||
|
void handleNewMessages(List<BulletinBoardMessage> messageList);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post a message to the bulletin board in an asynchronous manner
|
||||||
|
* @param msg is the message to be posted
|
||||||
|
* @param callback is a class containing methods to handle the result of the operation
|
||||||
|
* @return a unique message ID for the message, that can be later used to retrieve the batch
|
||||||
|
*/
|
||||||
|
public MessageID postMessage(BulletinBoardMessage msg, ClientCallback<?> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This method allows for sending large messages as a batch to the bulletin board
|
||||||
|
* @param signerId is the canonical form for the ID of the sender of this batch
|
||||||
|
* @param batchId is a unique (per signer) ID for this batch
|
||||||
|
* @param batchDataList is the (canonically ordered) list of data comprising the batch message
|
||||||
|
* @param startPosition is the location (in the batch) of the first entry in batchDataList (optionally used to continue interrupted post operations)
|
||||||
|
* @param callback is a callback function class for handling results of the operation
|
||||||
|
* @return a unique message ID for the entire message, that can be later used to retrieve the batch
|
||||||
|
*/
|
||||||
|
public MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, int startPosition, ClientCallback<?> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Overloading of the postBatch method in which startPosition is set to the default value 0
|
||||||
|
*/
|
||||||
|
public MessageID postBatch(byte[] signerId, int batchId, List<BatchData> batchDataList, ClientCallback<?> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check how "safe" a given message is in an asynchronous manner
|
||||||
|
* The result of the computation is a rank between 0.0 and 1.0 indicating the fraction of servers containing the message
|
||||||
|
* @param id is the unique message identifier for retrieval
|
||||||
|
* @param callback is a callback function class for handling results of the operation
|
||||||
|
*/
|
||||||
|
public void getRedundancy(MessageID id, ClientCallback<Float> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all messages posted matching the given filter in an asynchronous manner
|
||||||
|
* Note that if messages haven't been "fully posted", this might return a different
|
||||||
|
* set of messages in different calls. However, messages that are fully posted
|
||||||
|
* are guaranteed to be included.
|
||||||
|
* @param filterList return only messages that match the filters (null means no filtering).
|
||||||
|
* @param callback is a callback function class for handling results of the operation
|
||||||
|
*/
|
||||||
|
public void readMessages(MessageFilterList filterList, ClientCallback<List<BulletinBoardMessage>> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read a given batch message from the bulletin board
|
||||||
|
* @param signerId is the ID of the signer (sender) of the batch message
|
||||||
|
* @param batchId is the unique (per signer) ID of the batch
|
||||||
|
* @param callback is a callback class for handling the result of the operation
|
||||||
|
*/
|
||||||
|
public void readBatch(byte[] signerId, int batchId, ClientCallback<CompleteBatch> callback);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subscribes to a notifier that will return any new messages on the server that match the given filters
|
||||||
|
* @param filterList defines the set of filters for message retrieval
|
||||||
|
* @param messageHandler defines the handler for new messages received
|
||||||
|
*/
|
||||||
|
public void subscribe(MessageFilterList filterList, MessageHandler messageHandler);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,61 @@
|
||||||
package meerkat.mixer.necessary;
|
package meerkat.mixer.necessary;
|
||||||
|
|
||||||
|
import meerkat.comm.CommunicationException;
|
||||||
|
import meerkat.protobuf.Voting.BulletinBoardClientParams;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static meerkat.protobuf.BulletinBoardAPI.*;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by talm on 24/10/15.
|
||||||
|
*
|
||||||
|
* ToDo: this should be replaced by BulletinBoardClient at BB project
|
||||||
*/
|
*/
|
||||||
public class BulletinBoardClient {
|
public interface BulletinBoardClient {
|
||||||
|
|
||||||
|
interface ClientCallback<T> {
|
||||||
|
void handleCallback(T msg);
|
||||||
|
void handleFailure(Throwable t);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize the client to use some specified servers
|
||||||
|
* @param clientParams contains the parameters required for the client setup
|
||||||
|
*/
|
||||||
|
void init(BulletinBoardClientParams clientParams);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Post a message to the bulletin board in a synchronous manner
|
||||||
|
* @param msg is the message to be posted
|
||||||
|
* @return a unique message ID for the message, that can be later used to retrieve the batch
|
||||||
|
* @throws CommunicationException
|
||||||
|
*/
|
||||||
|
MessageID postMessage(BulletinBoardMessage msg) throws CommunicationException;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check how "safe" a given message is in a synchronous manner
|
||||||
|
* @param id is the unique message identifier for retrieval
|
||||||
|
* @return a normalized "redundancy score" from 0 (local only) to 1 (fully published)
|
||||||
|
*/
|
||||||
|
float getRedundancy(MessageID id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Read all messages posted matching the given filter in a synchronous manner
|
||||||
|
* Note that if messages haven't been "fully posted", this might return a different
|
||||||
|
* set of messages in different calls. However, messages that are fully posted
|
||||||
|
* are guaranteed to be included.
|
||||||
|
* @param filterList return only messages that match the filters (null means no filtering).
|
||||||
|
* @return the list of messages
|
||||||
|
*/
|
||||||
|
List<BulletinBoardMessage> readMessages(MessageFilterList filterList);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Closes all connections, if any.
|
||||||
|
* This is msgRecived in a synchronous (blocking) way.
|
||||||
|
*/
|
||||||
|
void close();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,70 @@
|
||||||
package meerkat.mixer.necessary;
|
package meerkat.mixer.necessary;
|
||||||
|
|
||||||
|
|
||||||
|
import meerkat.protobuf.BulletinBoardAPI.*;
|
||||||
|
import meerkat.protobuf.Crypto.*;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Arbel Deutsch Peled on 14-Dec-15.
|
||||||
|
*
|
||||||
|
* A data structure for holding a complete batch message along with its signature
|
||||||
|
*
|
||||||
|
* ToDo: this should be replaced by CompleteBatch at BB project
|
||||||
*/
|
*/
|
||||||
public class CompleteBatch {
|
public class CompleteBatch {
|
||||||
|
|
||||||
|
private BeginBatchMessage beginBatchMessage;
|
||||||
|
private List<BatchData> batchDataList;
|
||||||
|
private Signature signature;
|
||||||
|
|
||||||
|
public CompleteBatch() {
|
||||||
|
batchDataList = new LinkedList<BatchData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompleteBatch(BeginBatchMessage newBeginBatchMessage) {
|
||||||
|
this();
|
||||||
|
beginBatchMessage = newBeginBatchMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List<BatchData> newDataList) {
|
||||||
|
this(newBeginBatchMessage);
|
||||||
|
appendBatchData(newDataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List<BatchData> newDataList, Signature newSignature) {
|
||||||
|
this(newBeginBatchMessage, newDataList);
|
||||||
|
signature = newSignature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public BeginBatchMessage getBeginBatchMessage() {
|
||||||
|
return beginBatchMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<BatchData> getBatchDataList() {
|
||||||
|
return batchDataList;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Signature getSignature() {
|
||||||
|
return signature;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBeginBatchMessage(BeginBatchMessage beginBatchMessage) {
|
||||||
|
this.beginBatchMessage = beginBatchMessage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendBatchData(BatchData newBatchData) {
|
||||||
|
batchDataList.add(newBatchData);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendBatchData(List<BatchData> newBatchDataList) {
|
||||||
|
batchDataList.addAll(newBatchDataList);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setSignature(Signature newSignature) {
|
||||||
|
signature = newSignature;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,303 @@
|
||||||
package meerkat.mixer.prover;
|
package meerkat.mixer.prover;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* use for organize the input for each ZKP
|
||||||
|
*
|
||||||
|
* both meerkat.mixer.prover and meerkat.mixer.verifier implantation are using it
|
||||||
*/
|
*/
|
||||||
public class ElGamalProofOrganizer {
|
public class ElGamalProofOrganizer {
|
||||||
|
|
||||||
|
private final ECGroup group;
|
||||||
|
private final ECPoint g;
|
||||||
|
private final ECPoint h;
|
||||||
|
private final byte[] gEncoded;
|
||||||
|
private final byte[] hEncoded;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param group
|
||||||
|
* @param g - generator of group
|
||||||
|
* @param h - h = g ^ SecretKey
|
||||||
|
*/
|
||||||
|
public ElGamalProofOrganizer(ECGroup group, ECPoint g, ECPoint h){
|
||||||
|
this.group = group;
|
||||||
|
this.g = g;
|
||||||
|
this.h = h;
|
||||||
|
this.gEncoded = group.encode(g);
|
||||||
|
this.hEncoded = group.encode(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum OrProofOrder {
|
||||||
|
first, second, third, fourth
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum TrueCouple {
|
||||||
|
left, right, unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can be used by meerkat.mixer.prover only
|
||||||
|
*
|
||||||
|
* call to the meerkat.mixer.main overload with flag = true
|
||||||
|
*/
|
||||||
|
protected ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||||
|
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2
|
||||||
|
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) throws InvalidProtocolBufferException {
|
||||||
|
|
||||||
|
//boolean flag = true;
|
||||||
|
return createProofInput(in1,in2,out1,out2,r1,r2,switched,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can be used by anyone, e.g meerkat.mixer.verifier
|
||||||
|
*
|
||||||
|
* call to the meerkat.mixer.main overload with flag = false
|
||||||
|
*/
|
||||||
|
public ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||||
|
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException {
|
||||||
|
|
||||||
|
// flag = false;
|
||||||
|
return createProofInput(in1,in2,out1,out2,null,null,false,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inner method
|
||||||
|
* convert each encrypted message to ElGamalCiphertext
|
||||||
|
*
|
||||||
|
* @param flag - true if called by meerkat.mixer.prover ( r1,r2,switched are known)
|
||||||
|
* @return ElGamalProofInput
|
||||||
|
* @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't
|
||||||
|
* ElGamalCiphertext
|
||||||
|
*/
|
||||||
|
private ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2
|
||||||
|
, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2
|
||||||
|
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched,boolean flag)
|
||||||
|
throws InvalidProtocolBufferException {
|
||||||
|
|
||||||
|
//convert RerandomizableEncryptedMessage to ElGamalCiphertext
|
||||||
|
ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1);
|
||||||
|
ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2);
|
||||||
|
ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1);
|
||||||
|
ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2);
|
||||||
|
|
||||||
|
if(flag) {
|
||||||
|
return new ElGamalProofInput(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched);
|
||||||
|
}else {
|
||||||
|
return new ElGamalProofInput(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can be construct by instance of organizer only by calling createProofInput method (all constructors are private)
|
||||||
|
*
|
||||||
|
* in construction it use for preparing the input for prove, while avoiding double converting or calculations
|
||||||
|
*
|
||||||
|
* use as a container for 4 OrProofInput.
|
||||||
|
*/
|
||||||
|
public class ElGamalProofInput {
|
||||||
|
|
||||||
|
private final OrProofInput first;
|
||||||
|
private final OrProofInput second;
|
||||||
|
private final OrProofInput third;
|
||||||
|
private final OrProofInput fourth;
|
||||||
|
|
||||||
|
private ECPoint convert2ECPoint(ByteString bs){
|
||||||
|
return group.decode(bs.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param flag - true if called by meerkat.mixer.prover ( r1,r2,switched are known)
|
||||||
|
*/
|
||||||
|
private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||||
|
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New
|
||||||
|
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched,boolean flag){
|
||||||
|
|
||||||
|
ECPoint e1c1 = convert2ECPoint(e1.getC1());
|
||||||
|
ECPoint e1c2 = convert2ECPoint(e1.getC2());
|
||||||
|
ECPoint e2c1 = convert2ECPoint(e2.getC1());
|
||||||
|
ECPoint e2c2 = convert2ECPoint(e2.getC2());
|
||||||
|
ECPoint e1Nc1 = convert2ECPoint(e1New.getC1());
|
||||||
|
ECPoint e1Nc2 = convert2ECPoint(e1New.getC2());
|
||||||
|
ECPoint e2Nc1 = convert2ECPoint(e2New.getC1());
|
||||||
|
ECPoint e2Nc2 = convert2ECPoint(e2New.getC2());
|
||||||
|
|
||||||
|
ECPoint c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1));
|
||||||
|
ECPoint c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1));
|
||||||
|
ECPoint c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1));
|
||||||
|
ECPoint c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1));
|
||||||
|
|
||||||
|
ECPoint c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2));
|
||||||
|
ECPoint c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2));
|
||||||
|
ECPoint c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2));
|
||||||
|
ECPoint c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2));
|
||||||
|
|
||||||
|
|
||||||
|
if(!flag){
|
||||||
|
|
||||||
|
this.first = new OrProofInput(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2);
|
||||||
|
this.second = new OrProofInput(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1);
|
||||||
|
this.third = new OrProofInput(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2);
|
||||||
|
this.fourth = new OrProofInput(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2);
|
||||||
|
|
||||||
|
}else {
|
||||||
|
|
||||||
|
byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1);
|
||||||
|
byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1);
|
||||||
|
byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2);
|
||||||
|
byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2);
|
||||||
|
byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1);
|
||||||
|
byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1);
|
||||||
|
byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2);
|
||||||
|
byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2);
|
||||||
|
|
||||||
|
|
||||||
|
if (!switched) {
|
||||||
|
this.first = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||||
|
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||||
|
, r1, TrueCouple.left);
|
||||||
|
this.second = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||||
|
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||||
|
, r1, TrueCouple.left);
|
||||||
|
this.third = new OrProofInput(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||||
|
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||||
|
, r2, TrueCouple.right);
|
||||||
|
this.fourth = new OrProofInput(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||||
|
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||||
|
, r2, TrueCouple.right);
|
||||||
|
} else {
|
||||||
|
this.first = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2
|
||||||
|
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded
|
||||||
|
, r2, TrueCouple.right);
|
||||||
|
this.second = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1
|
||||||
|
, c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded
|
||||||
|
, r1, TrueCouple.right);
|
||||||
|
this.third = new OrProofInput(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2
|
||||||
|
, c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||||
|
, r2, TrueCouple.left);
|
||||||
|
this.fourth = new OrProofInput(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2
|
||||||
|
, c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded
|
||||||
|
, r1, TrueCouple.left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by the meerkat.mixer.prover
|
||||||
|
* call to the meerkat.mixer.main constructor with flag = true
|
||||||
|
*/
|
||||||
|
private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||||
|
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New
|
||||||
|
, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched){
|
||||||
|
//flag = true;
|
||||||
|
this(e1,e2,e1New,e2New,r1,r2,switched,true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by meerkat.mixer.prover
|
||||||
|
* call to the meerkat.mixer.main constructor with flag = true
|
||||||
|
*/
|
||||||
|
private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2
|
||||||
|
, ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){
|
||||||
|
//flag = false;
|
||||||
|
this(e1,e2,e1New,e2New,null,null,false,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter for all 4 OrProofInputs
|
||||||
|
*
|
||||||
|
* @param orProofOrder
|
||||||
|
* @return the required OrProof
|
||||||
|
*/
|
||||||
|
public OrProofInput getOrProofInput(OrProofOrder orProofOrder) {
|
||||||
|
switch (orProofOrder) {
|
||||||
|
|
||||||
|
case first:
|
||||||
|
return this.first;
|
||||||
|
case second:
|
||||||
|
return this.second;
|
||||||
|
case third:
|
||||||
|
return this.third;
|
||||||
|
case fourth:
|
||||||
|
return this.fourth;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* can't be constructed (all constructors are private)
|
||||||
|
*
|
||||||
|
* 4 instances will be constructed for each new ElGamalProofInput
|
||||||
|
*
|
||||||
|
* container for all meerkat.mixer.necessary inputs for single OrProof
|
||||||
|
*/
|
||||||
|
public class OrProofInput{
|
||||||
|
public final ECPoint g1;
|
||||||
|
public final ECPoint h1;
|
||||||
|
public final ECPoint g2;
|
||||||
|
public final ECPoint h2;
|
||||||
|
public final ECPoint g1Tag;
|
||||||
|
public final ECPoint h1Tag;
|
||||||
|
public final ECPoint g2Tag;
|
||||||
|
public final ECPoint h2Tag;
|
||||||
|
|
||||||
|
// can be access by meerkat.mixer.prover only
|
||||||
|
protected final byte[] g1Encoded;
|
||||||
|
protected final byte[] h1Encoded;
|
||||||
|
protected final byte[] g2Encoded;
|
||||||
|
protected final byte[] h2Encoded;
|
||||||
|
protected final byte[] g1TagEncoded;
|
||||||
|
protected final byte[] h1TagEncoded;
|
||||||
|
protected final byte[] g2TagEncoded;
|
||||||
|
protected final byte[] h2TagEncoded;
|
||||||
|
protected final Crypto.EncryptionRandomness x;
|
||||||
|
protected final TrueCouple flag;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by meerkat.mixer.prover only
|
||||||
|
*/
|
||||||
|
private OrProofInput(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag
|
||||||
|
,byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded
|
||||||
|
, Crypto.EncryptionRandomness x, TrueCouple flag) {
|
||||||
|
this.g1 = g;
|
||||||
|
this.h1 = h1;
|
||||||
|
this.g2 = h;
|
||||||
|
this.h2 = h2;
|
||||||
|
this.g1Tag = g;
|
||||||
|
this.h1Tag = h1Tag;
|
||||||
|
this.g2Tag = h;
|
||||||
|
this.h2Tag = h2Tag;
|
||||||
|
|
||||||
|
this.g1Encoded = gEncoded;
|
||||||
|
this.h1Encoded = h1Encoded;
|
||||||
|
this.g2Encoded = hEncoded;
|
||||||
|
this.h2Encoded = h2Encoded;
|
||||||
|
this.g1TagEncoded = gEncoded;
|
||||||
|
this.h1TagEncoded = h1TagEncoded;
|
||||||
|
this.g2TagEncoded = hEncoded;
|
||||||
|
this.h2TagEncoded = h2TagEncoded;
|
||||||
|
|
||||||
|
this.x = x;
|
||||||
|
this.flag = flag;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* used by meerkat.mixer.verifier
|
||||||
|
*/
|
||||||
|
private OrProofInput(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) {
|
||||||
|
this(h1,h2,h1Tag,h2Tag,null,null,null,null,null,TrueCouple.unknown);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,216 @@
|
||||||
package meerkat.mixer.prover;
|
package meerkat.mixer.prover;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.factcenter.qilin.primitives.RandomOracle;
|
||||||
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
import java.util.Random;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* implements of Mix2ZeroKnowledgeProver interface
|
||||||
|
* this implantation assumes that each RerandomizableEncryptedMessage is ElGamalCiphertext
|
||||||
*/
|
*/
|
||||||
public class Prover {
|
public class Prover implements Mix2ZeroKnowledgeProver {
|
||||||
|
|
||||||
|
private final ECGroup group;
|
||||||
|
private final RandomOracle randomOracle;
|
||||||
|
private final Random rand;
|
||||||
|
private final ECElGamalEncryption encryptor;
|
||||||
|
private final ECPoint g,h;
|
||||||
|
private final BigInteger groupOrderUpperBound;
|
||||||
|
private final ElGamalProofOrganizer organizer;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param rand
|
||||||
|
* @param encryptor
|
||||||
|
* @param randomOracle - use for Fiat–Shamir heuristic
|
||||||
|
*/
|
||||||
|
public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) {
|
||||||
|
|
||||||
|
this.rand = rand;
|
||||||
|
this.encryptor = encryptor;
|
||||||
|
this.randomOracle = randomOracle;
|
||||||
|
this.group = this.encryptor.getGroup();
|
||||||
|
this.g = group.getGenerator();
|
||||||
|
this.h = this.encryptor.getElGamalPK().getPK();
|
||||||
|
this.organizer = new ElGamalProofOrganizer(group,g,h);
|
||||||
|
this.groupOrderUpperBound = group.orderUpperBound();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param in1
|
||||||
|
* @param in2
|
||||||
|
* @param out1 - if sw then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1)
|
||||||
|
* @param out2 - if sw then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2)
|
||||||
|
* @param sw - flag
|
||||||
|
* @param i - column of in1 and out1 in encryption table
|
||||||
|
* @param j - column of in2 and out2 in encryption table
|
||||||
|
* @param layer - row of in1,in2 in encryption table
|
||||||
|
* @param r1
|
||||||
|
* @param r2
|
||||||
|
* @return - a valid ZKP that indeed out1,out2 calculated as required
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage in2,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out2,
|
||||||
|
boolean sw,int i,int j, int layer,
|
||||||
|
Crypto.EncryptionRandomness r1,
|
||||||
|
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth;
|
||||||
|
|
||||||
|
ElGamalProofOrganizer.ElGamalProofInput input = organizer.createProofInput(in1,in2,out1,out2,r1,r2,sw);
|
||||||
|
|
||||||
|
first = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.first));
|
||||||
|
second = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.second));
|
||||||
|
third = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.third));
|
||||||
|
fourth = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.fourth));
|
||||||
|
|
||||||
|
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
|
||||||
|
.setI(i)
|
||||||
|
.setJ(j)
|
||||||
|
.setLayer(layer)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder()
|
||||||
|
.setFirst(first)
|
||||||
|
.setSecond(second)
|
||||||
|
.setThird(third)
|
||||||
|
.setFourth(fourth)
|
||||||
|
.setLocation(location)
|
||||||
|
.build();
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Fiat–Shamir heuristic
|
||||||
|
* @param input - protobuf contains all parameters from the first step of the current prove
|
||||||
|
* @param randomOracle
|
||||||
|
* @return randomOracle.hash(input)
|
||||||
|
*/
|
||||||
|
public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input, RandomOracle randomOracle) {
|
||||||
|
byte[] arr = input.toByteArray();
|
||||||
|
return new BigInteger(1,randomOracle.hash(arr,arr.length));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param orProofInput
|
||||||
|
* @return ZKP OrProof: there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2)
|
||||||
|
* assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.prover
|
||||||
|
*/
|
||||||
|
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalProofOrganizer.OrProofInput orProofInput) {
|
||||||
|
|
||||||
|
ECPoint g1 = orProofInput.g1;
|
||||||
|
ECPoint h1 = orProofInput.h1;
|
||||||
|
ECPoint g2 = orProofInput.g2;
|
||||||
|
ECPoint h2 = orProofInput.h2;
|
||||||
|
|
||||||
|
ECPoint g1Tag = orProofInput.g1Tag;
|
||||||
|
ECPoint h1Tag = orProofInput.h1Tag;
|
||||||
|
ECPoint g2Tag = orProofInput.g2Tag;
|
||||||
|
ECPoint h2Tag = orProofInput.h2Tag;
|
||||||
|
|
||||||
|
BigInteger r = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||||
|
BigInteger c1,c2,z,zTag;
|
||||||
|
ECPoint u,v,uTag,vTag;
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle;
|
||||||
|
|
||||||
|
|
||||||
|
switch (orProofInput.flag) {
|
||||||
|
case left:
|
||||||
|
c2 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||||
|
zTag = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||||
|
//step 1
|
||||||
|
u = group.multiply(g1, r);
|
||||||
|
v = group.multiply(g2, r);
|
||||||
|
uTag = group.add(group.multiply(g1Tag, zTag), group.negate(group.multiply(h1Tag, c2)));
|
||||||
|
vTag = group.add(group.multiply(g2Tag, zTag), group.negate(group.multiply(h2Tag, c2)));
|
||||||
|
//step 2
|
||||||
|
// c1 = (hash(input + step1) + group size - c2)% group size
|
||||||
|
forRandomOracle =
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||||
|
.setG1(ByteString.copyFrom(orProofInput.g1Encoded))
|
||||||
|
.setH1(ByteString.copyFrom(orProofInput.h1Encoded))
|
||||||
|
.setG2(ByteString.copyFrom(orProofInput.g2Encoded))
|
||||||
|
.setH2(ByteString.copyFrom(orProofInput.h2Encoded))
|
||||||
|
.setG1Tag(ByteString.copyFrom(orProofInput.g1TagEncoded))
|
||||||
|
.setH1Tag(ByteString.copyFrom(orProofInput.h1TagEncoded))
|
||||||
|
.setG2Tag(ByteString.copyFrom(orProofInput.g2TagEncoded))
|
||||||
|
.setH2Tag(ByteString.copyFrom(orProofInput.h2TagEncoded))
|
||||||
|
.setU(ByteString.copyFrom(group.encode(u)))
|
||||||
|
.setV(ByteString.copyFrom(group.encode(v)))
|
||||||
|
.setUTag(ByteString.copyFrom(group.encode(uTag)))
|
||||||
|
.setVTag(ByteString.copyFrom(group.encode(vTag)))
|
||||||
|
.build();
|
||||||
|
c1 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound);
|
||||||
|
//step 3
|
||||||
|
//z = (r + c1 * x) % group size;
|
||||||
|
z = r.add(c1.multiply(encryptor.extractRandomness(orProofInput.x))).mod(groupOrderUpperBound);
|
||||||
|
break;
|
||||||
|
case right:
|
||||||
|
c1 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||||
|
z = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound);
|
||||||
|
//step 1
|
||||||
|
uTag = group.multiply(g1Tag, r);
|
||||||
|
vTag = group.multiply(g2Tag, r);
|
||||||
|
u = group.add(group.multiply(g1, z), group.negate(group.multiply(h1, c1)));
|
||||||
|
v = group.add(group.multiply(g2, z), group.negate(group.multiply(h2, c1)));
|
||||||
|
//step 2
|
||||||
|
// c1 = (hash(input + step1) + group size - c1)% group size
|
||||||
|
forRandomOracle =
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||||
|
.setG1(ByteString.copyFrom(orProofInput.g1Encoded))
|
||||||
|
.setH1(ByteString.copyFrom(orProofInput.h1Encoded))
|
||||||
|
.setG2(ByteString.copyFrom(orProofInput.g2Encoded))
|
||||||
|
.setH2(ByteString.copyFrom(orProofInput.h2Encoded))
|
||||||
|
.setG1Tag(ByteString.copyFrom(orProofInput.g1TagEncoded))
|
||||||
|
.setH1Tag(ByteString.copyFrom(orProofInput.h1TagEncoded))
|
||||||
|
.setG2Tag(ByteString.copyFrom(orProofInput.g2TagEncoded))
|
||||||
|
.setH2Tag(ByteString.copyFrom(orProofInput.h2TagEncoded))
|
||||||
|
.setU(ByteString.copyFrom(group.encode(u)))
|
||||||
|
.setV(ByteString.copyFrom(group.encode(v)))
|
||||||
|
.setUTag(ByteString.copyFrom(group.encode(uTag)))
|
||||||
|
.setVTag(ByteString.copyFrom(group.encode(vTag)))
|
||||||
|
.build();
|
||||||
|
c2 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound);
|
||||||
|
//step 3
|
||||||
|
//zTag = (r + c2 * x) % group size;
|
||||||
|
zTag = r.add(c2.multiply(encryptor.extractRandomness(orProofInput.x))).mod(groupOrderUpperBound);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
|
||||||
|
.setG1(forRandomOracle.getG1())
|
||||||
|
.setH1(forRandomOracle.getH1())
|
||||||
|
.setG2(forRandomOracle.getG2())
|
||||||
|
.setH2(forRandomOracle.getH2())
|
||||||
|
.setG1Tag(forRandomOracle.getG1())
|
||||||
|
.setH1Tag(forRandomOracle.getH1Tag())
|
||||||
|
.setG2Tag(forRandomOracle.getG2Tag())
|
||||||
|
.setH2Tag(forRandomOracle.getH2Tag())
|
||||||
|
.setU(forRandomOracle.getU())
|
||||||
|
.setV(forRandomOracle.getV())
|
||||||
|
.setUTag(forRandomOracle.getUTag())
|
||||||
|
.setVTag(forRandomOracle.getVTag())
|
||||||
|
.setC1(ByteString.copyFrom(c1.toByteArray()))
|
||||||
|
.setC2(ByteString.copyFrom(c2.toByteArray()))
|
||||||
|
.setZ(ByteString.copyFrom(z.toByteArray()))
|
||||||
|
.setZTag(ByteString.copyFrom(zTag.toByteArray()))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,95 @@
|
||||||
package meerkat.mixer.verifier;
|
package meerkat.mixer.verifier;
|
||||||
|
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import meerkat.mixer.prover.ElGamalProofOrganizer;
|
||||||
|
import meerkat.mixer.prover.Prover;
|
||||||
|
import org.factcenter.qilin.primitives.RandomOracle;
|
||||||
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* implements Mix2ZeroKnowledgeVerifier
|
||||||
*/
|
*/
|
||||||
public class Verifier {
|
public class Verifier implements Mix2ZeroKnowledgeVerifier {
|
||||||
|
|
||||||
|
|
||||||
|
private final ECGroup group;
|
||||||
|
private final RandomOracle randomOracle;
|
||||||
|
private final ECPoint g,h;
|
||||||
|
private final ElGamalProofOrganizer organizer;
|
||||||
|
private final ZeroKnowledgeOrProofParser parser;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param encryptor should be as the encryptor used by meerkat.mixer.prover
|
||||||
|
* @param randomOracle should be as the random oracle used by meerkat.mixer.prover
|
||||||
|
*/
|
||||||
|
public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) {
|
||||||
|
this.group = encryptor.getGroup();
|
||||||
|
this.g = group.getGenerator();
|
||||||
|
this.h = encryptor.getElGamalPK().getPK();
|
||||||
|
this.randomOracle = randomOracle;
|
||||||
|
this.organizer = new ElGamalProofOrganizer(group,g,h);
|
||||||
|
this.parser = new ZeroKnowledgeOrProofParser(group);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* verify zero knowledge proof
|
||||||
|
* @param in1
|
||||||
|
* @param in2
|
||||||
|
* @param out1
|
||||||
|
* @param out2
|
||||||
|
* @param proof out1 = rerandomize(in1) && out2 = rerandomize(in2)
|
||||||
|
* ||
|
||||||
|
* out1 = rerandomize(in2) && out2 = rerandomize(in1)
|
||||||
|
* @return true iff all 4 or proofs are valid
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
public boolean verify(Crypto.RerandomizableEncryptedMessage in1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage in2,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out1,
|
||||||
|
Crypto.RerandomizableEncryptedMessage out2,
|
||||||
|
Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException {
|
||||||
|
ElGamalProofOrganizer.ElGamalProofInput input = organizer.createProofInput(in1,in2,out1,out2);
|
||||||
|
return verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.first), proof.getFirst())&&
|
||||||
|
verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.second), proof.getSecond())&&
|
||||||
|
verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.third), proof.getThird())&&
|
||||||
|
verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.fourth), proof.getFourth());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param orProofInput
|
||||||
|
* @param orProof
|
||||||
|
* @return verify single or proof
|
||||||
|
*/
|
||||||
|
private boolean verifyElGamaOrProof(ElGamalProofOrganizer.OrProofInput orProofInput,
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof orProof) {
|
||||||
|
ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof);
|
||||||
|
return container.g1.equals(orProofInput.g1) &&
|
||||||
|
container.h1.equals(orProofInput.h1) &&
|
||||||
|
container.g2.equals(orProofInput.g2) &&
|
||||||
|
container.h2.equals(orProofInput.h2) &&
|
||||||
|
container.g1Tag.equals(orProofInput.g1Tag) &&
|
||||||
|
container.h1Tag.equals(orProofInput.h1Tag) &&
|
||||||
|
container.g2Tag.equals(orProofInput.g2Tag) &&
|
||||||
|
container.h2Tag.equals(orProofInput.h2Tag) &&
|
||||||
|
container.c1.add(container.c2).mod(group.orderUpperBound())
|
||||||
|
.equals(Prover.hash(container.forRandomOracle,randomOracle).mod(group.orderUpperBound())) &&
|
||||||
|
group.multiply(container.g1, container.z)
|
||||||
|
.equals(group.add(container.u, group.multiply(container.h1,container.c1))) &&
|
||||||
|
group.multiply(container.g2, container.z)
|
||||||
|
.equals(group.add(container.v, group.multiply(container.h2,container.c1))) &&
|
||||||
|
group.multiply(container.g1Tag, container.zTag)
|
||||||
|
.equals(group.add(container.uTag, group.multiply(container.h1Tag,container.c2))) &&
|
||||||
|
group.multiply(container.g2Tag, container.zTag)
|
||||||
|
.equals(group.add(container.vTag, group.multiply(container.h2Tag,container.c2)));
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,91 @@
|
||||||
package meerkat.mixer.verifier;
|
package meerkat.mixer.verifier;
|
||||||
|
|
||||||
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.crypto.mixnet.MixerOutput;
|
||||||
|
import meerkat.protobuf.Crypto;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 12/30/2015.
|
||||||
|
* provide one operation - verify meerkat.mixer.mixing output
|
||||||
*/
|
*/
|
||||||
public class VerifyTable {
|
public final class VerifyTable {
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param verifier
|
||||||
|
* @param n
|
||||||
|
* @param mixerOutput
|
||||||
|
* @return true iff the meerkat.mixer.mixing output is valid
|
||||||
|
* @throws InvalidProtocolBufferException
|
||||||
|
*/
|
||||||
|
public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier,int n,MixerOutput mixerOutput)
|
||||||
|
throws InvalidProtocolBufferException {
|
||||||
|
int index1,index2,layer;
|
||||||
|
|
||||||
|
//assert n = 2^k
|
||||||
|
if ( (n &(n-1)) != 0)
|
||||||
|
throw new IllegalArgumentException("n");
|
||||||
|
|
||||||
|
int layers = 2*(int)(Math.log(n) / Math.log(2)) - 1;
|
||||||
|
//initialize locationChecksum table
|
||||||
|
// use for check BeneshNet validity
|
||||||
|
boolean[][] locationChecksum = new boolean[layers][n];
|
||||||
|
for (boolean[] locationChecksumLayer: locationChecksum) {
|
||||||
|
Arrays.fill(locationChecksumLayer,false);
|
||||||
|
}
|
||||||
|
|
||||||
|
Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.getProofs();
|
||||||
|
Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.getEncryptedMessages();
|
||||||
|
|
||||||
|
for (int i = 0; i < zeroKnowledgeProofs.length ; i++){
|
||||||
|
for (int j = 0; j < zeroKnowledgeProofs[i].length ; j ++){
|
||||||
|
Mixing.ZeroKnowledgeProof zkp = zeroKnowledgeProofs[i][j];
|
||||||
|
Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation();
|
||||||
|
index1 = location.getI();
|
||||||
|
index2 = location.getJ();
|
||||||
|
layer = location.getLayer();
|
||||||
|
|
||||||
|
// check location validity
|
||||||
|
if (layer > layers >> 1) {
|
||||||
|
if (index2 - index1 != n >> (layers - layer))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
if (index2 - index1 != n >> (layer + 1))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// mark location in table
|
||||||
|
locationChecksum[layer][index1] = true;
|
||||||
|
locationChecksum[layer][index2] = true;
|
||||||
|
|
||||||
|
// verify proof
|
||||||
|
if(!verifier.verify(rerandomizableEncryptedMessages[layer][index1],
|
||||||
|
rerandomizableEncryptedMessages[layer][index2],
|
||||||
|
rerandomizableEncryptedMessages[layer + 1][index1],
|
||||||
|
rerandomizableEncryptedMessages[layer + 1][index2],
|
||||||
|
zkp)) {
|
||||||
|
|
||||||
|
verifier.verify(rerandomizableEncryptedMessages[layer][index1],
|
||||||
|
rerandomizableEncryptedMessages[layer][index2],
|
||||||
|
rerandomizableEncryptedMessages[layer + 1][index1],
|
||||||
|
rerandomizableEncryptedMessages[layer + 1][index2],
|
||||||
|
zkp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// verify all meerkat.mixer.necessary locations for BeneshNet were proved
|
||||||
|
for (boolean[] checksumLayer: locationChecksum) {
|
||||||
|
for (boolean locationBoolean: checksumLayer) {
|
||||||
|
if (!locationBoolean)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,95 @@
|
||||||
package meerkat.mixer.verifier;
|
package meerkat.mixer.verifier;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.protobuf.Mixing;
|
||||||
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Created by Tzlil on 4/16/2016.
|
* Created by Tzlil on 1/25/2016.
|
||||||
|
* zero knowledge proof parser
|
||||||
*/
|
*/
|
||||||
public class ZeroKnowledgeOrProofParser {
|
public class ZeroKnowledgeOrProofParser {
|
||||||
|
|
||||||
|
private final ECGroup group;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* parse or proof message and return the result in zero knowledge or proof container
|
||||||
|
* @param orProof
|
||||||
|
* @return zero knowledge or proof container
|
||||||
|
*/
|
||||||
|
public ZeroKnowledgeOrProofContainer parseOrProof(Mixing.ZeroKnowledgeProof.OrProof orProof){
|
||||||
|
return new ZeroKnowledgeOrProofContainer(orProof);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* getter
|
||||||
|
* @param group
|
||||||
|
*/
|
||||||
|
public ZeroKnowledgeOrProofParser(ECGroup group) {
|
||||||
|
this.group = group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* convert ByteString to ECPoint
|
||||||
|
* @param bs
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
public ECPoint convert2ECPoint(ByteString bs){
|
||||||
|
return group.decode(bs.toByteArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* inner class
|
||||||
|
* container for parsed zero knowledge or proof
|
||||||
|
* constructor is private, can be construct using ZeroKnowledgeOrProofParser.parseOrProof
|
||||||
|
*/
|
||||||
|
public class ZeroKnowledgeOrProofContainer{
|
||||||
|
public final ECPoint g1,g2,h1,h2;
|
||||||
|
public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag;
|
||||||
|
public final ECPoint u,v,uTag,vTag;
|
||||||
|
public final BigInteger c1,c2,z,zTag;
|
||||||
|
public final Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* constructor
|
||||||
|
* @param orProof
|
||||||
|
*/
|
||||||
|
private ZeroKnowledgeOrProofContainer(Mixing.ZeroKnowledgeProof.OrProof orProof){
|
||||||
|
this.forRandomOracle =
|
||||||
|
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder()
|
||||||
|
.setG1(orProof.getG1())
|
||||||
|
.setH1(orProof.getH1())
|
||||||
|
.setG2(orProof.getG2())
|
||||||
|
.setH2(orProof.getH2())
|
||||||
|
.setG1Tag(orProof.getG1Tag())
|
||||||
|
.setH1Tag(orProof.getH1Tag())
|
||||||
|
.setG2Tag(orProof.getG2Tag())
|
||||||
|
.setH2Tag(orProof.getH2Tag())
|
||||||
|
.setU(orProof.getU())
|
||||||
|
.setV(orProof.getV())
|
||||||
|
.setUTag(orProof.getUTag())
|
||||||
|
.setVTag(orProof.getVTag())
|
||||||
|
.build();
|
||||||
|
this.g1 = convert2ECPoint(orProof.getG1());
|
||||||
|
this.g2 = convert2ECPoint(orProof.getG2());
|
||||||
|
this.h1 = convert2ECPoint(orProof.getH1());
|
||||||
|
this.h2 = convert2ECPoint(orProof.getH2());
|
||||||
|
this.g1Tag = convert2ECPoint(orProof.getG1Tag());
|
||||||
|
this.g2Tag = convert2ECPoint(orProof.getG2Tag());
|
||||||
|
this.h1Tag = convert2ECPoint(orProof.getH1Tag());
|
||||||
|
this.h2Tag = convert2ECPoint(orProof.getH2Tag());
|
||||||
|
this.u = convert2ECPoint(orProof.getU());
|
||||||
|
this.v = convert2ECPoint(orProof.getV());
|
||||||
|
this.uTag = convert2ECPoint(orProof.getUTag());
|
||||||
|
this.vTag = convert2ECPoint(orProof.getVTag());
|
||||||
|
this.c1 = new BigInteger(orProof.getC1().toByteArray());
|
||||||
|
this.c2 = new BigInteger(orProof.getC2().toByteArray());
|
||||||
|
this.z = new BigInteger(orProof.getZ().toByteArray());
|
||||||
|
this.zTag = new BigInteger(orProof.getZTag().toByteArray());
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,18 @@ package meerkat.mixer;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.mixer.mixing.Mixer;
|
||||||
|
import meerkat.mixer.mixing.MixerOutput;
|
||||||
|
import meerkat.mixer.prover.Prover;
|
||||||
|
import meerkat.mixer.verifier.Verifier;
|
||||||
|
import meerkat.mixer.verifier.VerifyTable;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
import mixer.Mixer;
|
|
||||||
import mixer.MixerOutput;
|
|
||||||
import mixer.Utils;
|
|
||||||
import org.factcenter.qilin.primitives.RandomOracle;
|
import org.factcenter.qilin.primitives.RandomOracle;
|
||||||
import org.factcenter.qilin.primitives.concrete.DigestOracle;
|
import org.factcenter.qilin.primitives.concrete.DigestOracle;
|
||||||
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.junit.Before;
|
import org.junit.Before;
|
||||||
import prover.Prover;
|
|
||||||
import verifier.Verifier;
|
|
||||||
import verifier.VerifyTable;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
|
@ -52,7 +51,7 @@ public class CreateTestVector {
|
||||||
randomOracle = new DigestOracle();
|
randomOracle = new DigestOracle();
|
||||||
verifier = new Verifier(encryptor,randomOracle);
|
verifier = new Verifier(encryptor,randomOracle);
|
||||||
prover = new Prover(randomProver,encryptor,randomOracle);
|
prover = new Prover(randomProver,encryptor,randomOracle);
|
||||||
mixer = new Mixer(randomMixer,prover,encryptor,verifier);
|
mixer = new Mixer(prover,encryptor);
|
||||||
|
|
||||||
// generate n
|
// generate n
|
||||||
int logN = 10; // + random.nextInt(8)
|
int logN = 10; // + random.nextInt(8)
|
||||||
|
@ -74,11 +73,11 @@ public class CreateTestVector {
|
||||||
|
|
||||||
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
|
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
|
||||||
System.out.println("start mixing");
|
System.out.println("start mixing");
|
||||||
MixerOutput mixerOutput = new MixerOutput(mixer.mix(mixerInput));
|
MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer);
|
||||||
System.out.println("mixing ended, start verification");
|
System.out.println("mixing ended, start verification");
|
||||||
assert (VerifyTable.verifyTable(verifier,n,mixerOutput));
|
assert (VerifyTable.verifyTable(verifier,n,mixerOutput));
|
||||||
System.out.println("verification ended, start printing");
|
System.out.println("verification ended, start printing");
|
||||||
mixerOutput.outToFile("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3");
|
mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3");
|
||||||
System.out.println("all done");
|
System.out.println("all done");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,11 +90,11 @@ public class CreateTestVector {
|
||||||
|
|
||||||
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
|
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
|
||||||
System.out.println("start mixing");
|
System.out.println("start mixing");
|
||||||
MixerOutput mixerOutput = new MixerOutput(mixer.mix(mixerInput));
|
MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random);
|
||||||
System.out.println("mixing ended, start negative verification");
|
System.out.println("mixing ended, start negative verification");
|
||||||
assert (!VerifyTable.verifyTable(verifier,n,mixerOutput));
|
assert (!VerifyTable.verifyTable(verifier,n,mixerOutput));
|
||||||
System.out.println("verification ended, start printing");
|
System.out.println("verification ended, start printing");
|
||||||
mixerOutput.outToFile("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5");
|
mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5");
|
||||||
System.out.println("all done");
|
System.out.println("all done");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,6 +4,9 @@ package meerkat.mixer;
|
||||||
* Created by Tzlil on 12/17/2015.
|
* Created by Tzlil on 12/17/2015.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
import meerkat.mixer.mixing.MixNetwork;
|
||||||
|
import meerkat.mixer.mixing.RandomPermutation;
|
||||||
|
import meerkat.mixer.mixing.Switch;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
|
@ -7,6 +7,10 @@ package meerkat.mixer;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.mixer.mixing.Mixer;
|
||||||
|
import meerkat.mixer.prover.Prover;
|
||||||
|
import meerkat.mixer.verifier.Verifier;
|
||||||
|
import meerkat.mixer.verifier.VerifyTable;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
import org.factcenter.qilin.primitives.RandomOracle;
|
import org.factcenter.qilin.primitives.RandomOracle;
|
||||||
|
@ -15,9 +19,6 @@ import org.factcenter.qilin.primitives.concrete.ECElGamal;
|
||||||
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import prover.Prover;
|
|
||||||
import verifier.Verifier;
|
|
||||||
import verifier.VerifyTable;
|
|
||||||
|
|
||||||
import java.security.spec.InvalidKeySpecException;
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -49,7 +50,7 @@ public class MixingTest {
|
||||||
randomOracle = new DigestOracle();
|
randomOracle = new DigestOracle();
|
||||||
verifier = new Verifier(encryptor,randomOracle);
|
verifier = new Verifier(encryptor,randomOracle);
|
||||||
prover = new Prover(randomProver,encryptor,randomOracle);
|
prover = new Prover(randomProver,encryptor,randomOracle);
|
||||||
mixer = new Mixer(randomMixer,prover,encryptor);
|
mixer = new Mixer(prover,encryptor);
|
||||||
|
|
||||||
// generate n
|
// generate n
|
||||||
int logN = 8; // + random.nextInt(8)
|
int logN = 8; // + random.nextInt(8)
|
||||||
|
@ -75,7 +76,7 @@ public class MixingTest {
|
||||||
System.out.println(" start mixing");
|
System.out.println(" start mixing");
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
|
|
||||||
meerkat.crypto.mixnet.MixerOutput mixerOutput = mixer.mix(mixerInput);
|
meerkat.crypto.mixnet.MixerOutput mixerOutput = mixer.mix(mixerInput,randomMixer);
|
||||||
|
|
||||||
long finishTime = System.currentTimeMillis();
|
long finishTime = System.currentTimeMillis();
|
||||||
System.out.println(" that took: "+(finishTime-startTime)+ " ms");
|
System.out.println(" that took: "+(finishTime-startTime)+ " ms");
|
||||||
|
|
|
@ -5,6 +5,8 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
|
||||||
|
import meerkat.mixer.prover.Prover;
|
||||||
|
import meerkat.mixer.verifier.Verifier;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Crypto;
|
import meerkat.protobuf.Crypto;
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
|
@ -15,8 +17,6 @@ import org.factcenter.qilin.primitives.concrete.ECElGamal;
|
||||||
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
import org.factcenter.qilin.primitives.concrete.ECGroup;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import prover.Prover;
|
|
||||||
import verifier.Verifier;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
|
@ -3,7 +3,7 @@ package profiling.BigInteger;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package profiling.BigInteger;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package profiling.BigInteger;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,7 @@ package profiling.BigInteger;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.protobuf.ConcreteCrypto;
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Voting;
|
import meerkat.protobuf.Voting;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
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;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
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 mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ package profiling.ECGroup;
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
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;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package profiling.ECGroup;
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
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;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package profiling.ECGroup;
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
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;
|
||||||
|
|
|
@ -2,7 +2,7 @@ package profiling.ECGroup;
|
||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
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;
|
||||||
|
|
|
@ -5,7 +5,7 @@ import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
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 mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
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;
|
||||||
|
|
||||||
|
|
|
@ -4,16 +4,16 @@ import com.google.protobuf.ByteString;
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
import meerkat.crypto.concrete.ECElGamalEncryption;
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
|
||||||
|
import meerkat.mixer.prover.Prover;
|
||||||
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 mixer.Utils;
|
import meerkat.mixer.Utils;
|
||||||
import org.bouncycastle.math.ec.ECPoint;
|
import org.bouncycastle.math.ec.ECPoint;
|
||||||
import org.factcenter.qilin.primitives.RandomOracle;
|
import org.factcenter.qilin.primitives.RandomOracle;
|
||||||
import org.factcenter.qilin.primitives.concrete.DigestOracle;
|
import org.factcenter.qilin.primitives.concrete.DigestOracle;
|
||||||
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 prover.Prover;
|
|
||||||
|
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
Loading…
Reference in New Issue