diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1e04d9c..31ff232 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -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 diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java index a76b5fd..f13a225 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java @@ -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); diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index 763f46b..6a09e12 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -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; } diff --git a/mixer/src/main/java/main/MainMixing.java b/mixer/src/main/java/main/MainMixing.java new file mode 100644 index 0000000..25b61df --- /dev/null +++ b/mixer/src/main/java/main/MainMixing.java @@ -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 zeroKnowledgeProofsLists = downloadProofs(); + List 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 inputForMixer = + Arrays.asList(rerandomizableEncryptedMessageLists + .get(rerandomizableEncryptedMessageLists.size() - 1)[layers - 1]); + + updateBB(mixer.mix(inputForMixer)); + } + + private List downloadProofs() + { + return null; + } + + private List downloadEncryptionTable() + { + return null; + } + + private List getInputForFirstMixer() + { + return null; + } + + private void updateBB(Pair 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; + } +} diff --git a/mixer/src/main/java/mixer/MixNetwork.java b/mixer/src/main/java/mixer/MixNetwork.java index 219886f..da096d0 100644 --- a/mixer/src/main/java/mixer/MixNetwork.java +++ b/mixer/src/main/java/mixer/MixNetwork.java @@ -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 permutationsQueue = new ArrayBlockingQueue(n); Graph graph; @@ -64,26 +64,6 @@ public class MixNetwork { return switches[layer]; } - - - private int[] randomPermutation(int n){ - List numbers= new ArrayList(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; diff --git a/mixer/src/main/java/mixer/Mixer.java b/mixer/src/main/java/mixer/Mixer.java index 97981b7..b39a720 100644 --- a/mixer/src/main/java/mixer/Mixer.java +++ b/mixer/src/main/java/mixer/Mixer.java @@ -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(proofsTable, encryptionTable); diff --git a/mixer/src/main/java/mixer/RandomPermutation.java b/mixer/src/main/java/mixer/RandomPermutation.java new file mode 100644 index 0000000..900761b --- /dev/null +++ b/mixer/src/main/java/mixer/RandomPermutation.java @@ -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 numbers= new ArrayList(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; + } +} diff --git a/mixer/src/main/java/necessary/Group.java b/mixer/src/main/java/necessary/Group.java deleted file mode 100644 index 27c57d8..0000000 --- a/mixer/src/main/java/necessary/Group.java +++ /dev/null @@ -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(); -} diff --git a/mixer/src/main/java/necessary/GroupImpl.java b/mixer/src/main/java/necessary/GroupImpl.java deleted file mode 100644 index 5e98248..0000000 --- a/mixer/src/main/java/necessary/GroupImpl.java +++ /dev/null @@ -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 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(); - } -} - diff --git a/mixer/src/main/java/prover/Prover.java b/mixer/src/main/java/prover/Prover.java index 6c4c002..2de6f29 100644 --- a/mixer/src/main/java/prover/Prover.java +++ b/mixer/src/main/java/prover/Prover.java @@ -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 group; General general; Random rand; Encryption encryptor; - public Prover(Group group,Random rand,Encryption encryptor,General general) { + public Prover(Group 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) diff --git a/mixer/src/main/java/verifier/Verifier.java b/mixer/src/main/java/verifier/Verifier.java index 197e012..d70bd91 100644 --- a/mixer/src/main/java/verifier/Verifier.java +++ b/mixer/src/main/java/verifier/Verifier.java @@ -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())))); } } diff --git a/mixer/src/test/java/mixer/MixNetworkTest.java b/mixer/src/test/java/mixer/MixNetworkTest.java new file mode 100644 index 0000000..b783a2a --- /dev/null +++ b/mixer/src/test/java/mixer/MixNetworkTest.java @@ -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)); + + } + +}