Refactoring (tests currently fail)

mixer
Tal Moran 2017-01-19 11:08:07 +02:00
parent 78f823f31e
commit fc2c26d7e9
34 changed files with 584 additions and 1035 deletions

View File

@ -1,20 +0,0 @@
package meerkat.crypto.mixnet;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
/**
* Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts.
*/
public interface Mix2ZeroKnowledgeProver {
public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
boolean switched,int i,int j, int layer, // switch info
Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException;
}

View File

@ -0,0 +1,20 @@
package meerkat.crypto.mixnet;
import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
/**
* Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts.
*/
public interface Mix2ZeroKnowledgeProver {
public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1,
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx, // switch info
Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException;
}

View File

@ -9,5 +9,6 @@ import meerkat.protobuf.Mixing;
public interface MixerOutput { public interface MixerOutput {
public Mixing.Mix2Proof[][] getProofs(); public Mixing.Mix2Proof[][] getProofs();
public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages(); public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages();
public int getN(); public int getLogN();
public int getNumLayers();
} }

View File

@ -15,37 +15,6 @@ import java.util.List;
* provide convert operation from batch data to meerkat.mixer.mixing output and backwards * provide convert operation from batch data to meerkat.mixer.mixing output and backwards
*/ */
public class BatchConverter { 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 * convert meerkat.mixer.mixing output to batch data
* @param mixerOutput * @param mixerOutput
@ -55,8 +24,13 @@ public class BatchConverter {
List<BulletinBoardAPI.BatchChunk> result = new ArrayList<BulletinBoardAPI.BatchChunk>(); List<BulletinBoardAPI.BatchChunk> result = new ArrayList<BulletinBoardAPI.BatchChunk>();
Mixing.MixBatchHeader header = Mixing.MixBatchHeader.newBuilder()
.setLogN(mixerOutput.getLogN())
.setLayers(mixerOutput.getNumLayers())
.build();
result.add(BulletinBoardAPI.BatchChunk.newBuilder() result.add(BulletinBoardAPI.BatchChunk.newBuilder()
.setData(Integer2ByteString(n)) .setData(header.toByteString())
.build()); .build());
for (Mixing.Mix2Proof[] zkpLayer : mixerOutput.getProofs()) { for (Mixing.Mix2Proof[] zkpLayer : mixerOutput.getProofs()) {
@ -85,10 +59,11 @@ public class BatchConverter {
public MixerOutput BatchChunkList2MixerOutput public MixerOutput BatchChunkList2MixerOutput
(List<BulletinBoardAPI.BatchChunk> batchChunkList) throws Exception { (List<BulletinBoardAPI.BatchChunk> batchChunkList) throws Exception {
if (n != ByteString2Integer(batchChunkList.remove(0).getData())){ Mixing.MixBatchHeader header = Mixing.MixBatchHeader.parseFrom(batchChunkList.remove(0).getData());
throw new Exception();
}
int logN = header.getLogN();
int n = 1 << logN;
int layers = header.getLayers();
int nDiv2 = n >>1; int nDiv2 = n >>1;
Mixing.Mix2Proof[][] proofs = new Mixing.Mix2Proof[layers][nDiv2]; Mixing.Mix2Proof[][] proofs = new Mixing.Mix2Proof[layers][nDiv2];
for (int layer = 0; layer < layers; layer++) for (int layer = 0; layer < layers; layer++)
@ -110,7 +85,7 @@ public class BatchConverter {
} }
} }
return new meerkat.mixer.mixing.MixerOutput(n,layers,proofs,encryptions); return new meerkat.mixer.mixing.MixerOutput(logN, proofs,encryptions);
} }

View File

@ -21,19 +21,14 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
private Throwable t; private Throwable t;
private CompleteBatch msg; private CompleteBatch msg;
private final int n, layers;
private final Mix2ZeroKnowledgeVerifier verifier; private final Mix2ZeroKnowledgeVerifier verifier;
/** /**
* constructor * constructor
* @param n
* @param layers
* @param verifier * @param verifier
*/ */
public BatchHandler(int n, int layers, Mix2ZeroKnowledgeVerifier verifier) { public BatchHandler(Mix2ZeroKnowledgeVerifier verifier) {
this.mixerOutput = null; this.mixerOutput = null;
this.n = n;
this.layers = layers;
this.msgReceived = false; this.msgReceived = false;
this.t = null; this.t = null;
this.verifier = verifier; this.verifier = verifier;
@ -70,7 +65,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
* @throws Exception * @throws Exception
*/ */
private void convertMessage() throws Exception { private void convertMessage() throws Exception {
BatchConverter batchConverter = new BatchConverter(n,layers); BatchConverter batchConverter = new BatchConverter();
this.mixerOutput = batchConverter.BatchChunkList2MixerOutput(msg.getBatchChunkList()); this.mixerOutput = batchConverter.BatchChunkList2MixerOutput(msg.getBatchChunkList());
} }
@ -83,7 +78,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
if (mixerOutput == null) { if (mixerOutput == null) {
convertMessage(); convertMessage();
} }
return VerifyTable.verifyTable(verifier, n, mixerOutput); return VerifyTable.verifyTable(verifier, mixerOutput);
} }
/** /**
@ -98,7 +93,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
if(!verifyTable()){ if(!verifyTable()){
throw new Exception("in valid table"); throw new Exception("in valid table");
} }
return Arrays.asList(mixerOutput.getEncryptedMessages()[layers]);//there are layers + 1 return Arrays.asList(mixerOutput.getEncryptedMessages()[mixerOutput.getNumLayers()]);//there are layers + 1
} }
} }

View File

@ -5,7 +5,6 @@ import meerkat.crypto.mixnet.Mixer;
import meerkat.crypto.mixnet.MixerOutput; import meerkat.crypto.mixnet.MixerOutput;
import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.BulletinBoardAPI;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.mixer.mixing.MixNetwork;
import meerkat.mixer.necessary.AsyncBulletinBoardClient; import meerkat.mixer.necessary.AsyncBulletinBoardClient;
@ -26,7 +25,6 @@ public class MainMixing {
private final Mixer mixer; private final Mixer mixer;
private final Mix2ZeroKnowledgeVerifier verifier; private final Mix2ZeroKnowledgeVerifier verifier;
private final int n, layers;
private final AsyncBulletinBoardClient asyncBulletinBoardClient; private final AsyncBulletinBoardClient asyncBulletinBoardClient;
private final byte[] id; private final byte[] id;
@ -35,16 +33,13 @@ public class MainMixing {
* constructor * constructor
* @param mixer * @param mixer
* @param verifier * @param verifier
* @param n
* @param asyncBulletinBoardClient * @param asyncBulletinBoardClient
* @param id * @param id
*/ */
public MainMixing(Mixer mixer, Mix2ZeroKnowledgeVerifier verifier, int n public MainMixing(Mixer mixer, Mix2ZeroKnowledgeVerifier verifier,
, AsyncBulletinBoardClient asyncBulletinBoardClient, byte[] id) { AsyncBulletinBoardClient asyncBulletinBoardClient, byte[] id) {
this.mixer = mixer; this.mixer = mixer;
this.verifier = verifier; this.verifier = verifier;
this.n = n;
this.layers = MixNetwork.numberOfLayers(n);
this.asyncBulletinBoardClient = asyncBulletinBoardClient; this.asyncBulletinBoardClient = asyncBulletinBoardClient;
this.id = id; this.id = id;
} }
@ -64,7 +59,7 @@ public class MainMixing {
List<BatchHandler> batchHandlers = new ArrayList<BatchHandler>(prevBatchIds.size()); List<BatchHandler> batchHandlers = new ArrayList<BatchHandler>(prevBatchIds.size());
BatchHandler currentBatchHandler; BatchHandler currentBatchHandler;
for (Integer prevBatchId : prevBatchIds) { for (Integer prevBatchId : prevBatchIds) {
currentBatchHandler = new BatchHandler(n, layers,verifier); currentBatchHandler = new BatchHandler(verifier);
asyncBulletinBoardClient.readBatch(id, prevBatchId,currentBatchHandler); asyncBulletinBoardClient.readBatch(id, prevBatchId,currentBatchHandler);
batchHandlers.add(currentBatchHandler); batchHandlers.add(currentBatchHandler);
} }
@ -99,7 +94,7 @@ public class MainMixing {
private void updateBB(MixerOutput mixerOutput private void updateBB(MixerOutput mixerOutput
, int batchId, AsyncBulletinBoardClient.ClientCallback<?> callback) { , int batchId, AsyncBulletinBoardClient.ClientCallback<?> callback) {
BatchConverter batchConverter = new BatchConverter(n,layers); BatchConverter batchConverter = new BatchConverter();
List<BulletinBoardAPI.BatchChunk> batchChunkList = batchConverter.MixerOutput2BatchChunk(mixerOutput); List<BulletinBoardAPI.BatchChunk> batchChunkList = batchConverter.MixerOutput2BatchChunk(mixerOutput);
asyncBulletinBoardClient.postBatch(id, batchId, batchChunkList, callback); asyncBulletinBoardClient.postBatch(id, batchId, batchChunkList, callback);
} }

View File

@ -1,214 +0,0 @@
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 12/15/2015.
* contains benes mix network.
* the network is generated in the constructor and can't be change
*/
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;
}
}
}
}

View File

@ -80,89 +80,96 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
/** /**
* generate new random mix network * generate new random mix network
* @param n number of votes * @param logN log number of votes
* @param random * @param random
* @return new random mix network * @return new random mix network
*/ */
private MixNetwork generateMixNetwork(int n,Random random){ private PermutationNetwork generateMixNetwork(int logN, Random random){
return new MixNetwork(new RandomPermutation(n,random)); BenesNetwork net = new BenesNetwork(logN);
RandomPermutation perm = new RandomPermutation(1 << logN, random);
net.setPermutation(perm.permutation);
return net;
} }
/** /**
* fills the encryption table with rerandomize encrypted votes. * fills the encryption table with rerandomized encrypted votes.
* @param layers
* @param mixNetwork switches table (boolean values) * @param mixNetwork switches table (boolean values)
* @param encryptionTable an initialized encryption table s.t first layer == given encrypted votes * @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 * @param randomnesses an initialized randomness table of size layers * n, use for rerandomize operations
* @throws InvalidProtocolBufferException * @throws InvalidProtocolBufferException
*/ */
private void rerandomize(int layers,MixNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable private void rerandomize(PermutationNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable
,EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { ,EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException {
Switch[] switchesLayer; Switch[] switchesLayer;
int index1,index2; int index1,index2;
RerandomizableEncryptedMessage e1,e2; RerandomizableEncryptedMessage a,b;
EncryptionRandomness r1,r2; EncryptionRandomness r1,r2;
for (int layer = 0; layer < layers; layer++) int layers = mixNetwork.getNumLayers();
{
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]; int numSwitches = mixNetwork.getNumInputs() >>> 1;
r2 = randomnesses[layer][index2];
if (!sw.value) {
encryptionTable[layer + 1][index1] = encryptor.rerandomize(e1, r1);
encryptionTable[layer + 1][index2] = encryptor.rerandomize(e2, r2);
for (int layer = 0; layer < layers; layer++) {
for (int switchIdx = 0; switchIdx < numSwitches; ++switchIdx) {
boolean isCrossed = mixNetwork.isCrossed(layer, switchIdx);
int out0 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx);
int out1 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx + 1);
r1 = randomnesses[layer][2 * switchIdx];
r2 = randomnesses[layer][2 * switchIdx + 1];
a = encryptionTable[layer][2 * switchIdx];
b = encryptionTable[layer][2 * switchIdx + 1];
if (isCrossed) {
encryptionTable[layer + 1][out0] = encryptor.rerandomize(b, r2);
encryptionTable[layer + 1][out1] = encryptor.rerandomize(a, r1);
} else { } else {
encryptionTable[layer + 1][index1] = encryptor.rerandomize(e2, r2); encryptionTable[layer + 1][out0] = encryptor.rerandomize(a, r1);
encryptionTable[layer + 1][index2] = encryptor.rerandomize(e1, r1); encryptionTable[layer + 1][out1] = encryptor.rerandomize(b, r2);
} }
} }
} }
} }
/** /**
* generate zero knowledge proof for each rerandomize encrypted votes couple in encryptionTable * 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 mixNetwork switches table (boolean values) used for set encryption table
* @param encryptionTable full encryption table * @param encryptionTable full encryption table
* @param randomnesses randomness table of size layers * n, used for set encryption table * @param randomnesses randomness table of size layers * n, used for set encryption table
* @return zero knowledge proofs table * @return zero knowledge proofs table
* @throws InvalidProtocolBufferException * @throws InvalidProtocolBufferException
*/ */
private Mix2Proof[][] generateMix2ProofTable(int n, int layers, MixNetwork mixNetwork private Mix2Proof[][] generateMix2ProofTable(PermutationNetwork mixNetwork
, RerandomizableEncryptedMessage[][] encryptionTable , RerandomizableEncryptedMessage[][] encryptionTable
, EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { , EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException {
int layers = mixNetwork.getNumLayers();
int n = mixNetwork.getNumInputs();
Switch[] switchesLayer; Switch[] switchesLayer;
int index1,index2; int index1,index2;
int switchIndex = 0; int switchIndex = 0;
int nDiv2 = n >> 1; int numSwitches = n >> 1;
Mix2Proof[][] proofsTable = new Mix2Proof[layers][nDiv2]; Mix2Proof[][] proofsTable = new Mix2Proof[layers][numSwitches];
RerandomizableEncryptedMessage e1,e2; RerandomizableEncryptedMessage a,b,c,d;
EncryptionRandomness r1,r2; EncryptionRandomness r1,r2;
for (int layer = 0; layer < layers; layer++) for (int layer = 0; layer < layers; layer++) {
{ for (int switchIdx = 0; switchIdx < numSwitches; ++switchIdx) {
switchesLayer = mixNetwork.getSwitchesByLayer(layer); boolean isCrossed = mixNetwork.isCrossed(layer, switchIdx);
for (Switch sw : switchesLayer) { int out0 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx);
index1 = sw.i; int out1 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx + 1);
index2 = sw.j;
e1 = encryptionTable[layer][index1]; a = encryptionTable[layer][2 * switchIdx];
e2 = encryptionTable[layer][index2]; b = encryptionTable[layer][2 * switchIdx + 1];
r1 = randomnesses[layer][index1]; c = encryptionTable[layer + 1][out0];
r2 = randomnesses[layer][index2]; d = encryptionTable[layer + 1][out1];
r1 = randomnesses[layer][2 * switchIdx];
r2 = randomnesses[layer][2 * switchIdx + 1];
proofsTable[layer][switchIndex] = proofsTable[layer][switchIndex] =
prover.prove(e1, e2, encryptionTable[layer + 1][index1], prover.prove(a, b, c, d, isCrossed, layer, switchIdx, out0, out1, r1, r2);
encryptionTable[layer + 1][index2],
sw.value, sw.i, sw.j, sw.layer, r1, r2);
switchIndex = (switchIndex + 1) % nDiv2;
} }
} }
return proofsTable; return proofsTable;
@ -180,14 +187,18 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
int n = ciphertexts.size(); int n = ciphertexts.size();
assert (n > 1 && isPowerOfTwo(n)); assert (n > 1 && isPowerOfTwo(n));
int layers = MixNetwork.numberOfLayers(n); // layers = 2logn -1 int logN = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 1;
PermutationNetwork net = generateMixNetwork(logN,random);
int layers = net.getNumLayers();
RerandomizableEncryptedMessage[][] encryptionTable = initializeEncryptionTable(n,layers,ciphertexts); RerandomizableEncryptedMessage[][] encryptionTable = initializeEncryptionTable(n,layers,ciphertexts);
EncryptionRandomness[][] randomnesses = generateRandomnessesForRerandomize(n,layers,random); EncryptionRandomness[][] randomnesses = generateRandomnessesForRerandomize(n,layers,random);
MixNetwork mixNetwork = generateMixNetwork(n,random);
rerandomize(layers,mixNetwork,encryptionTable,randomnesses);
Mix2Proof[][] proofsTable = generateMix2ProofTable(n,layers,mixNetwork,encryptionTable,randomnesses);
return new meerkat.mixer.mixing.MixerOutput(n,layers,proofsTable, encryptionTable); rerandomize(net,encryptionTable,randomnesses);
Mix2Proof[][] proofsTable = generateMix2ProofTable(net,encryptionTable,randomnesses);
return new meerkat.mixer.mixing.MixerOutput(logN, proofsTable, encryptionTable);
} }
} }

View File

@ -16,23 +16,20 @@ import java.io.IOException;
public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput { public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput {
private final Mixing.Mix2Proof[][] proofs; private final Mixing.Mix2Proof[][] proofs;
private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages; private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages;
private final int n; private final int logN;
private final int layers;
/** /**
* constructor * constructor
* @param n number of votes * @param logN log (base 2) of the number of votes
* @param layers
* @param encryptedMessages at level 0 , contains the original encrypted votes * @param encryptedMessages at level 0 , contains the original encrypted votes
* at each other level contains the re encrypted votes * at each other level contains the re encrypted votes
* @param proofs in each cell (level,switch) contains the match zero knowledge proof * @param proofs in each cell (level,switch) contains the match zero knowledge proof
*/ */
public MixerOutput(int n,int layers,Mixing.Mix2Proof[][] proofs public MixerOutput(int logN, Mixing.Mix2Proof[][] proofs
, Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) { , Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) {
this.proofs = proofs; this.proofs = proofs;
this.encryptedMessages = encryptedMessages; this.encryptedMessages = encryptedMessages;
this.n = n; this.logN = logN;
this.layers = layers;
} }
@ -48,8 +45,13 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{
} }
@Override @Override
public int getN() { public int getLogN() {
return n; return logN;
}
@Override
public int getNumLayers() {
return 2 * logN - 1;
} }
/** /**
@ -57,33 +59,33 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{
* @param dir - directory * @param dir - directory
* @throws IOException * @throws IOException
*/ */
public void outToFolder(String dir) throws IOException { // public void outToFolder(String dir) throws IOException {
//
(new File(dir)).mkdirs(); // (new File(dir)).mkdirs();
//create files // //create files
String proofsDir = dir + "/Proofs"; // String proofsDir = dir + "/Proofs";
String encDir = dir + "/EncryptedMessages"; // String encDir = dir + "/EncryptedMessages";
(new File(proofsDir)).mkdir(); // (new File(proofsDir)).mkdir();
(new File(encDir)).mkdir(); // (new File(encDir)).mkdir();
for (int layer = 0; layer < layers; layer++){ // for (int layer = 0; layer < layers; layer++){
(new File(proofsDir +"/layer" + layer )).mkdir(); // (new File(proofsDir +"/layer" + layer )).mkdir();
(new File(encDir +"/layer" + layer )).mkdir(); // (new File(encDir +"/layer" + layer )).mkdir();
} // }
(new File(encDir +"/input")).mkdir(); // (new File(encDir +"/input")).mkdir();
//
//
for (int layer = 0; layer < layers; layer++){ // for (int layer = 0; layer < layers; layer++){
for(int i = 0; i < proofs[layer].length; i ++){ // for(int i = 0; i < proofs[layer].length; i ++){
writeProofToFile(proofsDir,proofs[layer][i]); // writeProofToFile(proofsDir,proofs[layer][i]);
} // }
} // }
//
for (int layer = 0; layer <= layers; layer++){ // for (int layer = 0; layer <= layers; layer++){
for(int i = 0; i < encryptedMessages[layer].length; i ++){ // for(int i = 0; i < encryptedMessages[layer].length; i ++){
writeEncToFile(encDir,layer - 1, i,encryptedMessages[layer][i]); // writeEncToFile(encDir,layer - 1, i,encryptedMessages[layer][i]);
} // }
} // }
} // }
/** /**
* create new file contains single proof * create new file contains single proof
@ -91,19 +93,19 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{
* @param proof * @param proof
* @throws IOException * @throws IOException
*/ */
private void writeProofToFile(String proofsDir, Mixing.Mix2Proof proof) throws IOException { // private void writeProofToFile(String proofsDir, Mixing.Mix2Proof proof) throws IOException {
Mixing.Mix2Proof.Location location = proof.getLocation(); // Mixing.Mix2Proof.Location location = proof.getLocation();
int layer = location.getLayer(); // int layer = location.getLayer();
int i = location.getI(); // int i = location.getI();
int j = location.getJ(); // int j = location.getJ();
String fileName = proofsDir+"/layer" + layer +"/" + i +"_" + j; // String fileName = proofsDir+"/layer" + layer +"/" + i +"_" + j;
//
File file = new File(fileName); // File file = new File(fileName);
file.createNewFile(); // file.createNewFile();
FileOutputStream fos = new FileOutputStream(file); // FileOutputStream fos = new FileOutputStream(file);
fos.write(proof.toByteArray()); // fos.write(proof.toByteArray());
fos.close(); // fos.close();
} // }
/** /**
* create new file contains single encrypted message * create new file contains single encrypted message

View File

@ -0,0 +1,39 @@
package meerkat.mixer.proofs;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.protobuf.Mixing;
import java.util.Random;
/**
* Sigma protocol for plaintext equivalence of a pair of ciphertexts.
*/
public class DlogConjunction {
public static class Prover
extends SigmaProtocolAnd2.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement,
ECElGamalMixStatementGenerator.AndStatementWitness witness) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[0], witness.witnesses[0]),
new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[1], witness.witnesses[1]));
}
}
public static class Simulator extends SigmaProtocolAnd2.Simulator {
public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[0]), new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[1]));
}
}
public static class Verifier
extends SigmaProtocolAnd2.Verifier<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.AndStatement statement) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[0]), new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[1]));
}
}
}

View File

@ -1,184 +0,0 @@
package meerkat.mixer.proofs;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.concrete.Util;
import meerkat.protobuf.ConcreteCrypto.GroupElement;
import meerkat.protobuf.Mixing;
import meerkat.protobuf.Mixing.Mix2Proof.AndProof;
import meerkat.protobuf.Mixing.Mix2Proof.DlogProof;
import org.bouncycastle.math.ec.ECPoint;
import org.factcenter.qilin.primitives.concrete.ECGroup;
import java.math.BigInteger;
import java.util.Random;
import static meerkat.protobuf.Mixing.Mix2Proof.DlogProof.*;
/**
* Prover, Simulator and Verifier
*/
public class ECElGamalMixProtocols {
final ECElGamalMixParams params;
final ECGroup group;
final ECElGamalEncryption encryptor;
final ECPoint g;
final ECPoint h;
final Random rand;
final ChallengeGenerator challengeGenerator = new ChallengeGenerator();
public ECElGamalMixProtocols(ECElGamalMixParams params, Random rand) {
this.params = params;
this.rand = rand;
group = params.group;
encryptor = params.encryptor;
g = params.g;
h = params.h;
}
public class ChallengeGenerator implements SigmaProtocolOr2.ChallengeGenerator {
@Override
public BigInteger generateChallenge() { return encryptor.generateRandomExponent(rand); }
@Override
public BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { return c1.subtract(c2).mod(group.orderUpperBound()); }
}
public class DlogStatementSchnorrProver implements SigmaProtocol.Prover<DlogProof.FirstMessage, DlogProof.FinalMessage> {
ECElGamalMixParams.DlogStatement statement;
ECElGamalMixParams.DlogStatementWitness witness;
BigInteger r = null;
public DlogStatementSchnorrProver(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) {
this.statement = statement;
this.witness = witness;
}
@Override
public FirstMessage getFirstMessage() {
r = encryptor.generateRandomExponent(rand);
ECPoint gr = group.multiply(statement.g, r);
ECPoint hr = group.multiply(statement.h, r);
FirstMessage firstMessage = FirstMessage.newBuilder()
.setGr(encryptor.encodeElement(gr))
.setHr(encryptor.encodeElement(hr))
.build();
return firstMessage;
}
@Override
public FinalMessage getFinalMessage(BigInteger challenge) {
return FinalMessage.newBuilder()
.setXcr(Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound())))
.build();
}
@Override
public void reset() { r = null; }
}
public class DlogStatementSchnorrVerifier implements SigmaProtocol.Verifier<DlogProof.FirstMessage, DlogProof.FinalMessage> {
final ECElGamalMixParams.DlogStatement statement;
public DlogStatementSchnorrVerifier(ECElGamalMixParams.DlogStatement statement) {
this.statement = statement;
}
@Override
public boolean verify(FirstMessage firstMessage, BigInteger challenge,
FinalMessage finalMessage) {
GroupElement grEncoded = firstMessage.getGr();
ECPoint gr = encryptor.decodeElement(grEncoded);
GroupElement hrEncoded = firstMessage.getHr();
ECPoint hr = encryptor.decodeElement(hrEncoded);
BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr());
boolean gGood = group.add(gr, group.multiply(statement.a,challenge)).equals(group.multiply(statement.g,xcr));
boolean hGood = group.add(hr, group.multiply(statement.b,challenge)).equals(group.multiply(statement.h,xcr));
return gGood && hGood;
}
}
public class DlogStatementSchnorrSimulator implements SigmaProtocol.Simulator<DlogProof.FirstMessage, DlogProof.FinalMessage> {
ECElGamalMixParams.DlogStatement statement;
BigInteger response = null;
public DlogStatementSchnorrSimulator(ECElGamalMixParams.DlogStatement statement) {
this.statement = statement;
}
@Override
public FirstMessage getFirstMessage(BigInteger challenge) {
response = encryptor.generateRandomExponent(rand);
ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a,challenge));
ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b,challenge));
return FirstMessage.newBuilder()
.setGr(encryptor.encodeElement(u))
.setHr(encryptor.encodeElement(v))
.build();
}
@Override
public FinalMessage getFinalMessage() {
return FinalMessage.newBuilder()
.setXcr(Util.encodeBigInteger(response))
.build();
}
@Override
public void reset() { response = null; }
}
/**
* Prover for plaintext equivalence of a pair of ciphertexts.
*/
public class AndStatementProver
extends SigmaProtocolAnd2.Prover<AndProof.FirstMessage, DlogProof.FirstMessage, AndProof.FinalMessage, DlogProof.FinalMessage> {
public AndStatementProver(ECElGamalMixParams.AndStatement statement,
ECElGamalMixParams.AndStatementWitness witness) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new DlogStatementSchnorrProver(statement.clauses[0], witness.witnesses[0]),
new DlogStatementSchnorrProver(statement.clauses[1], witness.witnesses[1]));
}
}
public class AndStatementVerifier
extends SigmaProtocolAnd2.Verifier<AndProof.FirstMessage, DlogProof.FirstMessage, AndProof.FinalMessage, DlogProof.FinalMessage> {
public AndStatementVerifier(ECElGamalMixParams.AndStatement statement) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
new DlogStatementSchnorrVerifier(statement.clauses[0]), new DlogStatementSchnorrVerifier(statement.clauses[1]));
}
}
public class AndStatementSimulator extends SigmaProtocolAnd2.Simulator {
public AndStatementSimulator(ECElGamalMixParams.AndStatement statement) {
super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
new DlogStatementSchnorrSimulator(statement.clauses[0]), new DlogStatementSchnorrSimulator(statement.clauses[1]));
}
}
public class Mix2Prover extends SigmaProtocolOr2.Prover<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage> {
public Mix2Prover(ECElGamalMixParams.Mix2Statement statement, ECElGamalMixParams.Mix2StatementWitness witness) {
super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator,
new AndStatementProver(statement.clauses[witness.trueClauseIndex], witness.witness),
new AndStatementSimulator(statement.clauses[1 - witness.trueClauseIndex]),
witness.trueClauseIndex);
}
}
public class Mix2Verifier extends SigmaProtocolOr2.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage> {
public Mix2Verifier(ECElGamalMixParams.Mix2Statement statement) {
super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator,
new AndStatementVerifier(statement.clauses[0]), new AndStatementVerifier(statement.clauses[1]));
}
}
}

View File

@ -16,7 +16,7 @@ import java.math.BigInteger;
* *
* both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it
*/ */
public class ECElGamalMixParams { public class ECElGamalMixStatementGenerator {
final ECElGamalEncryption encryptor; final ECElGamalEncryption encryptor;
final ECGroup group; final ECGroup group;
@ -31,7 +31,7 @@ public class ECElGamalMixParams {
* @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and * @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and
* second base (h) are taken from the encryptor (second base is the public key) * second base (h) are taken from the encryptor (second base is the public key)
*/ */
public ECElGamalMixParams(ECElGamalEncryption encryptor){ public ECElGamalMixStatementGenerator(ECElGamalEncryption encryptor){
this.encryptor = encryptor; this.encryptor = encryptor;
this.group = encryptor.getGroup(); this.group = encryptor.getGroup();
this.g = group.getGenerator(); this.g = group.getGenerator();
@ -40,11 +40,6 @@ public class ECElGamalMixParams {
this.hEncoded = encryptor.encodeElement(h); this.hEncoded = encryptor.encodeElement(h);
} }
public enum TrueCouple {
left, right, unknown
}
/** /**
* can be used by anyone, e.g meerkat.mixer.verifier * can be used by anyone, e.g meerkat.mixer.verifier
* *
@ -84,7 +79,7 @@ public class ECElGamalMixParams {
* *
* The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality. * The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality.
* *
* A Mix2Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private) * A Mix2Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixStatementGenerator (all constructors are private)
* *
*/ */
public class Mix2Statement { public class Mix2Statement {
@ -180,9 +175,9 @@ public class ECElGamalMixParams {
DlogStatement(ECPoint a, ECPoint b) { DlogStatement(ECPoint a, ECPoint b) {
this.g = ECElGamalMixParams.this.g; this.g = ECElGamalMixStatementGenerator.this.g;
this.a = a; this.a = a;
this.h = ECElGamalMixParams.this.h; this.h = ECElGamalMixStatementGenerator.this.h;
this.b = b; this.b = b;
} }
} }

View File

@ -0,0 +1,46 @@
package meerkat.mixer.proofs;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.protobuf.Mixing;
import org.factcenter.qilin.primitives.concrete.ECGroup;
import java.math.BigInteger;
import java.util.Random;
/**
* Sigma protocol for proving correctness of a 2x2 switch
*/
public class Mix2 {
public static class ChallengeGenerator implements SigmaProtocolOr2.ChallengeGenerator {
ECElGamalEncryption encryptor;
ECGroup group;
Random rand;
public ChallengeGenerator(ECElGamalEncryption encryptor, Random rand) {
this.encryptor = encryptor;
group = encryptor.getGroup();
}
@Override
public BigInteger generateChallenge() { return encryptor.generateRandomExponent(rand); }
@Override
public BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { return c1.subtract(c2).mod(group.orderUpperBound()); }
}
public static class Prover extends SigmaProtocolOr2.Prover<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage> {
public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.Mix2Statement statement, ECElGamalMixStatementGenerator.Mix2StatementWitness witness) {
super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, rand),
new DlogConjunction.Prover(encryptor, rand, statement.clauses[witness.trueClauseIndex], witness.witness),
new DlogConjunction.Simulator(encryptor, rand, statement.clauses[1 - witness.trueClauseIndex]),
witness.trueClauseIndex);
}
}
public static class Verifier extends SigmaProtocolOr2.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage> {
public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.Mix2Statement statement) {
super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, null),
new DlogConjunction.Verifier(encryptor, statement.clauses[0]), new DlogConjunction.Verifier(encryptor, statement.clauses[1]));
}
}
}

View File

@ -2,7 +2,6 @@ package meerkat.mixer.proofs;
import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.InvalidProtocolBufferException;
import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.concrete.Util;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver;
import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
@ -26,8 +25,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
private final ECElGamalEncryption encryptor; private final ECElGamalEncryption encryptor;
private final ECPoint g,h; private final ECPoint g,h;
private final BigInteger groupOrderUpperBound; private final BigInteger groupOrderUpperBound;
private final ECElGamalMixParams mixParams; private final ECElGamalMixStatementGenerator mixParams;
final ECElGamalMixProtocols mixProtocols;
final SigmaFiatShamir<Mixing.Mix2Proof, Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> mix2NIZK; final SigmaFiatShamir<Mixing.Mix2Proof, Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> mix2NIZK;
/** /**
@ -43,9 +41,8 @@ public class Prover implements Mix2ZeroKnowledgeProver {
this.group = this.encryptor.getGroup(); this.group = this.encryptor.getGroup();
this.g = group.getGenerator(); this.g = group.getGenerator();
this.h = this.encryptor.getElGamalPK().getPK(); this.h = this.encryptor.getElGamalPK().getPK();
this.mixParams = new ECElGamalMixParams(encryptor); this.mixParams = new ECElGamalMixStatementGenerator(encryptor);
this.groupOrderUpperBound = group.orderUpperBound(); this.groupOrderUpperBound = group.orderUpperBound();
this.mixProtocols = new ECElGamalMixProtocols(mixParams, rand); // We don't need randomness for the verifier
this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle);
} }
@ -55,8 +52,6 @@ public class Prover implements Mix2ZeroKnowledgeProver {
* @param c - if switched then c = rerandomize(b,r2) else c = rerandomize(a,r1) * @param c - if switched then c = rerandomize(b,r2) else c = rerandomize(a,r1)
* @param d - if switched then d = rerandomize(a,r1) else d = rerandomize(b,r2) * @param d - if switched then d = rerandomize(a,r1) else d = rerandomize(b,r2)
* @param switched - trueClauseIndex * @param switched - trueClauseIndex
* @param i - column of a and c in encryption table
* @param j - column of b and d in encryption table
* @param layer - row of a,b in encryption table * @param layer - row of a,b in encryption table
* @param r1 * @param r1
* @param r2 * @param r2
@ -67,186 +62,25 @@ public class Prover implements Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage b, Crypto.RerandomizableEncryptedMessage b,
Crypto.RerandomizableEncryptedMessage c, Crypto.RerandomizableEncryptedMessage c,
Crypto.RerandomizableEncryptedMessage d, Crypto.RerandomizableEncryptedMessage d,
boolean switched,int i,int j, int layer, boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx,
Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException {
ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(a,b,c,d); ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(a, b, c, d);
ECElGamalMixParams.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); ECElGamalMixStatementGenerator.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched);
ECElGamalMixProtocols.Mix2Prover prover = mixProtocols.new Mix2Prover(statement, witness); Mix2.Prover prover = new Mix2.Prover(encryptor, rand, statement, witness);
Mixing.Mix2Proof.Location location = Mixing.Mix2Proof.Location.newBuilder() Mixing.Mix2Proof.Location location = Mixing.Mix2Proof.Location.newBuilder()
.setI(i) .setLayer(layer)
.setJ(j) .setSwitchIdx(switchIdx)
.setLayer(layer).build(); .setOut0(out0Idx)
.setOut1(out1Idx)
.build();
return mix2NIZK.generateNizk(prover).toBuilder().setLocation(location).build(); return mix2NIZK.generateNizk(prover).toBuilder().setLocation(location).build();
// Mixing.Mix2Proof first,second,third,fourth;
//
// ECElGamalMixParams.MixStatementWitness statement = mixParams.createProverStatement(a,b,c,d,r1,r2,switched);
//
// first = createOrProof(statement.getDlogStatement(0));
// second = createOrProof(statement.getDlogStatement(1));
// third = createOrProof(statement.getDlogStatement(2));
// fourth = createOrProof(statement.getDlogStatement(3));
//
// 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;
} }
//
//
// Mixing.Mix2Proof.DlogProof.FirstMessage createDlogProof(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) {
//
// BigInteger r = encryptor.generateRandomExponent(rand);
// ECPoint gr = group.multiply(statement.g, r);
// ECPoint hr = group.multiply(statement.h, r);
//
// Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder()
// .setGr(group.encode(gr))
// .setHr(group.encode(hr))
// .build();
//
// BigInteger challenge = Prover.hash()
// }
//
//
//
//
// /**
// * Generate a ZK proof that there exists x s.t (g ^ x == a and h ^ x == b) or (g' ^ x == a and h' ^ x == b).
// *
// * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g}(a)==log_{g}(b)):
// * <ol>
// * <li>Prover chooses a random r, and sends g^r, h^r </li>
// * <li>Verifier chooses a random c and sends c</li>
// * <li>Prover computes </li>
// * </ol>
// *
// *
// * @param orStatement
// * @return ZKP OrProof:
// * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs
// */
// private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) {
//
// ECPoint g1 = orStatement.g1;
// ECPoint h1 = orStatement.h1;
// ECPoint g2 = orStatement.g2;
// ECPoint h2 = orStatement.h2;
//
// ECPoint g1Tag = orStatement.g1Tag;
// ECPoint h1Tag = orStatement.h1Tag;
// ECPoint g2Tag = orStatement.g2Tag;
// ECPoint h2Tag = orStatement.h2Tag;
//
// // Randomness for the ZK proof
// BigInteger r = encryptor.generateRandomExponent(rand);
//
//
// BigInteger c1,c2,z,zTag;
// ECPoint u,v,uTag,vTag;
// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage;
//
//
// switch (orStatement.trueClauseIndex) {
// case left:
// c2 = encryptor.generateRandomExponent(rand);
// zTag = encryptor.generateRandomExponent(rand);
// //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
// firstMessage =
// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder()
// .setG1(orStatement.g1Encoded)
// .setH1(orStatement.h1Encoded)
// .setG2(orStatement.g2Encoded)
// .setH2(orStatement.h2Encoded)
// .setG1Tag(orStatement.g1TagEncoded)
// .setH1Tag(orStatement.h1TagEncoded)
// .setG2Tag(orStatement.g2TagEncoded)
// .setH2Tag(orStatement.h2TagEncoded)
// .setU(encryptor.encodeElement(u))
// .setV(encryptor.encodeElement(v))
// .setUTag(encryptor.encodeElement(uTag))
// .setVTag(encryptor.encodeElement(vTag))
// .build();
// c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound);
// //step 3
// //z = (r + c1 * x) % group size;
// z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound);
// break;
// case right:
// c1 = encryptor.generateRandomExponent(rand);
// z = encryptor.generateRandomExponent(rand);
// //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
// firstMessage =
// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder()
// .setG1(orStatement.g1Encoded)
// .setH1(orStatement.h1Encoded)
// .setG2(orStatement.g2Encoded)
// .setH2(orStatement.h2Encoded)
// .setG1Tag(orStatement.g1TagEncoded)
// .setH1Tag(orStatement.h1TagEncoded)
// .setG2Tag(orStatement.g2TagEncoded)
// .setH2Tag(orStatement.h2TagEncoded)
// .setU(encryptor.encodeElement(u))
// .setV(encryptor.encodeElement(v))
// .setUTag(encryptor.encodeElement(uTag))
// .setVTag(encryptor.encodeElement(vTag))
// .build();
// c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound);
// //step 3
// //zTag = (r + c2 * x) % group size;
// zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound);
// break;
// default:
// return null;
// }
//
//
// return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
// .setG1(firstMessage.getG1())
// .setH1(firstMessage.getH1())
// .setG2(firstMessage.getG2())
// .setH2(firstMessage.getH2())
// .setG1Tag(firstMessage.getG1())
// .setH1Tag(firstMessage.getH1Tag())
// .setG2Tag(firstMessage.getG2Tag())
// .setH2Tag(firstMessage.getH2Tag())
// .setU(firstMessage.getU())
// .setV(firstMessage.getV())
// .setUTag(firstMessage.getUTag())
// .setVTag(firstMessage.getVTag())
// .setC1(Util.encodeBigInteger(c1))
// .setC2(Util.encodeBigInteger(c2))
// .setZ(Util.encodeBigInteger(z))
// .setZTag(Util.encodeBigInteger(zTag))
// .build();
// }
} }

View File

@ -0,0 +1,123 @@
package meerkat.mixer.proofs;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.crypto.concrete.Util;
import meerkat.protobuf.ConcreteCrypto;
import meerkat.protobuf.Mixing;
import org.bouncycastle.math.ec.ECPoint;
import org.factcenter.qilin.primitives.concrete.ECGroup;
import java.math.BigInteger;
import java.util.Random;
/**
* Schnorr's ZK proof of Dlog equivlance
*/
public class SchnorrDlogEquivalence {
public static class Verifier implements SigmaProtocol.Verifier<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
ECElGamalEncryption encryptor;
ECGroup group;
final ECElGamalMixStatementGenerator.DlogStatement statement;
public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.DlogStatement statement) {
this.encryptor = encryptor;
group = encryptor.getGroup();
this.statement = statement;
}
@Override
public boolean verify(Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage, BigInteger challenge,
Mixing.Mix2Proof.DlogProof.FinalMessage finalMessage) {
ConcreteCrypto.GroupElement grEncoded = firstMessage.getGr();
ECPoint gr = encryptor.decodeElement(grEncoded);
ConcreteCrypto.GroupElement hrEncoded = firstMessage.getHr();
ECPoint hr = encryptor.decodeElement(hrEncoded);
BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr());
boolean gGood = group.add(gr, group.multiply(statement.a, challenge)).equals(group.multiply(statement.g, xcr));
boolean hGood = group.add(hr, group.multiply(statement.b, challenge)).equals(group.multiply(statement.h, xcr));
return gGood && hGood;
}
}
public static class Simulator implements SigmaProtocol.Simulator<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
ECElGamalEncryption encryptor;
ECGroup group;
Random rand;
ECElGamalMixStatementGenerator.DlogStatement statement;
BigInteger response = null;
public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.DlogStatement statement) {
this.encryptor = encryptor;
group = encryptor.getGroup();
this.rand = rand;
this.statement = statement;
}
@Override
public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(BigInteger challenge) {
response = encryptor.generateRandomExponent(rand);
ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a, challenge));
ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b, challenge));
return Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder()
.setGr(encryptor.encodeElement(u))
.setHr(encryptor.encodeElement(v))
.build();
}
@Override
public Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage() {
return Mixing.Mix2Proof.DlogProof.FinalMessage.newBuilder()
.setXcr(Util.encodeBigInteger(response))
.build();
}
}
public static class Prover implements SigmaProtocol.Prover<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
ECElGamalEncryption encryptor;
ECGroup group;
Random rand;
ECElGamalMixStatementGenerator.DlogStatement statement;
ECElGamalMixStatementGenerator.DlogStatementWitness witness;
BigInteger r = null;
public Prover(ECElGamalEncryption encryptor, Random rand,
ECElGamalMixStatementGenerator.DlogStatement statement, ECElGamalMixStatementGenerator.DlogStatementWitness witness) {
this.encryptor = encryptor;
group = encryptor.getGroup();
this.rand = rand;
this.statement = statement;
this.witness = witness;
}
@Override
public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage() {
r = encryptor.generateRandomExponent(rand);
ECPoint gr = group.multiply(statement.g, r);
ECPoint hr = group.multiply(statement.h, r);
Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder()
.setGr(encryptor.encodeElement(gr))
.setHr(encryptor.encodeElement(hr))
.build();
return firstMessage;
}
@Override
public Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage(BigInteger challenge) {
return Mixing.Mix2Proof.DlogProof.FinalMessage.newBuilder()
.setXcr(Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound())))
.build();
}
}
}

View File

@ -12,23 +12,11 @@ public interface SigmaProtocol {
public interface Prover <FirstMsgType, FinalMessageType> { public interface Prover <FirstMsgType, FinalMessageType> {
public FirstMsgType getFirstMessage(); public FirstMsgType getFirstMessage();
public FinalMessageType getFinalMessage(BigInteger challenge); public FinalMessageType getFinalMessage(BigInteger challenge);
/**
* Reset the prover (so the next calls to {@link #getFirstMessage()} will
* start a new proof.
*/
public void reset();
} }
public interface Simulator <FirstMsgType, FinalMessageType> { public interface Simulator <FirstMsgType, FinalMessageType> {
public FirstMsgType getFirstMessage(BigInteger challenge); public FirstMsgType getFirstMessage(BigInteger challenge);
public FinalMessageType getFinalMessage(); public FinalMessageType getFinalMessage();
/**
* Reset the prover (so the next calls to {@link #getFirstMessage(BigInteger)} will
* start a new proof.
*/
public void reset();
} }
public interface Verifier <FirstMsgType, FinalMessageType> { public interface Verifier <FirstMsgType, FinalMessageType> {

View File

@ -29,10 +29,6 @@ public class SigmaProtocolAnd2 {
public FinalMessageOut getFinalMessage(BigInteger challenge) { public FinalMessageOut getFinalMessage(BigInteger challenge) {
return finalMessageConcatenator.concatenate(provers[0].getFinalMessage(challenge), provers[1].getFinalMessage(challenge)); return finalMessageConcatenator.concatenate(provers[0].getFinalMessage(challenge), provers[1].getFinalMessage(challenge));
} }
@Override
public void reset() { provers[0].reset(); provers[1].reset(); }
} }
static public class Verifier<FirstMessageOut, FirstMessageIn, static public class Verifier<FirstMessageOut, FirstMessageIn,
@ -80,8 +76,6 @@ public class SigmaProtocolAnd2 {
return finalMessageConcatenator.concatenate(simulators[0].getFinalMessage(), simulators[1].getFinalMessage()); return finalMessageConcatenator.concatenate(simulators[0].getFinalMessage(), simulators[1].getFinalMessage());
} }
@Override
public void reset() { simulators[0].reset(); simulators[1].reset(); }
} }
} }

View File

@ -72,9 +72,6 @@ public class SigmaProtocolOr2 {
return finalMessageConcatenator.concatenate(simChallenge, simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); return finalMessageConcatenator.concatenate(simChallenge, simulator.getFinalMessage(), prover.getFinalMessage(realchallenge));
} }
} }
@Override
public void reset() { prover.reset(); simulator.reset(); simChallenge = null; }
} }
static public class Verifier <FirstMessageOut, FirstMessageIn, FinalMessageOut, FinalMessageIn> static public class Verifier <FirstMessageOut, FirstMessageIn, FinalMessageOut, FinalMessageIn>
@ -142,9 +139,6 @@ public class SigmaProtocolOr2 {
public FinalMessageOut getFinalMessage() { public FinalMessageOut getFinalMessage() {
return finalMessageConcatenator.concatenate(simChallenge0, simulators[0].getFinalMessage(), simulators[1].getFinalMessage()); return finalMessageConcatenator.concatenate(simChallenge0, simulators[0].getFinalMessage(), simulators[1].getFinalMessage());
} }
@Override
public void reset() { simulators[0].reset(); simulators[1].reset(); }
} }
} }

View File

@ -8,7 +8,6 @@ import meerkat.protobuf.Mixing;
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.ECGroup; import org.factcenter.qilin.primitives.concrete.ECGroup;
import meerkat.mixer.proofs.ECElGamalMixProtocols.Mix2Verifier;
/** /**
* implements Mix2ZeroKnowledgeVerifier * implements Mix2ZeroKnowledgeVerifier
@ -16,11 +15,11 @@ import meerkat.mixer.proofs.ECElGamalMixProtocols.Mix2Verifier;
public class Verifier implements Mix2ZeroKnowledgeVerifier { public class Verifier implements Mix2ZeroKnowledgeVerifier {
private final ECElGamalEncryption encryptor;
private final ECGroup group; private final ECGroup group;
private final RandomOracle randomOracle; private final RandomOracle randomOracle;
private final ECPoint g,h; private final ECPoint g,h;
private final ECElGamalMixParams mixParams; private final ECElGamalMixStatementGenerator mixParams;
final ECElGamalMixProtocols mixProtocols;
final SigmaFiatShamir mix2NIZK; final SigmaFiatShamir mix2NIZK;
@ -32,12 +31,12 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
* @param randomOracle should be as the random oracle used by meerkat.mixer.proofs * @param randomOracle should be as the random oracle used by meerkat.mixer.proofs
*/ */
public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) { public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) {
this.encryptor = encryptor;
this.group = encryptor.getGroup(); this.group = encryptor.getGroup();
this.g = group.getGenerator(); this.g = group.getGenerator();
this.h = encryptor.getElGamalPK().getPK(); this.h = encryptor.getElGamalPK().getPK();
this.randomOracle = randomOracle; this.randomOracle = randomOracle;
this.mixParams = new ECElGamalMixParams(encryptor); this.mixParams = new ECElGamalMixStatementGenerator(encryptor);
this.mixProtocols = new ECElGamalMixProtocols(mixParams, null); // We don't need randomness for the verifier
this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle);
// this.parser = new ZeroKnowledgeOrProofParser(group); // this.parser = new ZeroKnowledgeOrProofParser(group);
} }
@ -60,8 +59,8 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
Crypto.RerandomizableEncryptedMessage out2, Crypto.RerandomizableEncryptedMessage out2,
Mixing.Mix2Proof proof) throws InvalidProtocolBufferException { Mixing.Mix2Proof proof) throws InvalidProtocolBufferException {
ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2);
Mix2Verifier verifier = mixProtocols.new Mix2Verifier(statement); Mix2.Verifier verifier = new Mix2.Verifier(encryptor, statement);
return mix2NIZK.verifyNizk(proof, verifier); return mix2NIZK.verifyNizk(proof, verifier);
} }

View File

@ -16,20 +16,17 @@ public final class VerifyTable {
/** /**
* constructor * constructor
* @param verifier * @param verifier
* @param n
* @param mixerOutput * @param mixerOutput
* @return true iff the meerkat.mixer.mixing output is valid * @return true iff the meerkat.mixer.mixing output is valid
* @throws InvalidProtocolBufferException * @throws InvalidProtocolBufferException
*/ */
public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier,int n,MixerOutput mixerOutput) public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier, MixerOutput mixerOutput)
throws InvalidProtocolBufferException { throws InvalidProtocolBufferException {
int index1,index2,layer; int out0,out1,layer, switchIdx;
//assert n = 2^k
if ( (n &(n-1)) != 0)
throw new IllegalArgumentException("n");
int layers = 2*(int)(Math.log(n) / Math.log(2)) - 1; int layers = mixerOutput.getNumLayers();
int n = 1 << mixerOutput.getLogN();
//initialize locationChecksum table //initialize locationChecksum table
// use for check BeneshNet validity // use for check BeneshNet validity
boolean[][] locationChecksum = new boolean[layers][n]; boolean[][] locationChecksum = new boolean[layers][n];
@ -44,36 +41,32 @@ public final class VerifyTable {
for (int j = 0; j < Mix2Proofs[i].length ; j ++){ for (int j = 0; j < Mix2Proofs[i].length ; j ++){
Mixing.Mix2Proof zkp = Mix2Proofs[i][j]; Mixing.Mix2Proof zkp = Mix2Proofs[i][j];
Mixing.Mix2Proof.Location location = zkp.getLocation(); Mixing.Mix2Proof.Location location = zkp.getLocation();
index1 = location.getI(); out0 = location.getOut0();
index2 = location.getJ(); out1 = location.getOut1();
layer = location.getLayer(); layer = location.getLayer();
switchIdx = location.getSwitchIdx();
// check location validity // check location validity
if (layer > layers >> 1) { // TODO: add check
if (index2 - index1 != n >> (layers - layer)) // if (layer > layers >> 1) {
return false; // if (out1 - out0 != n >> (layers - layer))
} // return false;
else{ // }
if (index2 - index1 != n >> (layer + 1)) // else{
return false; // if (out1 - out0 != n >> (layer + 1))
} // return false;
// }
// mark location in table // mark location in table
locationChecksum[layer][index1] = true; locationChecksum[layer][2 * switchIdx] = true;
locationChecksum[layer][index2] = true; locationChecksum[layer][2 * switchIdx + 1] = true;
// verify proof // verify proof
if(!verifier.verify(rerandomizableEncryptedMessages[layer][index1], if(!verifier.verify(rerandomizableEncryptedMessages[layer][2 * switchIdx],
rerandomizableEncryptedMessages[layer][index2], rerandomizableEncryptedMessages[layer][2 * switchIdx + 1],
rerandomizableEncryptedMessages[layer + 1][index1], rerandomizableEncryptedMessages[layer + 1][out0],
rerandomizableEncryptedMessages[layer + 1][index2], rerandomizableEncryptedMessages[layer + 1][out1],
zkp)) { zkp)) {
verifier.verify(rerandomizableEncryptedMessages[layer][index1],
rerandomizableEncryptedMessages[layer][index2],
rerandomizableEncryptedMessages[layer + 1][index1],
rerandomizableEncryptedMessages[layer + 1][index2],
zkp);
return false; return false;
} }
} }

View File

@ -7,6 +7,11 @@ option java_package = "meerkat.protobuf";
import 'meerkat/crypto.proto'; import 'meerkat/crypto.proto';
import 'meerkat/concrete_crypto.proto'; import 'meerkat/concrete_crypto.proto';
message MixBatchHeader {
int32 logN = 1; // log (base 2) of number of inputs to mix
int32 layers = 2; // Number of layers in mix
}
message Plaintext { message Plaintext {
bytes data = 1; bytes data = 1;
} }
@ -44,13 +49,19 @@ message Mix2Proof {
BigInteger c0 = 3; // Challenge for clause 0; challenge for clause 1 is computed from real challenge and c0 BigInteger c0 = 3; // Challenge for clause 0; challenge for clause 1 is computed from real challenge and c0
} }
// Location of the
message Location { message Location {
int32 i = 1; int32 layer = 1; // layer in which the switch is placed
int32 j = 2; int32 switchIdx = 2; // idx of the switch
int32 layer = 3; int32 out0 = 3; // idx of the first output ciphertext (in layer+1 of the ciphertext matrix)
int32 out1 = 4; // idx of the second output ciphertext (in layer+1 of the ciphertext matrix)
} }
FirstMessage firstMessage = 1; FirstMessage firstMessage = 1;
FinalMessage finalMessage = 2; FinalMessage finalMessage = 2;
Location location = 5; Location location = 5;
} }

View File

@ -1,100 +1,100 @@
package meerkat.mixer; //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.Mixer;
import meerkat.mixer.mixing.MixerOutput; //import meerkat.mixer.mixing.MixerOutput;
import meerkat.mixer.proofs.Prover; //import meerkat.mixer.proofs.Prover;
import meerkat.mixer.proofs.Verifier; //import meerkat.mixer.proofs.Verifier;
import meerkat.mixer.proofs.VerifyTable; //import meerkat.mixer.proofs.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;
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 java.io.IOException; //import java.io.IOException;
import java.security.spec.InvalidKeySpecException; //import java.security.spec.InvalidKeySpecException;
import java.util.ArrayList; //import java.util.ArrayList;
import java.util.List; //import java.util.List;
import java.util.Random; //import java.util.Random;
//
/** ///**
* Created by Tzlil on 1/19/2016. // * Created by Tzlil on 1/19/2016.
*/ // */
public class CreateTestVector { //public class CreateTestVector {
//
//
ECElGamalEncryption encryptor; // ECElGamalEncryption encryptor;
ECGroup group; // ECGroup group;
Random random,randomMixer,randomProver; // Random random,randomMixer,randomProver;
RandomOracle randomOracle; // RandomOracle randomOracle;
Mix2ZeroKnowledgeVerifier verifier; // Mix2ZeroKnowledgeVerifier verifier;
Mix2ZeroKnowledgeProver prover; // Mix2ZeroKnowledgeProver prover;
meerkat.crypto.mixnet.Mixer mixer; // meerkat.crypto.mixnet.Mixer mixer;
private int layers; // private int layers;
private int n; // private int n;
//
//
@Before // @Before
public void setup() throws InvalidKeySpecException { // public void setup() throws InvalidKeySpecException {
// initialization // // initialization
random = new Random(); // random = new Random();
group = new ECGroup("secp256k1"); // group = new ECGroup("secp256k1");
encryptor = new ECElGamalEncryption(); // encryptor = new ECElGamalEncryption();
encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random))));
randomMixer = new Random(); // randomMixer = new Random();
randomProver = new Random(); // randomProver = new Random();
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(prover,encryptor); // mixer = new Mixer(prover,encryptor);
//
// generate n // // generate n
int logN = 10; // + random.nextInt(8) // int logN = 10; // + random.nextInt(8)
layers = 2*logN - 1; // layers = 2*logN - 1;
n = 1 << logN; // n = 1 << logN;
} // }
//
public List<Crypto.RerandomizableEncryptedMessage> generateMixerInput(){ // public List<Crypto.RerandomizableEncryptedMessage> generateMixerInput(){
List<Crypto.RerandomizableEncryptedMessage> result = new ArrayList<Crypto.RerandomizableEncryptedMessage>(); // List<Crypto.RerandomizableEncryptedMessage> result = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
Voting.PlaintextBallot msg; // Voting.PlaintextBallot msg;
for (int i = 0; i < n ; i++){ // for (int i = 0; i < n ; i++){
msg = Utils.genRandomBallot(2,3,16); // msg = Utils.genRandomBallot(2,3,16);
result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random))); // result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random)));
} // }
return result; // return result;
} // }
//@SimpleRerandomizeTest // //@SimpleRerandomizeTest
public void createValidTest() throws IOException { // public void createValidTest() throws IOException {
//
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput(); // List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
System.out.println("start mixing"); // System.out.println("start mixing");
MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer); // 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.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3"); // mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3");
System.out.println("all done"); // System.out.println("all done");
} // }
//
//@SimpleRerandomizeTest // //@SimpleRerandomizeTest
public void createInvalidTest() throws IOException { // public void createInvalidTest() throws IOException {
//
//Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(enc,randomOracle,true); // //Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(enc,randomOracle,true);
//Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,enc,randomOracle,true); // //Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,enc,randomOracle,true);
//mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); // //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier);
//
List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput(); // List<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
System.out.println("start mixing"); // System.out.println("start mixing");
MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random); // 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.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5"); // mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5");
System.out.println("all done"); // System.out.println("all done");
} // }
} //}

View File

@ -77,7 +77,7 @@ public class Mix2ProofTest extends ECParamTestBase {
group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2())))); group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2()))));
Mixing.Mix2Proof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2); Mixing.Mix2Proof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0, 0, r1,r2);
assertTrue (verifier.verify(e1,e2,e1New,e2New, proof)); assertTrue (verifier.verify(e1,e2,e1New,e2New, proof));
} }

View File

@ -1,46 +0,0 @@
package meerkat.mixer;
/**
* 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 java.util.Arrays;
import java.util.Random;
public class MixNetworkTest {
@Test
public void testMixNetwork() throws Exception{
Random random = new Random(1);
int logn = 10;
int n = 1 << logn;
int layers = 2*logn - 1;
RandomPermutation randomPermutation = new RandomPermutation(n,random);
MixNetwork mixNetwork = new MixNetwork(randomPermutation);
//initialize arr s.t arr[i] = i
int[] arr = new int[n];
for (int i = 0; i < n ;i ++)
arr[i] = i;
// layer by layer swap between values
for (int layer = 0 ; layer< layers ; layer ++) {
for (Switch sw : mixNetwork.getSwitchesByLayer(layer)) {
if(sw.value) {
arr[sw.i] += arr[sw.j];
arr[sw.j] = arr[sw.i] - arr[sw.j];
arr[sw.i] -= arr[sw.j];
}
}
}
assert(Arrays.equals(arr,randomPermutation.permutation));
}
}

View File

@ -45,7 +45,7 @@ public class MixingTest extends ECParamTestBase {
mixer = new Mixer(prover, enc); mixer = new Mixer(prover, enc);
// generate n // generate n
int logN = 9; // + random.nextInt(8) int logN = 5; // + random.nextInt(8)
layers = 2*logN - 1; layers = 2*logN - 1;
n = 1 << logN; n = 1 << logN;
} }
@ -76,7 +76,7 @@ public class MixingTest extends ECParamTestBase {
System.out.println("start verification"); System.out.println("start verification");
startTime = System.currentTimeMillis(); startTime = System.currentTimeMillis();
assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); assert (VerifyTable.verifyTable(verifier,mixerOutput));
finishTime = System.currentTimeMillis(); finishTime = System.currentTimeMillis();
System.out.println(" that took: "+(finishTime-startTime)+ " ms"); System.out.println(" that took: "+(finishTime-startTime)+ " ms");

View File

@ -11,8 +11,8 @@ import java.math.BigInteger;
public class DlogAndStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> { public class DlogAndStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> {
final DlogStatementSchnorrSigmaTest dlogtest; final DlogStatementSchnorrSigmaTest dlogtest;
ECElGamalMixParams.DlogStatement s1, s2; ECElGamalMixStatementGenerator.DlogStatement s1, s2;
ECElGamalMixParams.DlogStatementWitness w1, w2; ECElGamalMixStatementGenerator.DlogStatementWitness w1, w2;
public DlogAndStatementSigmaTest() { public DlogAndStatementSigmaTest() {
this.dlogtest = new DlogStatementSchnorrSigmaTest(); this.dlogtest = new DlogStatementSchnorrSigmaTest();
@ -20,10 +20,10 @@ public class DlogAndStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proo
@Override @Override
void generateRandomTrueStatement() { void generateRandomTrueStatement() {
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> s1w1 = dlogtest.returnRandomTrueStatement(); Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> s1w1 = dlogtest.returnRandomTrueStatement();
s1 = s1w1.a; w1 = s1w1.b; s1 = s1w1.a; w1 = s1w1.b;
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> s2w2 = dlogtest.returnRandomTrueStatement(); Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> s2w2 = dlogtest.returnRandomTrueStatement();
s2 = s2w2.a; w2 = s2w2.b; s2 = s2w2.a; w2 = s2w2.b;
} }
@ -36,19 +36,19 @@ public class DlogAndStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proo
@Override @Override
protected SigmaProtocol.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewProver() { protected SigmaProtocol.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewProver() {
return new SigmaProtocolAnd2.Prover<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, return new SigmaProtocolAnd2.Prover<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
dlogtest.prots.new DlogStatementSchnorrProver(s1, w1), dlogtest.prots.new DlogStatementSchnorrProver(s2, w2)); new SchnorrDlogEquivalence.Prover(dlogtest.encryptor, rand, s1, w1), new SchnorrDlogEquivalence.Prover(dlogtest.encryptor, rand, s2, w2));
} }
@Override @Override
protected SigmaProtocol.Verifier<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewVerifier() { protected SigmaProtocol.Verifier<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewVerifier() {
return new SigmaProtocolAnd2.Verifier<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, return new SigmaProtocolAnd2.Verifier<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
dlogtest.prots.new DlogStatementSchnorrVerifier(s1), dlogtest.prots.new DlogStatementSchnorrVerifier(s2)); new SchnorrDlogEquivalence.Verifier(dlogtest.encryptor, s1), new SchnorrDlogEquivalence.Verifier(dlogtest.encryptor, s2));
} }
@Override @Override
protected SigmaProtocol.Simulator<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewSimulator() { protected SigmaProtocol.Simulator<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> getNewSimulator() {
return new SigmaProtocolAnd2.Simulator<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, return new SigmaProtocolAnd2.Simulator<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2,
dlogtest.prots.new DlogStatementSchnorrSimulator(s1), dlogtest.prots.new DlogStatementSchnorrSimulator(s2)); new SchnorrDlogEquivalence.Simulator(dlogtest.encryptor, rand, s1), new SchnorrDlogEquivalence.Simulator(dlogtest.encryptor, rand, s2));
} }
@Override @Override

View File

@ -11,8 +11,8 @@ import java.math.BigInteger;
public class DlogOrStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> { public class DlogOrStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> {
final DlogStatementSchnorrSigmaTest dlogtest; final DlogStatementSchnorrSigmaTest dlogtest;
final ECElGamalMixParams.AndStatement[] statements = new ECElGamalMixParams.AndStatement[2]; final ECElGamalMixStatementGenerator.AndStatement[] statements = new ECElGamalMixStatementGenerator.AndStatement[2];
ECElGamalMixParams.AndStatementWitness w; ECElGamalMixStatementGenerator.AndStatementWitness w;
int trueStatementIndex; int trueStatementIndex;
@ -23,53 +23,57 @@ public class DlogOrStatementSigmaTest extends SigmaProtocolTest<Mixing.Mix2Proof
@Override @Override
void generateRandomTrueStatement() { void generateRandomTrueStatement() {
trueStatementIndex = rand.nextInt(2); trueStatementIndex = rand.nextInt(2);
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> s1w1 = dlogtest.returnRandomTrueStatement(); Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> s1w1 = dlogtest.returnRandomTrueStatement();
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> s2w2 = dlogtest.returnRandomTrueStatement(); Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> s2w2 = dlogtest.returnRandomTrueStatement();
ECElGamalMixParams.AndStatement trueStatement = dlogtest.params.new AndStatement(s1w1.a, s2w2.a); ECElGamalMixStatementGenerator.AndStatement trueStatement = dlogtest.statementGenerator.new AndStatement(s1w1.a, s2w2.a);
w = dlogtest.params.new AndStatementWitness(s1w1.b, s2w2.b); w = dlogtest.statementGenerator.new AndStatementWitness(s1w1.b, s2w2.b);
statements[trueStatementIndex] = trueStatement; statements[trueStatementIndex] = trueStatement;
ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement();
ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement();
ECElGamalMixParams.AndStatement falseStatement = dlogtest.params.new AndStatement(f1, f2); ECElGamalMixStatementGenerator.AndStatement falseStatement = dlogtest.statementGenerator.new AndStatement(f1, f2);
statements[1 - trueStatementIndex] = falseStatement; statements[1 - trueStatementIndex] = falseStatement;
} }
@Override @Override
void generateRandomFalseStatement() { void generateRandomFalseStatement() {
ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement();
ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement();
statements[0] = dlogtest.params.new AndStatement(f1, f2); statements[0] = dlogtest.statementGenerator.new AndStatement(f1, f2);
f1 = dlogtest.returnRandomFalseStatement(); f1 = dlogtest.returnRandomFalseStatement();
f2 = dlogtest.returnRandomFalseStatement(); f2 = dlogtest.returnRandomFalseStatement();
statements[1] = dlogtest.params.new AndStatement(f1, f2); statements[1] = dlogtest.statementGenerator.new AndStatement(f1, f2);
} }
@Override @Override
protected SigmaProtocol.Prover<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewProver() { protected SigmaProtocol.Prover<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewProver() {
SigmaProtocol.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andProver = dlogtest.prots.new AndStatementProver(statements[trueStatementIndex], w); SigmaProtocol.Prover<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andProver = new DlogConjunction.Prover(dlogtest.encryptor, rand, statements[trueStatementIndex], w);
SigmaProtocol.Simulator<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andSimulator = dlogtest.prots.new AndStatementSimulator(statements[1 - trueStatementIndex]); SigmaProtocol.Simulator<Mixing.Mix2Proof.AndProof.FirstMessage, Mixing.Mix2Proof.AndProof.FinalMessage> andSimulator = new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1 - trueStatementIndex]);
Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
return new SigmaProtocolOr2.Prover<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, return new SigmaProtocolOr2.Prover<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
dlogtest.prots.challengeGenerator, andProver, andSimulator, trueStatementIndex); gen, andProver, andSimulator, trueStatementIndex);
} }
@Override @Override
protected SigmaProtocol.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewVerifier() { protected SigmaProtocol.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewVerifier() {
Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
return new SigmaProtocolOr2.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage, return new SigmaProtocolOr2.Verifier<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.AndProof.FirstMessage,
Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, Mixing.Mix2Proof.FinalMessage, Mixing.Mix2Proof.AndProof.FinalMessage>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementVerifier(statements[0]), dlogtest.prots.new AndStatementVerifier(statements[1])); gen, new DlogConjunction.Verifier(dlogtest.encryptor, statements[0]), new DlogConjunction.Verifier(dlogtest.encryptor, statements[1]));
} }
@Override @Override
protected SigmaProtocol.Simulator<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewSimulator() { protected SigmaProtocol.Simulator<Mixing.Mix2Proof.FirstMessage, Mixing.Mix2Proof.FinalMessage> getNewSimulator() {
Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand);
return new SigmaProtocolOr2.Simulator<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, return new SigmaProtocolOr2.Simulator<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2,
dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementSimulator(statements[0]), gen, new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[0]),
dlogtest.prots.new AndStatementSimulator(statements[1])); new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1]));
} }
@Override @Override

View File

@ -1,8 +1,10 @@
package meerkat.mixer.proofs; package meerkat.mixer.proofs;
import meerkat.crypto.concrete.ECElGamalEncryption;
import meerkat.mixer.ECParamTestBase; import meerkat.mixer.ECParamTestBase;
import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing;
import org.bouncycastle.math.ec.ECPoint; import org.bouncycastle.math.ec.ECPoint;
import org.factcenter.qilin.primitives.concrete.ECGroup;
import org.factcenter.qilin.util.Pair; import org.factcenter.qilin.util.Pair;
import java.math.BigInteger; import java.math.BigInteger;
@ -13,42 +15,44 @@ import java.math.BigInteger;
public class DlogStatementSchnorrSigmaTest extends public class DlogStatementSchnorrSigmaTest extends
SigmaProtocolTest<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> { SigmaProtocolTest<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> {
ECParamTestBase ecParams = new ECParamTestBase(); ECParamTestBase ecParams;
ECElGamalMixParams params; ECElGamalMixStatementGenerator statementGenerator;
ECElGamalMixProtocols prots; ECElGamalEncryption encryptor;
ECGroup group;
ECElGamalMixParams.DlogStatement statement; ECElGamalMixStatementGenerator.DlogStatement statement;
ECElGamalMixParams.DlogStatementWitness witness; ECElGamalMixStatementGenerator.DlogStatementWitness witness;
ECElGamalMixProtocols.DlogStatementSchnorrProver prover; SchnorrDlogEquivalence.Prover prover;
ECElGamalMixProtocols.DlogStatementSchnorrVerifier verifier; SchnorrDlogEquivalence.Verifier verifier;
ECElGamalMixProtocols.DlogStatementSchnorrSimulator simulator; SchnorrDlogEquivalence.Simulator simulator;
public DlogStatementSchnorrSigmaTest() { public DlogStatementSchnorrSigmaTest() {
ecParams = new ECParamTestBase();
this.params = new ECElGamalMixParams(ecParams.enc); encryptor = ecParams.enc;
this.prots = new ECElGamalMixProtocols(params, rand); // We don't need randomness for the verifier group = encryptor.getGroup();
this.statementGenerator = new ECElGamalMixStatementGenerator(ecParams.enc);
} }
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> returnRandomTrueStatement() { Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> returnRandomTrueStatement() {
BigInteger x = prots.encryptor.generateRandomExponent(rand); BigInteger x = encryptor.generateRandomExponent(rand);
ECPoint a = prots.group.multiply(prots.g, x); ECPoint a = group.multiply(statementGenerator.g, x);
ECPoint b = prots.group.multiply(prots.h, x); ECPoint b = group.multiply(statementGenerator.h, x);
ECElGamalMixParams.DlogStatement statement = params.new DlogStatement(a, b); ECElGamalMixStatementGenerator.DlogStatement statement = statementGenerator.new DlogStatement(a, b);
ECElGamalMixParams.DlogStatementWitness witness = params.new DlogStatementWitness(x); ECElGamalMixStatementGenerator.DlogStatementWitness witness = statementGenerator.new DlogStatementWitness(x);
return new Pair<>(statement, witness); return new Pair<>(statement, witness);
} }
ECElGamalMixParams.DlogStatement returnRandomFalseStatement() { ECElGamalMixStatementGenerator.DlogStatement returnRandomFalseStatement() {
ECPoint a = prots.group.sample(rand); ECPoint a = group.sample(rand);
ECPoint b = prots.group.sample(rand); ECPoint b = group.sample(rand);
return params.new DlogStatement(a, b); return statementGenerator.new DlogStatement(a, b);
} }
void generateRandomTrueStatement() { void generateRandomTrueStatement() {
Pair<ECElGamalMixParams.DlogStatement, ECElGamalMixParams.DlogStatementWitness> sw = returnRandomTrueStatement(); Pair<ECElGamalMixStatementGenerator.DlogStatement, ECElGamalMixStatementGenerator.DlogStatementWitness> sw = returnRandomTrueStatement();
this.statement = sw.a; this.statement = sw.a;
this.witness = sw.b; this.witness = sw.b;
} }
@ -60,24 +64,24 @@ public class DlogStatementSchnorrSigmaTest extends
@Override @Override
protected SigmaProtocol.Prover<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewProver() { protected SigmaProtocol.Prover<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewProver() {
prover = prots.new DlogStatementSchnorrProver(statement, witness); prover = new SchnorrDlogEquivalence.Prover(encryptor, rand, statement, witness);
return prover; return prover;
} }
@Override @Override
protected SigmaProtocol.Verifier<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewVerifier() { protected SigmaProtocol.Verifier<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewVerifier() {
verifier = prots.new DlogStatementSchnorrVerifier(statement); verifier = new SchnorrDlogEquivalence.Verifier(encryptor, statement);
return verifier; return verifier;
} }
@Override @Override
protected SigmaProtocol.Simulator<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewSimulator() { protected SigmaProtocol.Simulator<Mixing.Mix2Proof.DlogProof.FirstMessage, Mixing.Mix2Proof.DlogProof.FinalMessage> getNewSimulator() {
simulator = prots.new DlogStatementSchnorrSimulator(statement); simulator = new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement);
return simulator; return simulator;
} }
@Override @Override
protected BigInteger getChallengeModulus() { protected BigInteger getChallengeModulus() {
return prots.group.orderUpperBound(); return group.orderUpperBound();
} }
} }

View File

@ -34,11 +34,6 @@ public class DummySigmaProof {
public BigInteger getFinalMessage(BigInteger challenge) { public BigInteger getFinalMessage(BigInteger challenge) {
return challenge.add(r.multiply(x.add(y))); return challenge.add(r.multiply(x.add(y)));
} }
@Override
public void reset() {
}
} }
public static class Verifier implements SigmaProtocol.Verifier<Crypto.BigInteger,BigInteger> { public static class Verifier implements SigmaProtocol.Verifier<Crypto.BigInteger,BigInteger> {
@ -81,11 +76,6 @@ public class DummySigmaProof {
public BigInteger getFinalMessage() { public BigInteger getFinalMessage() {
return resp; return resp;
} }
@Override
public void reset() {
}
} }
} }

View File

@ -75,7 +75,7 @@ public class ZeroKnowledgeProof {
for (int i = 0; i < n*2 ; i +=2){ for (int i = 0; i < n*2 ; i +=2){
prover.prove(encryptedMessage[i],encryptedMessage[i+1],reencryptedMessage[i],reencryptedMessage[i+1], prover.prove(encryptedMessage[i],encryptedMessage[i+1],reencryptedMessage[i],reencryptedMessage[i+1],
false,0,0,0,randomnesses[i],randomnesses[i+1]); false,0,0,0, 0, randomnesses[i],randomnesses[i+1]);
} }
long finishTime = System.currentTimeMillis(); long finishTime = System.currentTimeMillis();