Mixing + Mixer test

mixer
tzlil.gon 2015-12-17 19:15:48 +02:00
parent 767d73c143
commit c8646712c0
12 changed files with 276 additions and 125 deletions

View File

@ -1,4 +1,4 @@
#Mon Dec 14 14:35:37 IST 2015
#Thu Dec 17 12:20:25 IST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME

View File

@ -11,7 +11,7 @@ public interface Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
boolean switched,
boolean switched,int i,int j, int layer, // switch info
Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2);

View File

@ -44,8 +44,15 @@ message ZeroKnowledgeProof {
bytes z = 15;
bytes zTag = 16;
}
message Location{
int32 i = 1;
int32 j = 2;
int32 layer = 3;
}
OrProof first = 1;
OrProof second = 2;
OrProof third = 3;
OrProof fourth = 4;
Location location = 5;
}

View File

@ -0,0 +1,133 @@
package main;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.crypto.mixnet.Mixer;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import qilin.util.Pair;
import java.util.Arrays;
import java.util.List;
/**
* Created by Tzlil on 12/17/2015.
*/
public class MainMixing {
Mixer mixer;
Mix2ZeroKnowledgeVerifier verifier;
int n,layers;
public MainMixing(Mixer mixer, Mix2ZeroKnowledgeVerifier verifier, int n) {
this.mixer = mixer;
this.verifier = verifier;
this.n = n;
this.layers = (int) (2 * Math.log(n) / Math.log(2)) - 1; // layers = 2logn -1
}
private void firstMixing( ) throws Exception
{
updateBB(mixer.mix(getInputForFirstMixer()));
}
private void otherMixing() throws Exception
{
List<Mixing.ZeroKnowledgeProof[][]> zeroKnowledgeProofsLists = downloadProofs();
List<Crypto.RerandomizableEncryptedMessage[][]> rerandomizableEncryptedMessageLists = downloadEncryptionTable();
for (int i = 0; i < zeroKnowledgeProofsLists.size(); i++)
{
if(!verifyTable(n,layers,zeroKnowledgeProofsLists.get(i),rerandomizableEncryptedMessageLists.get(i)))
throw new Exception();
}
Crypto.RerandomizableEncryptedMessage[] lastLayerInCurrent,firstLineInNext;
for (int i = 0; i < rerandomizableEncryptedMessageLists.size() - 1 ; i++)
{
lastLayerInCurrent = rerandomizableEncryptedMessageLists.get(i)[layers - 1];
firstLineInNext = rerandomizableEncryptedMessageLists.get(i + 1)[0];
if(!Arrays.equals(lastLayerInCurrent,firstLineInNext))
throw new Exception();
}
List<Crypto.RerandomizableEncryptedMessage> inputForMixer =
Arrays.asList(rerandomizableEncryptedMessageLists
.get(rerandomizableEncryptedMessageLists.size() - 1)[layers - 1]);
updateBB(mixer.mix(inputForMixer));
}
private List<Mixing.ZeroKnowledgeProof[][]> downloadProofs()
{
return null;
}
private List<Crypto.RerandomizableEncryptedMessage[][]> downloadEncryptionTable()
{
return null;
}
private List<Crypto.RerandomizableEncryptedMessage> getInputForFirstMixer()
{
return null;
}
private void updateBB(Pair<Mixing.ZeroKnowledgeProof[][],Crypto.RerandomizableEncryptedMessage[][]> mixerOutput){
}
private boolean verifyTable(int n,int layers, Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs,
Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages)
{
int index1,index2,layer;
//initialize locationChecksum table
// use for check BeneshNet validity
boolean[][] locationChecksum = new boolean[layers][n];
for (boolean[] locationChecksumLayer: locationChecksum) {
Arrays.fill(locationChecksumLayer,false);
}
for (Mixing.ZeroKnowledgeProof[] zkpLayer: zeroKnowledgeProofs) {
for (Mixing.ZeroKnowledgeProof zkp: zkpLayer) {
Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation();
index1 = location.getI();
index2 = location.getJ();
layer = location.getLayer();
// check location validity
if (layer > layers >> 1) {
if (index2 - index1 != n >> (layers - layer))
return false;
}
else{
if (index2 - index1 != n >> (layer + 1))
return false;
}
// mark location in table
locationChecksum[layer][index1] = true;
locationChecksum[layer][index2] = true;
// verify proof
if(!verifier.verify(rerandomizableEncryptedMessages[index1][layer],
rerandomizableEncryptedMessages[index2][layer],
rerandomizableEncryptedMessages[index1][layer + 1],
rerandomizableEncryptedMessages[index2][layer + 1],
zkp))
return false;
}
}
// verify all necessary locations for BeneshNet were proved
for (boolean[] checksumLayer: locationChecksum) {
for (boolean locationBoolean: checksumLayer) {
if (!locationBoolean)
return false;
}
}
return true;
}
}

View File

@ -1,7 +1,5 @@
package mixer;
import com.google.protobuf.Enum;
import java.util.ArrayList;
import java.util.List;
import java.util.Queue;
@ -14,12 +12,14 @@ import java.util.Random;
public class MixNetwork {
private final Switch[][] switches;
private final Random random;
public MixNetwork(int n,int layers,Random random)
public MixNetwork(RandomPermutation randomPermutation)
{
this.random = random;
int[] permutation = randomPermutation(n);
int[] permutation = randomPermutation.permutation;
int n = permutation.length;
assert ((n & n-1) == 0); //n == 2^k
int layers = (int)(2*Math.log(n)/Math.log(2));
int[] pi, piL, piR;
Queue<int[]> permutationsQueue = new ArrayBlockingQueue<int[]>(n);
Graph graph;
@ -64,26 +64,6 @@ public class MixNetwork {
return switches[layer];
}
private int[] randomPermutation(int n){
List<Integer> numbers= new ArrayList<Integer>(n);
for (int i = 0; i < n; i++)
{
numbers.add(i);
}
int[] result = new int[n];
int index;
for (int i = 0; i < n; i++)
{
index = random.nextInt(n - i);
result[i] = numbers.get(index);
numbers.remove(index);
}
return result;
}
private class Graph {
private int n;
private int nDiv2;

View File

@ -42,7 +42,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
EncryptionRandomness r1, r2;
RerandomizableEncryptedMessage e1, e2;
boolean half = true;
MixNetwork mixNetwork = new MixNetwork(n,layers,random);
MixNetwork mixNetwork = new MixNetwork(new RandomPermutation(n,random));
Switch[] switchesLayer;
// set first level of encryption
@ -72,7 +72,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer {
proofsTable[layer][switchIndex] =
prover.prove(e1, e2, encryptionTable[layer + 1][index1],
encryptionTable[layer + 1][index2],
sw.value, r1, r2);
sw.value, sw.i,sw.j,sw.layer, r1, r2);
}
}
return new Pair<ZeroKnowledgeProof[][], RerandomizableEncryptedMessage[][]>(proofsTable, encryptionTable);

View File

@ -0,0 +1,32 @@
package mixer;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
/**
* Created by Tzlil on 12/17/2015.
*/
class RandomPermutation {
protected final int[] permutation;
protected RandomPermutation(int n,Random random)
{
List<Integer> numbers= new ArrayList<Integer>(n);
for (int i = 0; i < n; i++)
{
numbers.add(i);
}
int[] result = new int[n];
int index;
for (int i = 0; i < n; i++)
{
index = random.nextInt(n - i);
result[i] = numbers.get(index);
numbers.remove(index);
}
permutation = result;
}
}

View File

@ -1,14 +0,0 @@
package necessary;
import com.google.protobuf.ByteString;
import java.math.BigInteger;
public interface Group {
ByteString div(ByteString dividend, ByteString divisor);
ByteString mul(ByteString a, ByteString b);
ByteString pow(ByteString bas, BigInteger exp);
BigInteger groupSize();
}

View File

@ -1,39 +0,0 @@
package necessary;
import com.google.protobuf.ByteString;
import meerkat.protobuf.Crypto;
import java.math.BigInteger;
/**
* Created by Tzlil on 12/14/2015.
*/
public class GroupImpl implements Group {
qilin.primitives.Group<ByteString> qilinInstance;
public GroupImpl(qilin.primitives.Group qilinInstance) {
this.qilinInstance = qilinInstance;
}
@Override
public ByteString div(ByteString dividend, ByteString divisor) {
return mul(dividend,qilinInstance.negate(divisor));
}
@Override
public ByteString mul(ByteString a, ByteString b) {
return qilinInstance.add(a,b);
}
@Override
public ByteString pow(ByteString bas, BigInteger exp) {
return qilinInstance.multiply(bas,exp);
}
@Override
public BigInteger groupSize() {
return qilinInstance.orderUpperBound();
}
}

View File

@ -7,20 +7,19 @@ import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import necessary.General;
import necessary.Group;
import qilin.primitives.Group;
import java.math.BigInteger;
import java.util.Random;
public class Prover implements Mix2ZeroKnowledgeProver {
Group group;
Group<ByteString> group;
General general;
Random rand;
Encryption encryptor;
public Prover(Group group,Random rand,Encryption encryptor,General general) {
public Prover(Group<ByteString> group,Random rand,Encryption encryptor,General general) {
this.group = group;
this.rand = rand;
this.encryptor = encryptor;
@ -31,7 +30,7 @@ public class Prover implements Mix2ZeroKnowledgeProver {
Crypto.RerandomizableEncryptedMessage in2,
Crypto.RerandomizableEncryptedMessage out1,
Crypto.RerandomizableEncryptedMessage out2,
boolean sw,
boolean sw,int i,int j, int layer,
Crypto.EncryptionRandomness r1,
Crypto.EncryptionRandomness r2) {
@ -50,11 +49,17 @@ public class Prover implements Mix2ZeroKnowledgeProver {
third = createOrProof(in2, out1, in2, out2, r2, true);
fourth = createOrProof(in1, out2, in2, out2, r1, true);
}
Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder()
.setI(i)
.setJ(j)
.setLayer(layer)
.build();
return Mixing.ZeroKnowledgeProof.newBuilder()
.setFirst(first)
.setSecond(second)
.setThird(third)
.setFourth(fourth)
.setLocation(location)
.build();
}
@ -74,6 +79,8 @@ public class Prover implements Mix2ZeroKnowledgeProver {
return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag);
}
private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1,
ElGamalCiphertext e2,
ElGamalCiphertext e1New,
@ -81,27 +88,27 @@ public class Prover implements Mix2ZeroKnowledgeProver {
Crypto.EncryptionRandomness x,
boolean flag) {
ByteString g1 = general.getG();
ByteString h1 = group.div(e1New.getC1(),e1.getC1());
ByteString h1 = group.add(e1New.getC1(),group.negate(e1.getC1()));
ByteString g2 = general.getH();
ByteString h2 = group.div(e1New.getC2(),e1.getC2());
ByteString h2 = group.add(e1New.getC2(),group.negate(e1.getC2()));
ByteString g1Tag = general.getG();
ByteString h1Tag = group.div(e2New.getC1(),e2.getC1());
ByteString h1Tag = group.add(e2New.getC1(),group.negate(e2.getC1()));
ByteString g2Tag = general.getH();
ByteString h2Tag = group.div(e2New.getC2(),e2.getC2());
ByteString h2Tag = group.add(e2New.getC2(),group.negate(e2.getC2()));
BigInteger r = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.groupSize());
BigInteger r = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
BigInteger c1,c2,z,zTag;
ByteString u,v,uTag,vTag;
if (flag)
{
c2 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.groupSize());
zTag = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.groupSize());
c2 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
zTag = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1
u = group.pow(g1, r);
v = group.pow(g2, r);
uTag = group.div(group.pow(g1Tag, zTag), group.pow(h1Tag, c2));
vTag = group.div(group.pow(g2Tag, zTag), group.pow(h2Tag, c2));
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
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
@ -119,20 +126,20 @@ public class Prover implements Mix2ZeroKnowledgeProver {
.setUTag(uTag)
.setVTag(vTag)
.build();
c1 = general.hash(forRandomOracle).add(group.groupSize().subtract(c2)).mod(group.groupSize());
c1 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound());
//step 3
//z = (r + c1 * x) % group size;
z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.groupSize());
z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
}
else
{
c1 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.groupSize());
z = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.groupSize());
c1 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
z = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound());
//step 1
uTag = group.pow(g1Tag, r);
vTag = group.pow(g2Tag, r);
u = group.div(group.pow(g1, z), group.pow(h1, c1));
v = group.div(group.pow(g2, z), group.pow(h2, c1));
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
Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle =
@ -150,10 +157,10 @@ public class Prover implements Mix2ZeroKnowledgeProver {
.setUTag(uTag)
.setVTag(vTag)
.build();
c2 = general.hash(forRandomOracle).add(group.groupSize().subtract(c1)).mod(group.groupSize());
c2 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound());
//step 3
//zTag = (r + c2 * x) % group size;
zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.groupSize());
zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound());
}
return Mixing.ZeroKnowledgeProof.OrProof.newBuilder()
.setG1(g1)

View File

@ -1,12 +1,11 @@
package verifier;
import meerkat.crypto.Encryption;
import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier;
import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext;
import meerkat.protobuf.Crypto;
import meerkat.protobuf.Mixing;
import necessary.General;
import necessary.Group;
import qilin.primitives.Group;
import java.math.BigInteger;
@ -42,6 +41,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(out1);
ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(out2);
return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFirst()) &&
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getSecond()) &&
verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getThird()) &&
@ -73,28 +73,28 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier {
return //input
orProof.getG1().equals(general.getG())&&
orProof.getH1().equals(group.div(e1New.getC1(), e1.getC1()))&&
orProof.getH1().equals(group.add(e1New.getC1(), group.negate(e1.getC1())))&&
orProof.getG2().equals(general.getH())&&
orProof.getH2().equals(group.div(e1New.getC2(), e1.getC2()))&&
orProof.getH2().equals(group.add(e1New.getC2(), group.negate(e1.getC2())))&&
// input'
orProof.getG1Tag().equals(general.getG())&&
orProof.getH1Tag().equals(group.div(e2New.getC1(), e2.getC1()))&&
orProof.getH1Tag().equals(group.add(e2New.getC1(), group.negate(e2.getC1())))&&
orProof.getG2Tag().equals(general.getH())&&
orProof.getH2Tag().equals(group.div(e2New.getC2(), e2.getC2())) &&
orProof.getH2Tag().equals(group.add(e2New.getC2(), group.negate(e2.getC2()))) &&
// hash
// assert (c1 + c2 ) % group size == hash (imput + step1) % group size
new BigInteger(orProof.getC1().toByteArray()).add(new BigInteger(orProof.getC2().toByteArray())).mod(group.groupSize())
.equals(general.hash(forRandomOracle).mod(group.groupSize()).mod(group.groupSize()))&&
new BigInteger(orProof.getC1().toByteArray()).add(new BigInteger(orProof.getC2().toByteArray())).mod(group.orderUpperBound())
.equals(general.hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()))&&
// proof
// g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case
group.pow(orProof.getG1(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.mul(orProof.getU(), group.pow(orProof.getH1(),new BigInteger(orProof.getC1().toByteArray())))) &&
group.pow(orProof.getG2(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.mul(orProof.getV(), group.pow(orProof.getH2(),new BigInteger(orProof.getC1().toByteArray())))) &&
group.pow(orProof.getG1Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.mul(orProof.getUTag(), group.pow(orProof.getH1Tag(),new BigInteger(orProof.getC2().toByteArray())))) &&
group.pow(orProof.getG2Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.mul(orProof.getVTag(), group.pow(orProof.getH2Tag(),new BigInteger(orProof.getC2().toByteArray()))));
group.multiply(orProof.getG1(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.add(orProof.getU(), group.multiply(orProof.getH1(),new BigInteger(orProof.getC1().toByteArray())))) &&
group.multiply(orProof.getG2(), new BigInteger(orProof.getZ().toByteArray()))
.equals(group.add(orProof.getV(), group.multiply(orProof.getH2(),new BigInteger(orProof.getC1().toByteArray())))) &&
group.multiply(orProof.getG1Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.add(orProof.getUTag(), group.multiply(orProof.getH1Tag(),new BigInteger(orProof.getC2().toByteArray())))) &&
group.multiply(orProof.getG2Tag(), new BigInteger(orProof.getZTag().toByteArray()))
.equals(group.add(orProof.getVTag(), group.multiply(orProof.getH2Tag(),new BigInteger(orProof.getC2().toByteArray()))));
}
}

View File

@ -0,0 +1,45 @@
package mixer;
/**
* Created by Tzlil on 12/17/2015.
*/
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();
int logn = random.nextInt()%10 + 5;
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));
}
}