From a834194d504d15c3e6ee95d202a3289305a7d58f Mon Sep 17 00:00:00 2001 From: "tzlil.gon" Date: Tue, 1 Dec 2015 21:48:41 +0200 Subject: [PATCH] mixer project --- gradle/wrapper/gradle-wrapper.properties | 2 +- .../java/meerkat/crypto/mixnet/Mixer.java | 7 +- .../src/main/proto/meerkat/mixing.proto | 74 ++++++++--------- mixer/src/main/java/mixer/Graph.java | 80 ++++++++++++------- mixer/src/main/java/mixer/Mixer.java | 71 ++++++++-------- 5 files changed, 122 insertions(+), 112 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7b65bea..3555c28 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Mon Oct 26 15:30:44 IST 2015 +#Tue Dec 01 01:04:39 IST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java index 52e8844..bbd999e 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java @@ -1,5 +1,10 @@ package meerkat.crypto.mixnet; +import com.google.protobuf.InvalidProtocolBufferException; +import javafx.util.Pair; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; + import java.util.List; import static meerkat.protobuf.Voting.*; @@ -7,5 +12,5 @@ import static meerkat.protobuf.Voting.*; * Created by talm on 25/10/15. */ public interface Mixer { - public List mix(List ballots); + public Pair mix(List ciphertexts) throws InvalidProtocolBufferException; } diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index 8adade9..8e56e2e 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -7,44 +7,38 @@ option java_package = "meerkat.protobuf"; import 'meerkat/crypto.proto'; message ZeroKnowledgeProof { - bytes data = 1; -} + message OrProof { + message GroupMember { + bytes data = 1; + } + message BigIntegerMsg { + bytes data = 1; + } -//message ZeroKnowledgeProof { -// -// message OrProof{ -// message GroupMember{ -// required bytes data = 1; -// } -// message BigIntegerMsg{ -// required bytes data = 1; -// } -// //input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag; -// required GroupMember g1 = 1; -// required GroupMember h1 = 2; -// required GroupMember g2 = 3; -// required GroupMember h2 = 4; -// required GroupMember g1Tag = 5; -// required GroupMember h1Tag = 6; -// required GroupMember g2Tag = 7; -// required GroupMember h2Tag = 8; -// -// //calc: u, v, uTag, vTag; -// required GroupMember g2 = 9; -// required GroupMember h2 = 10; -// required GroupMember g1Tag = 11; -// required GroupMember h1Tag = 12; -// -// //generated: c1,c2,z,zTag -// required BigIntegerMsg c1 = 13; -// required BigIntegerMsg c2 = 14; -// required BigIntegerMsg z = 15; -// required BigIntegerMsg zTag = 16; -// } -// -// required OrProof first = 1; -// required OrProof second = 2; -// required OrProof third = 3; -// required OrProof fourth = 4; -//} -// \ No newline at end of file + //input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag; + GroupMember g1 = 1; + GroupMember h1 = 2; + GroupMember g2 = 3; + GroupMember h2 = 4; + GroupMember g1Tag = 5; + GroupMember h1Tag = 6; + GroupMember g2Tag = 7; + GroupMember h2Tag = 8; + + //calc: u, v, uTag, vTag; + GroupMember u = 9; + GroupMember v = 10; + GroupMember uTag = 11; + GroupMember vTag = 12; + + //generated: c1,c2,z,zTag + BigIntegerMsg c1 = 13; + BigIntegerMsg c2 = 14; + BigIntegerMsg z = 15; + BigIntegerMsg zTag = 16; + } + OrProof first = 1; + OrProof second = 2; + OrProof third = 3; + OrProof fourth = 4; +} diff --git a/mixer/src/main/java/mixer/Graph.java b/mixer/src/main/java/mixer/Graph.java index b600be8..d57a044 100644 --- a/mixer/src/main/java/mixer/Graph.java +++ b/mixer/src/main/java/mixer/Graph.java @@ -6,78 +6,96 @@ import java.util.List; class Graph { private int n; + private int nDiv2; private Node[] nodes; protected Graph(int[] permutation){ n = permutation.length; // n = 2^k + nDiv2 = n /2; createNodes(); createEdges(permutation); setSwitches(); } - + + // provide an access to graph to algorithm result + // index must be less then n/2 protected boolean getSwitchValue(int index,boolean up) { - // index must be less then n/2 return up ? nodes[index].on : nodes[index + n / 2].on; } - + + // 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[n]; for (int i = 0; i < n / 2; i++) { - nodes[i] = new Node(i, i + n / 2, true); - nodes[i + n / 2] = new Node(i, i + n / 2, false); + nodes[i] = new Node(true); + nodes[i + nDiv2] = new Node(false); } } - + + // 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 pi1, pi2; - for (int i = 0; i < n / 2; i++) + int j; + for (int i = 0; i < nDiv2; i++) { - pi1 = (permutation[i] < n / 2) ? permutation[i] + (n / 2) : permutation[i]; - pi2 = (permutation[i + n / 2] < n / 2) ? permutation[i + n / 2] + (n / 2) : permutation[i + n / 2]; + j = (permutation[i] % nDiv2) + nDiv2; + nodes[i].edges.add(new Edge(nodes[j], (permutation[i] >= nDiv2))); + nodes[j].edges.add(new Edge(nodes[i], (permutation[i] >= nDiv2))); - nodes[i].edges.add(new Edge(nodes[pi1], (permutation[i] >= n / 2))); - nodes[pi1].edges.add(new Edge(nodes[i], (permutation[i] >= n / 2))); - - nodes[i].edges.add(new Edge(nodes[pi2], (permutation[i + n / 2] < n / 2))); - nodes[pi2].edges.add(new Edge(nodes[i], (permutation[i + n / 2] < n / 2))); + j = (permutation[i + nDiv2] % nDiv2) + nDiv2; + nodes[i].edges.add(new Edge(nodes[j], (permutation[i + nDiv2] < nDiv2))); + nodes[j].edges.add(new Edge(nodes[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() { - for (int i = 0; i < n / 2; i++) + Node node; + boolean v; + Edge e0,e1; + // iterate over first line of nodes + for (int i = 0; i < nDiv2; i++) { - Node node = nodes[i]; + node = nodes[i]; if (node.set) continue; - boolean v = false; + //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.on = v; - - if (node.edges.get(0).nighbor.set && node.edges.get(1).nighbor.set) + e0 = node.edges.get(0); e1 = node.edges.get(1); + if (e0.neighbor.set && e1.neighbor.set) break; - v ^= (!node.edges.get(0).nighbor.set) ? node.edges.get(0).broken : node.edges.get(1).broken; - node = (!node.edges.get(0).nighbor.set) ? node.edges.get(0).nighbor : node.edges.get(1).nighbor; + v ^= (!e0.neighbor.set) ? e0.broken : e1.broken; + node = (!e0.neighbor.set) ? e0.neighbor : e1.neighbor; } } } - + + //inner classes + private class Node { public boolean up; public List edges; - public int i, j; public boolean on; public boolean set; - public Node(int i, int j,boolean up) + public Node(boolean up) { - this.i = i; - this.j = j; this.up = up; edges = new ArrayList(); set = false; @@ -86,11 +104,11 @@ class Graph private class Edge { - public Node nighbor; + public Node neighbor; public boolean broken; - public Edge(Node nighbor, boolean broken) + public Edge(Node neighbor, boolean broken) { - this.nighbor = nighbor; + this.neighbor = neighbor; this.broken = broken; } } diff --git a/mixer/src/main/java/mixer/Mixer.java b/mixer/src/main/java/mixer/Mixer.java index c4d2952..e8fee4b 100644 --- a/mixer/src/main/java/mixer/Mixer.java +++ b/mixer/src/main/java/mixer/Mixer.java @@ -1,26 +1,20 @@ package mixer; -import java.math.BigInteger; import java.util.ArrayList; -import java.util.Dictionary; import java.util.List; import java.util.Queue; import java.util.concurrent.ArrayBlockingQueue; - -import com.google.protobuf.InvalidProtocolBufferException; - import javafx.util.Pair; - import java.util.Random; +import com.google.protobuf.InvalidProtocolBufferException; import meerkat.protobuf.Crypto.*; import meerkat.protobuf.Mixing.*; import meerkat.crypto.Encryption; -import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -public class Mixer{ +public class Mixer implements meerkat.crypto.mixnet.Mixer{ private Random random; private Mix2ZeroKnowledgeProver prover; @@ -34,7 +28,7 @@ public class Mixer{ } public Pair mix(List ciphertexts) throws InvalidProtocolBufferException{ - + int n = ciphertexts.size(); // assert n = 2^k and n > 1 if( n <= 1 || ((n & (n-1)) != 0)) @@ -47,7 +41,7 @@ public class Mixer{ } layers<<=1; layers--; - RerandomizableEncryptedMessage[][] encryptionsTable = new RerandomizableEncryptedMessage[layers][n]; + RerandomizableEncryptedMessage[][] encryptionTable = new RerandomizableEncryptedMessage[layers][n]; ZeroKnowledgeProof[][] proofsTable= new ZeroKnowledgeProof[layers][n/2]; boolean[][] mixnet = createMixNet(n,layers); int index1, index2, switchIndex = 0; @@ -55,39 +49,40 @@ public class Mixer{ RerandomizableEncryptedMessage e1, e2; boolean half = true; - //set first level of encryptions + //set first level of encryption for (int j = 0; j < n; j++) { - encryptionsTable[0][j] = ciphertexts.get(j); + encryptionTable[0][j] = ciphertexts.get(j); } - // main loop - for (int i = n, layer = 0; layer < layers; layer++) // i == permutation size + // main loop + int i = n; + for (int layer = 0; layer < layers; layer++) // i == permutation size { - for (int j = 0; j < n; j += i) // + for (int j = 0; j < n; j += i) // j == permutation index { - for (int k = 0; k < i / 2; k++) + for (int k = 0; k < i / 2; k++) // k == elements index in permutation j { index1 = k + j; index2 = k + j + i / 2; - e1 = encryptionsTable[layer][index1]; - e2 = encryptionsTable[layer][index2]; + e1 = encryptionTable[layer][index1]; + e2 = encryptionTable[layer][index2]; r1 = encryptor.generateRandomness(random); r2 = encryptor.generateRandomness(random); if (!mixnet[layer][switchIndex]) { - encryptionsTable[layer+1][index1] = encryptor.rerandomize(e1, r1); - encryptionsTable[layer+1][index2] = encryptor.rerandomize(e2,r2); + encryptionTable[layer+1][index1] = encryptor.rerandomize(e1, r1); + encryptionTable[layer+1][index2] = encryptor.rerandomize(e2,r2); } else { - encryptionsTable[layer+1][index1] = encryptor.rerandomize(e2,r2); - encryptionsTable[layer+1][index2] = encryptor.rerandomize(e1,r1); + encryptionTable[layer+1][index1] = encryptor.rerandomize(e2,r2); + encryptionTable[layer+1][index2] = encryptor.rerandomize(e1,r1); } proofsTable[layer][switchIndex] = - prover.prove(e1, e2, encryptionsTable[layer + 1][index1], - encryptionsTable[layer + 1][index2], + prover.prove(e1, e2, encryptionTable[layer + 1][index1], + encryptionTable[layer + 1][index2], mixnet[layer][switchIndex], r1,r2); switchIndex = (switchIndex + 1) % (n / 2); @@ -99,15 +94,13 @@ public class Mixer{ if (i == 1) { half = false; - i = 4; + i = 4; // avoid duplicate layer in the middle } } else - { - i <<= 1; - } + i <<= 1; } - return new Pair(proofsTable, encryptionsTable); + return new Pair(proofsTable, encryptionTable); } private int[] randomPermutation(int n){ @@ -130,23 +123,23 @@ public class Mixer{ private boolean[][] createMixNet(int n,int layers) { - int[] permutaion = randomPermutation(n); + int[] permutation = randomPermutation(n); int[] pi, piL, piR; - Queue permutaions = new ArrayBlockingQueue(n); + Queue permutationsQueue = new ArrayBlockingQueue(n); Graph graph; boolean[][] mixnet = new boolean[layers][n>>1]; - permutaions.add(permutaion); + permutationsQueue.add(permutation); for (int i = n, layer = 0; i > 1; i >>= 1, layer++) // i == permutation size - { - for (int j = 0; j < n / 2; j += i / 2) // + { + for (int j = 0; j < n / 2; j += i / 2) // j == permutation index { - pi = permutaions.remove(); + pi = permutationsQueue.remove(); graph = new Graph(pi); piL = new int[i / 2]; piR = new int[i / 2]; - for (int k = 0; k < i / 2; k++) + for (int k = 0; k < i / 2; k++) // k == switch index in permutation j { mixnet[layers - layer - 1][k + j] = graph.getSwitchValue(k, true); mixnet[layer][k + j] = graph.getSwitchValue(k, false); @@ -162,10 +155,10 @@ public class Mixer{ piR[k] = pi[k] % (i / 2); } } - permutaions.add(piL); - permutaions.add(piR); + permutationsQueue.add(piL); + permutationsQueue.add(piR); } - } + } return mixnet; }