diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java index c281dd7..910a1aa 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java @@ -109,6 +109,15 @@ public class ECElGamalEncryption extends GlobalCryptoSetup implements Encryption .build(); } + public static ConcreteCrypto.ElGamalCiphertext rerandomizableEncryptedMessage2ElGamalCiphertext(Crypto.RerandomizableEncryptedMessage msg) throws InvalidProtocolBufferException { + return ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData()); + } + + public static Crypto.RerandomizableEncryptedMessage elGamalCiphertext2RerandomizableEncryptedMessage(ConcreteCrypto.ElGamalCiphertext msg) { + return Crypto.RerandomizableEncryptedMessage.newBuilder() + .setData(msg.toByteString()).build(); + } + @Override public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException { BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); 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 f13a225..487483e 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java @@ -1,5 +1,6 @@ package meerkat.crypto.mixnet; +import com.google.protobuf.InvalidProtocolBufferException; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -13,7 +14,7 @@ public interface Mix2ZeroKnowledgeProver { Crypto.RerandomizableEncryptedMessage out2, boolean switched,int i,int j, int layer, // switch info Crypto.EncryptionRandomness r1, - Crypto.EncryptionRandomness r2); + Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException; } diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java index dd3c251..f98f0ac 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java @@ -1,5 +1,6 @@ package meerkat.crypto.mixnet; +import com.google.protobuf.InvalidProtocolBufferException; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -19,5 +20,5 @@ public interface Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, - Mixing.ZeroKnowledgeProof proof); + Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException; } diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index 6a09e12..83c87d6 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -6,6 +6,10 @@ option java_package = "meerkat.protobuf"; import 'meerkat/crypto.proto'; +message Plaintext{ + bytes data = 1; +} + message ZeroKnowledgeProof { message OrProof { message ForRandomOracle{ diff --git a/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java b/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java index fec4803..425ec50 100644 --- a/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java +++ b/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java @@ -49,7 +49,7 @@ public class ECElGamalUtils { .setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build(); return serializedPk; - } catch (NoSuchAlgorithmException|InvalidKeySpecException e) { + } catch (Exception e) { logger.error("Should never happen!", e); throw new RuntimeException("Error converting public key!", e); } diff --git a/mixer/src/main/java/main/MainMixing.java b/mixer/src/main/java/main/MainMixing.java index 70423c5..ab832d7 100644 --- a/mixer/src/main/java/main/MainMixing.java +++ b/mixer/src/main/java/main/MainMixing.java @@ -206,8 +206,7 @@ public class MainMixing { } - private boolean verifyTable() - { + private boolean verifyTable() throws InvalidProtocolBufferException { int index1,index2,layer; //initialize locationChecksum table diff --git a/mixer/src/main/java/mixer/Mixer.java b/mixer/src/main/java/mixer/Mixer.java index b39a720..1de3a91 100644 --- a/mixer/src/main/java/mixer/Mixer.java +++ b/mixer/src/main/java/mixer/Mixer.java @@ -2,6 +2,8 @@ package mixer; import java.util.ArrayList; import java.util.List; + +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import qilin.util.Pair; import java.util.Random; @@ -12,20 +14,23 @@ import meerkat.protobuf.Mixing.*; import meerkat.crypto.Encryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import verifier.Verifier; public class Mixer implements meerkat.crypto.mixnet.Mixer { private Random random; private Mix2ZeroKnowledgeProver prover; private Encryption encryptor; + private Mix2ZeroKnowledgeVerifier verifier; public Mixer(Random rand, Mix2ZeroKnowledgeProver prov, Encryption enc) { this.random = rand; this.prover = prov; this.encryptor = enc; - + this.verifier = null; } + public Pair mix(List ciphertexts) throws InvalidProtocolBufferException { int n = ciphertexts.size(); @@ -50,6 +55,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { encryptionTable[0][j] = ciphertexts.get(j); } + // main loop for (int layer = 0; layer < layers; layer++) { @@ -73,6 +79,8 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { prover.prove(e1, e2, encryptionTable[layer + 1][index1], encryptionTable[layer + 1][index2], sw.value, sw.i,sw.j,sw.layer, r1, r2); + + switchIndex = (switchIndex + 1) % nDiv2; } } return new Pair(proofsTable, encryptionTable); diff --git a/mixer/src/main/java/mixer/Switch.java b/mixer/src/main/java/mixer/Switch.java index c52e1fc..a7401ff 100644 --- a/mixer/src/main/java/mixer/Switch.java +++ b/mixer/src/main/java/mixer/Switch.java @@ -14,4 +14,15 @@ public class Switch{ this.layer = layer; this.value = value; } + + + @Override + public String toString() { + return "Switch{" + + "i=" + i + + ", j=" + j + + ", layer=" + layer + + ", value=" + value + + '}'; + } } diff --git a/mixer/src/main/java/necessary/General.java b/mixer/src/main/java/necessary/General.java deleted file mode 100644 index 92df602..0000000 --- a/mixer/src/main/java/necessary/General.java +++ /dev/null @@ -1,25 +0,0 @@ -package necessary; - -import meerkat.protobuf.ConcreteCrypto; -import meerkat.protobuf.Crypto; - -import com.google.protobuf.ByteString; -import meerkat.protobuf.Mixing; - -import java.math.BigInteger; - -public interface General { - - /* - given RerandomizableEncryptedMessage returns an equivalent ElGamalCiphertext - */ - ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc); - - ByteString getG(); - ByteString getH(); - - /* - fiat shamir assumption - */ - BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input); -} diff --git a/mixer/src/main/java/necessary/GeneralImpl.java b/mixer/src/main/java/necessary/GeneralImpl.java deleted file mode 100644 index 9a4fda6..0000000 --- a/mixer/src/main/java/necessary/GeneralImpl.java +++ /dev/null @@ -1,46 +0,0 @@ -package necessary; - -import com.google.protobuf.ByteString; -import meerkat.protobuf.ConcreteCrypto; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; -import qilin.primitives.RandomOracle; -import java.math.BigInteger; - -/** - * Created by Tzlil on 12/14/2015. - */ -public class GeneralImpl implements General { - - - private final RandomOracle rndomOracle; - private final ByteString h; - private final ByteString g; - - public GeneralImpl(RandomOracle randomOracle,ByteString g,ByteString h) { - this.rndomOracle = randomOracle; - this.h = h; - this.g = g; - } - - @Override - public ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc) { - return null; - } - - @Override - public ByteString getG() { - return g; - } - - @Override - public ByteString getH() { - return h; - } - - @Override - public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) { - byte[] arr = input.toByteArray(); - return new BigInteger(this.rndomOracle.hash(arr,arr.length)); - } -} diff --git a/mixer/src/main/java/prover/ProofOrganizer.java b/mixer/src/main/java/prover/ProofOrganizer.java new file mode 100644 index 0000000..3dae29c --- /dev/null +++ b/mixer/src/main/java/prover/ProofOrganizer.java @@ -0,0 +1,76 @@ +package prover; + +import meerkat.protobuf.Crypto; + +/** + * Created by Tzlil on 12/30/2015. + */ +public class ProofOrganizer { + + private final Crypto.RerandomizableEncryptedMessage e1; + private final Crypto.RerandomizableEncryptedMessage e2; + private final Crypto.RerandomizableEncryptedMessage e1New; + private final Crypto.RerandomizableEncryptedMessage e2New; + + //in1, out1, in2, out1, + //in1, out1, in1, out2 + //in2, out1, in2, out2, + //in1, out2, in2, out2 + public ProofOrganizer(Crypto.RerandomizableEncryptedMessage e1,Crypto.RerandomizableEncryptedMessage e2 + ,Crypto.RerandomizableEncryptedMessage e1New,Crypto.RerandomizableEncryptedMessage e2New) + { + this.e1 = e1; + this.e2 = e2; + this.e1New = e1New; + this.e2New = e2New; + + } + + public enum OrProofOrder{ + first,second,third,fourth + } + + public Crypto.RerandomizableEncryptedMessage getE1(OrProofOrder orProofOrder) + { + switch (orProofOrder){ + case third: + return e2; + default: + return e1; + } + + } + + public Crypto.RerandomizableEncryptedMessage getE1New(OrProofOrder orProofOrder) + { + switch (orProofOrder){ + case fourth: + return e2New; + default: + return e1New; + } + + } + + public Crypto.RerandomizableEncryptedMessage getE2(OrProofOrder orProofOrder) + { + switch (orProofOrder){ + case second: + return e1; + default: + return e2; + } + + } + + public Crypto.RerandomizableEncryptedMessage getE2New(OrProofOrder orProofOrder) + { + switch (orProofOrder){ + case first: + return e1New; + default: + return e2New; + } + + } +} diff --git a/mixer/src/main/java/prover/Prover.java b/mixer/src/main/java/prover/Prover.java index 2de6f29..7712a41 100644 --- a/mixer/src/main/java/prover/Prover.java +++ b/mixer/src/main/java/prover/Prover.java @@ -1,66 +1,135 @@ package prover; import com.google.protobuf.ByteString; -import meerkat.crypto.Encryption; +import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; -import necessary.General; -import qilin.primitives.Group; +import org.bouncycastle.math.ec.ECPoint; +import qilin.primitives.RandomOracle; +import qilin.primitives.concrete.ECGroup; import java.math.BigInteger; import java.util.Random; public class Prover implements Mix2ZeroKnowledgeProver { - Group group; - General general; + ECGroup group; + RandomOracle randomOracle; Random rand; - Encryption encryptor; + ECElGamalEncryption ecElGamalEncryption; + ECPoint g,h; + + Mix2ZeroKnowledgeVerifier verifier; + + public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) { - public Prover(Group group,Random rand,Encryption encryptor,General general) { - this.group = group; this.rand = rand; - this.encryptor = encryptor; - this.general = general; + this.ecElGamalEncryption = encryptor; + this.randomOracle = randomOracle; + this.group = ecElGamalEncryption.getGroup(); + this.g = group.getGenerator(); + this.h = ecElGamalEncryption.getElGamalPK().getPK(); + + verifier = null; } + public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle,Mix2ZeroKnowledgeVerifier verifier) { + + this.rand = rand; + this.ecElGamalEncryption = encryptor; + this.randomOracle = randomOracle; + this.group = ecElGamalEncryption.getGroup(); + this.g = group.getGenerator(); + this.h = ecElGamalEncryption.getElGamalPK().getPK(); + + this.verifier = verifier; + } + + + public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, boolean sw,int i,int j, int layer, Crypto.EncryptionRandomness r1, - Crypto.EncryptionRandomness r2) { + Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; + ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2); if (!sw) { - first = createOrProof(in1, out1, in2, out1, r1, true); - second = createOrProof(in1, out1, in1, out2, r1, true); - third = createOrProof(in2, out1, in2, out2, r2, false); - fourth = createOrProof(in1, out2, in2, out2, r2, false); + first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), + organizer.getE2(ProofOrganizer.OrProofOrder.first), + organizer.getE1New(ProofOrganizer.OrProofOrder.first), + organizer.getE2New(ProofOrganizer.OrProofOrder.first), + r1, true); + second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), + organizer.getE2(ProofOrganizer.OrProofOrder.second), + organizer.getE1New(ProofOrganizer.OrProofOrder.second), + organizer.getE2New(ProofOrganizer.OrProofOrder.second), r1, true); + third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), + organizer.getE2(ProofOrganizer.OrProofOrder.third), + organizer.getE1New(ProofOrganizer.OrProofOrder.third), + organizer.getE2New(ProofOrganizer.OrProofOrder.third), r2, false); + fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2(ProofOrganizer.OrProofOrder.fourth), + organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), r2, false); } else { - first = createOrProof(in1, out1, in2, out1, r2, false); - second = createOrProof(in1, out1, in1, out2, r1, false); - third = createOrProof(in2, out1, in2, out2, r2, true); - fourth = createOrProof(in1, out2, in2, out2, r1, true); + first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), + organizer.getE2(ProofOrganizer.OrProofOrder.first), + organizer.getE1New(ProofOrganizer.OrProofOrder.first), + organizer.getE2New(ProofOrganizer.OrProofOrder.first), + r2, false); + second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), + organizer.getE2(ProofOrganizer.OrProofOrder.second), + organizer.getE1New(ProofOrganizer.OrProofOrder.second), + organizer.getE2New(ProofOrganizer.OrProofOrder.second), + r1, false); + third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), + organizer.getE2(ProofOrganizer.OrProofOrder.third), + organizer.getE1New(ProofOrganizer.OrProofOrder.third), + organizer.getE2New(ProofOrganizer.OrProofOrder.third), + r2, true); + fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2(ProofOrganizer.OrProofOrder.fourth), + organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), + r1, true); } Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() .setI(i) .setJ(j) .setLayer(layer) .build(); - return Mixing.ZeroKnowledgeProof.newBuilder() + + + + Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder() .setFirst(first) .setSecond(second) .setThird(third) .setFourth(fourth) .setLocation(location) .build(); + + //debuging + if (verifier != null){ + if (!verifier.verify(in1,in2,out1,out2,result)){ + + System.out.print(location.toString()); + System.out.println("switch value : " + sw); + } + } + + return result; } private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1, @@ -68,42 +137,51 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.RerandomizableEncryptedMessage e1New, Crypto.RerandomizableEncryptedMessage e2New, Crypto.EncryptionRandomness x, - boolean flag){ - - ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(e1); - ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(e2); - ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(e1New); - ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(e2New); + boolean flag) throws InvalidProtocolBufferException { + ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1); + ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2); + ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1New); + ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2New); return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag); } - + private ECPoint convert2ECPoint(ByteString bs){ + return group.decode(bs.toByteArray()); + } + + public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) { + byte[] arr = input.toByteArray(); + return new BigInteger(this.randomOracle.hash(arr,arr.length)); + } + + private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1, ElGamalCiphertext e2, ElGamalCiphertext e1New, ElGamalCiphertext e2New, Crypto.EncryptionRandomness x, boolean flag) { - ByteString g1 = general.getG(); - ByteString h1 = group.add(e1New.getC1(),group.negate(e1.getC1())); - ByteString g2 = general.getH(); - ByteString h2 = group.add(e1New.getC2(),group.negate(e1.getC2())); - ByteString g1Tag = general.getG(); - ByteString h1Tag = group.add(e2New.getC1(),group.negate(e2.getC1())); - ByteString g2Tag = general.getH(); - ByteString h2Tag = group.add(e2New.getC2(),group.negate(e2.getC2())); + ECPoint g1 = g; + ECPoint h1 = group.add(convert2ECPoint(e1New.getC1()),group.negate(convert2ECPoint(e1.getC1()))); + ECPoint g2 = h; + ECPoint h2 = group.add(convert2ECPoint(e1New.getC2()),group.negate(convert2ECPoint(e1.getC2()))); - BigInteger r = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + ECPoint g1Tag = g; + ECPoint h1Tag = group.add(convert2ECPoint(e2New.getC1()),group.negate(convert2ECPoint(e2.getC1()))); + ECPoint g2Tag = h; + ECPoint h2Tag = group.add(convert2ECPoint(e2New.getC2()),group.negate(convert2ECPoint(e2.getC2()))); + + BigInteger r = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); BigInteger c1,c2,z,zTag; - ByteString u,v,uTag,vTag; + ECPoint u,v,uTag,vTag; if (flag) { - c2 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - zTag = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + c2 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + zTag = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); //step 1 u = group.multiply(g1, r); v = group.multiply(g2, r); @@ -113,28 +191,28 @@ public class Prover implements Mix2ZeroKnowledgeProver { // c1 = (hash(input + step1) + group size - c2)% group size Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(g1) - .setH1(h1) - .setG2(g2) - .setH2(h2) - .setG1Tag(g1Tag) - .setH1Tag(h1Tag) - .setG2Tag(g2Tag) - .setH2Tag(h2Tag) - .setU(u) - .setV(v) - .setUTag(uTag) - .setVTag(vTag) + .setG1(ByteString.copyFrom(group.encode(g1))) + .setH1(ByteString.copyFrom(group.encode(h1))) + .setG2(ByteString.copyFrom(group.encode(g2))) + .setH2(ByteString.copyFrom(group.encode(h2))) + .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) + .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) + .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) + .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) + .setU(ByteString.copyFrom(group.encode(u))) + .setV(ByteString.copyFrom(group.encode(v))) + .setUTag(ByteString.copyFrom(group.encode(uTag))) + .setVTag(ByteString.copyFrom(group.encode(vTag))) .build(); - c1 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound()); + c1 = 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.orderUpperBound()); } else { - c1 = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - z = new BigInteger(encryptor.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + c1 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + z = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); //step 1 uTag = group.multiply(g1Tag, r); vTag = group.multiply(g2Tag, r); @@ -144,37 +222,37 @@ public class Prover implements Mix2ZeroKnowledgeProver { // c1 = (hash(input + step1) + group size - c1)% group size Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(g1) - .setH1(h1) - .setG2(g2) - .setH2(h2) - .setG1Tag(g1Tag) - .setH1Tag(h1Tag) - .setG2Tag(g2Tag) - .setH2Tag(h2Tag) - .setU(u) - .setV(v) - .setUTag(uTag) - .setVTag(vTag) + .setG1(ByteString.copyFrom(group.encode(g1))) + .setH1(ByteString.copyFrom(group.encode(h1))) + .setG2(ByteString.copyFrom(group.encode(g2))) + .setH2(ByteString.copyFrom(group.encode(h2))) + .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) + .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) + .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) + .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) + .setU(ByteString.copyFrom(group.encode(u))) + .setV(ByteString.copyFrom(group.encode(v))) + .setUTag(ByteString.copyFrom(group.encode(uTag))) + .setVTag(ByteString.copyFrom(group.encode(vTag))) .build(); - c2 = general.hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound()); + c2 = 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.orderUpperBound()); } return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() - .setG1(g1) - .setH1(h1) - .setG2(g2) - .setH2(h2) - .setG1Tag(g1Tag) - .setH1Tag(h1Tag) - .setG2Tag(g2Tag) - .setH2Tag(h2Tag) - .setU(u) - .setV(v) - .setUTag(uTag) - .setVTag(vTag) + .setG1(ByteString.copyFrom(group.encode(g1))) + .setH1(ByteString.copyFrom(group.encode(h1))) + .setG2(ByteString.copyFrom(group.encode(g2))) + .setH2(ByteString.copyFrom(group.encode(h2))) + .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) + .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) + .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) + .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) + .setU(ByteString.copyFrom(group.encode(u))) + .setV(ByteString.copyFrom(group.encode(v))) + .setUTag(ByteString.copyFrom(group.encode(uTag))) + .setVTag(ByteString.copyFrom(group.encode(vTag))) .setC1(ByteString.copyFrom(c1.toByteArray())) .setC2(ByteString.copyFrom(c2.toByteArray())) .setZ(ByteString.copyFrom(z.toByteArray())) diff --git a/mixer/src/main/java/verifier/Verifier.java b/mixer/src/main/java/verifier/Verifier.java index d70bd91..19549ce 100644 --- a/mixer/src/main/java/verifier/Verifier.java +++ b/mixer/src/main/java/verifier/Verifier.java @@ -1,17 +1,24 @@ package verifier; +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; -import necessary.General; -import qilin.primitives.Group; +import org.bouncycastle.math.ec.ECPoint; +import prover.ProofOrganizer; +import qilin.primitives.RandomOracle; +import qilin.primitives.concrete.ECGroup; import java.math.BigInteger; +import java.util.List; public class Verifier implements Mix2ZeroKnowledgeVerifier { + /** * Return true iff the proof is valid. * @param in1 @@ -21,38 +28,78 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { * @return */ - Group group; - General general; + ECGroup group; + RandomOracle randomOracle; + ECElGamalEncryption encryptor; + ECPoint g,h; - public Verifier(Group group,General general) { - this.group = group; - this.general = general; + public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) { + this.encryptor = encryptor; + this.group = encryptor.getGroup(); + this.g = group.getGenerator(); + this.h = encryptor.getElGamalPK().getPK(); + this.randomOracle = randomOracle; } + public BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input) { + byte[] arr = input.toByteArray(); + return new BigInteger(this.randomOracle.hash(arr,arr.length)); + } + + private ECPoint convert2ECPoint(ByteString bs){ + return group.decode(bs.toByteArray()); + } + + public boolean verify(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, - Mixing.ZeroKnowledgeProof proof) - { + Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { - ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(in1); - ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(in2); - ElGamalCiphertext e1TagElGamal = general.calcRerandomizable2ElGamal(out1); - ElGamalCiphertext e2TagElGamal = general.calcRerandomizable2ElGamal(out2); + ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2); + return verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), + organizer.getE2(ProofOrganizer.OrProofOrder.first), + organizer.getE1New(ProofOrganizer.OrProofOrder.first), + organizer.getE2New(ProofOrganizer.OrProofOrder.first), + proof.getFirst(),ProofOrganizer.OrProofOrder.first)&& + verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), + organizer.getE2(ProofOrganizer.OrProofOrder.second), + organizer.getE1New(ProofOrganizer.OrProofOrder.second), + organizer.getE2New(ProofOrganizer.OrProofOrder.second), + proof.getSecond(),ProofOrganizer.OrProofOrder.second)&& + verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), + organizer.getE2(ProofOrganizer.OrProofOrder.third), + organizer.getE1New(ProofOrganizer.OrProofOrder.third), + organizer.getE2New(ProofOrganizer.OrProofOrder.third), + proof.getThird(),ProofOrganizer.OrProofOrder.third)&& + verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2(ProofOrganizer.OrProofOrder.fourth), + organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), + organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), + proof.getFourth(),ProofOrganizer.OrProofOrder.fourth); + } - return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFirst()) && - verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getSecond()) && - verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getThird()) && - verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFourth()); + + public boolean verifyOrProof(Crypto.RerandomizableEncryptedMessage e1, + Crypto.RerandomizableEncryptedMessage e2, + Crypto.RerandomizableEncryptedMessage e1Tag, + Crypto.RerandomizableEncryptedMessage e2Tag, + Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder) throws InvalidProtocolBufferException { + + ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1); + ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2); + ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1Tag); + ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2Tag); + return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof,orProofOrder); } public boolean verifyElGamaOrProof(ElGamalCiphertext e1, ElGamalCiphertext e2, ElGamalCiphertext e1New, ElGamalCiphertext e2New, - Mixing.ZeroKnowledgeProof.OrProof orProof) + Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder) { Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = @@ -71,30 +118,107 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { .setVTag(orProof.getVTag()) .build(); + ECPoint g1,g2,h1,h2; + ECPoint g1Tag,g2Tag,h1Tag,h2Tag; + g1 = convert2ECPoint(orProof.getG1()); + g2 = convert2ECPoint(orProof.getG2()); + h1 = convert2ECPoint(orProof.getH1()); + h2 = convert2ECPoint(orProof.getH2()); + g1Tag = convert2ECPoint(orProof.getG1Tag()); + g2Tag = convert2ECPoint(orProof.getG2Tag()); + h1Tag = convert2ECPoint(orProof.getH1Tag()); + h2Tag = convert2ECPoint(orProof.getH2Tag()); + + ECPoint u,v,uTag,vTag; + u = convert2ECPoint(orProof.getU()); + v = convert2ECPoint(orProof.getV()); + uTag = convert2ECPoint(orProof.getUTag()); + vTag = convert2ECPoint(orProof.getVTag()); + + BigInteger c1,c2,z,zTag; + c1 = new BigInteger(orProof.getC1().toByteArray()); + c2 = new BigInteger(orProof.getC2().toByteArray()); + z = new BigInteger(orProof.getZ().toByteArray()); + zTag = new BigInteger(orProof.getZTag().toByteArray()); + + ECPoint[] given = new ECPoint[12]; + ECPoint[] expected = new ECPoint[12]; + String[] description = new String[12]; + int i = 0; + given[i++] = g1; + given[i++] = h1; + given[i++] = g2; + given[i++] = h2; + given[i++] = g1Tag; + given[i++] = h1Tag; + given[i++] = g2Tag; + given[i++] = h2Tag; + given[i++] = group.multiply(g1, z); + given[i++] = group.multiply(g2, z); + given[i++] = group.multiply(g1Tag, zTag); + given[i] = group.multiply(g2Tag, zTag); + i = 0; + expected[i++] = g; + expected[i++] = group.add(convert2ECPoint(e1New.getC1()), group.negate(convert2ECPoint(e1.getC1()))); + expected[i++] = h; + expected[i++] = group.add(convert2ECPoint(e1New.getC2()), group.negate(convert2ECPoint(e1.getC2()))); + expected[i++] = g; + expected[i++] = group.add(convert2ECPoint(e2New.getC1()), group.negate(convert2ECPoint(e2.getC1()))); + expected[i++] = h; + expected[i++] = group.add(convert2ECPoint(e2New.getC2()), group.negate(convert2ECPoint(e2.getC2()))); + expected[i++] = group.add(u, group.multiply(h1,c1)); + expected[i++] = group.add(v, group.multiply(h2,c1)); + expected[i++] = group.add(uTag, group.multiply(h1Tag,c2)); + expected[i] = group.add(vTag, group.multiply(h2Tag,c2)); + i = 0; + description[i++] = "g1 != g"; + description[i++] = "h1 != e1New.c1/e1.c1"; + description[i++] = "g2 != h"; + description[i++] = "h2 != e1New.c2/e1.c2"; + description[i++] = "g1Tag != g"; + description[i++] = "h1Tag != e2New.c1/e2.c1"; + description[i++] = "g2Tag != h"; + description[i++] = "h2Tag != e2New.c2/e2.c2"; + description[i++] = "g1 ^ z != u * ( h1 ^ c1 )"; + description[i++] = "g2 ^ z != v * ( h2 ^ c1 )"; + description[i++] = "g1Tag ^ zTag != uTag * ( h1Tag ^ c2 )"; + description[i] = "g2Tag ^ zTag != vTag * ( h2Tag ^ c2 )"; + boolean first = true; + for (int j = 0; j < given.length ; j++){ + if(!given[j].equals(expected[j])){ + if (first){ + first = false; + System.out.print("\n\n\n"); + System.out.println(orProofOrder.toString()); + } + System.out.println(description[j]); + } + } + return //input - orProof.getG1().equals(general.getG())&& - orProof.getH1().equals(group.add(e1New.getC1(), group.negate(e1.getC1())))&& - orProof.getG2().equals(general.getH())&& - orProof.getH2().equals(group.add(e1New.getC2(), group.negate(e1.getC2())))&& + g1.equals(g)&& + h1.equals(group.add(convert2ECPoint(e1New.getC1()) + , group.negate(convert2ECPoint(e1.getC1()))))&& + g2.equals(h)&& + h2.equals(group.add(convert2ECPoint(e1New.getC2()) + , group.negate(convert2ECPoint(e1.getC2()))))&& // input' - orProof.getG1Tag().equals(general.getG())&& - orProof.getH1Tag().equals(group.add(e2New.getC1(), group.negate(e2.getC1())))&& - orProof.getG2Tag().equals(general.getH())&& - orProof.getH2Tag().equals(group.add(e2New.getC2(), group.negate(e2.getC2()))) && + g1Tag.equals(g)&& + h1Tag.equals(group.add(convert2ECPoint(e2New.getC1()) + , group.negate(convert2ECPoint(e2.getC1()))))&& + g2Tag.equals(h)&& + h2Tag.equals(group.add(convert2ECPoint(e2New.getC2()) + , group.negate(convert2ECPoint(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.orderUpperBound()) - .equals(general.hash(forRandomOracle).mod(group.orderUpperBound()).mod(group.orderUpperBound()))&& + .equals(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.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())))); + group.multiply(g1, z).equals(group.add(u, group.multiply(h1,c1))) && + group.multiply(g2, z).equals(group.add(v, group.multiply(h2,c1))) && + group.multiply(g1Tag, zTag).equals(group.add(uTag, group.multiply(h1Tag,c2))) && + group.multiply(g2Tag, zTag).equals(group.add(vTag, group.multiply(h2Tag,c2))); } } diff --git a/mixer/src/main/java/verifier/VerifyTable.java b/mixer/src/main/java/verifier/VerifyTable.java new file mode 100644 index 0000000..a0075c0 --- /dev/null +++ b/mixer/src/main/java/verifier/VerifyTable.java @@ -0,0 +1,83 @@ +package verifier; + +import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import qilin.util.Pair; + +import java.util.Arrays; + +/** + * Created by Tzlil on 12/30/2015. + */ +public final class VerifyTable { + + public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier,int n,Pair mixerOutput) throws InvalidProtocolBufferException { + int index1,index2,layer; + + //assert n = 2^k + if ( (n &(n-1)) != 0) + throw new IllegalArgumentException("n"); + + int layers = 2*(int)(Math.log(n) / Math.log(2)) - 1; + //initialize locationChecksum table + // use for check BeneshNet validity + boolean[][] locationChecksum = new boolean[layers][n]; + for (boolean[] locationChecksumLayer: locationChecksum) { + Arrays.fill(locationChecksumLayer,false); + } + + Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.a; + Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.b; + + 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[layer][index1], + rerandomizableEncryptedMessages[layer][index2], + rerandomizableEncryptedMessages[layer + 1][index1], + rerandomizableEncryptedMessages[layer + 1][index2], + zkp)) { + + verifier.verify(rerandomizableEncryptedMessages[layer][index1], + rerandomizableEncryptedMessages[layer][index2], + rerandomizableEncryptedMessages[layer + 1][index1], + rerandomizableEncryptedMessages[layer + 1][index2], + zkp); + System.out.print("\n\n\nlayer " + layer + " i , j " + index1 + " , " + index2 + "\n\n\n"); + 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/test/java/mixer/MixingText.java b/mixer/src/test/java/mixer/MixingText.java new file mode 100644 index 0000000..5081850 --- /dev/null +++ b/mixer/src/test/java/mixer/MixingText.java @@ -0,0 +1,113 @@ +package mixer; + +/** + * Created by Tzlil on 12/30/2015. + */ +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.GlobalCryptoSetup; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.jce.spec.ECPublicKeySpec; +import org.bouncycastle.math.ec.ECPoint; +import org.junit.Test; +import prover.Prover; +import qilin.primitives.RandomOracle; +import qilin.primitives.concrete.DigestOracle; +import qilin.primitives.concrete.ECElGamal; +import qilin.primitives.concrete.ECGroup; +import qilin.primitives.generic.ElGamal; +import qilin.util.Pair; +import verifier.Verifier; +import verifier.VerifyTable; + +import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.List; +import java.util.Random; + +public class MixingText { + + ECElGamalEncryption encryptor; + ECGroup group; + Random random ; + private BigInteger sk; + private ECElGamal.SK key; + private ConcreteCrypto.ElGamalPublicKey serializedPk; + + public final static String ENCRYPTION_KEY_ALGORITHM = "ECDH"; + /** + * Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption} + * @param pk + * @return + */ + public static ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK pk) { + ECPoint pkPoint = pk.getPK(); + ECParameterSpec params = group.getCurveParams(); + + ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params); + + try { + KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM, + GlobalCryptoSetup.getBouncyCastleProvider()); + PublicKey javaPk = fact.generatePublic(pubKeySpec); + ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder() + .setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build(); + + return serializedPk; + } catch (Exception e) { + throw new RuntimeException("Error converting public key!", e); + } + } + + @Test + public void mixingTest() throws InvalidProtocolBufferException, InvalidKeySpecException { + // initialization + random = new Random(); + group = new ECGroup("secp256k1"); + sk = ECElGamal.generateSecretKey(group, random); + key = new ECElGamal.SK(group, sk); + serializedPk = serializePk(group, key); + encryptor = new ECElGamalEncryption(); + encryptor.init(serializedPk); + + + Random randomMixer = new Random(); + Random randomProver = new Random(); + RandomOracle randomOracle = new DigestOracle(); + + Mix2ZeroKnowledgeVerifier verifier = new Verifier(encryptor,randomOracle); + Mix2ZeroKnowledgeProver prover = new Prover(randomProver,encryptor,randomOracle,verifier); + meerkat.crypto.mixnet.Mixer mixer = new Mixer(randomMixer,prover,encryptor); + ECGroup group = encryptor.getGroup(); + + + // generate n + int logN = 7; // + random.nextInt(8) + int layers = 2*logN - 1; + int n = 1 << logN; + + // generate MixerInput + List mixerInput = new ArrayList(); + Message message; + for (int i = 0; i < n ; i++){ + message = Mixing.Plaintext.newBuilder() + .setData(ByteString.copyFrom(group.encode(group.sample(random)))) + .build(); + mixerInput.add(encryptor.encrypt(message, encryptor.generateRandomness(random))); + } + + Pair mixerOutput = mixer.mix(mixerInput); + +// assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); + } +}