diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3555c28..1ca625d 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,4 +1,4 @@ -#Tue Dec 01 01:04:39 IST 2015 +#Fri Dec 11 12:12:40 IST 2015 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index 8e56e2e..882d882 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -8,34 +8,27 @@ import 'meerkat/crypto.proto'; message ZeroKnowledgeProof { message OrProof { - message GroupMember { - bytes data = 1; - } - message BigIntegerMsg { - bytes data = 1; - } - //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; + bytes g1 = 1; + bytes h1 = 2; + bytes g2 = 3; + bytes h2 = 4; + bytes g1Tag = 5; + bytes h1Tag = 6; + bytes g2Tag = 7; + bytes h2Tag = 8; //calc: u, v, uTag, vTag; - GroupMember u = 9; - GroupMember v = 10; - GroupMember uTag = 11; - GroupMember vTag = 12; + bytes u = 9; + bytes v = 10; + bytes uTag = 11; + bytes vTag = 12; //generated: c1,c2,z,zTag - BigIntegerMsg c1 = 13; - BigIntegerMsg c2 = 14; - BigIntegerMsg z = 15; - BigIntegerMsg zTag = 16; + bytes c1 = 13; + bytes c2 = 14; + bytes z = 15; + bytes zTag = 16; } OrProof first = 1; OrProof second = 2; diff --git a/mixer/src/main/java/necessary/General.java b/mixer/src/main/java/necessary/General.java new file mode 100644 index 0000000..b6a3707 --- /dev/null +++ b/mixer/src/main/java/necessary/General.java @@ -0,0 +1,41 @@ +package necessary; + +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.Crypto; + +import com.google.protobuf.ByteString; + +public interface General { + + /* + given RerandomizableEncryptedMessage returns an equivalent ElGamalCiphertext + */ + ConcreteCrypto.ElGamalCiphertext calcRerandomizable2ElGamal(Crypto.RerandomizableEncryptedMessage enc); + + + /* + modulo operation over ByteString + */ + ByteString mod(ByteString dividend, ByteString divisor); + + /* + addition operation over ByteString + */ + ByteString add(ByteString a, ByteString b); + + /* + subtraction operation over ByteString + */ + ByteString sub(ByteString Subtraction, ByteString subtrahend); + + + /* + multiplication operation over ByteString + */ + ByteString mul(ByteString a, ByteString b); + + /* + hash operation over ByteString + */ + ByteString hash(ByteString... arr); +} diff --git a/mixer/src/main/java/necessary/Group.java b/mixer/src/main/java/necessary/Group.java new file mode 100644 index 0000000..544b1d7 --- /dev/null +++ b/mixer/src/main/java/necessary/Group.java @@ -0,0 +1,14 @@ +package necessary; + + +import com.google.protobuf.ByteString; + +public interface Group { + + ByteString getG(); + ByteString getH(); + ByteString div(ByteString dividend, ByteString divisor); + ByteString mul(ByteString a, ByteString b); + ByteString pow(ByteString bas, ByteString exp); + ByteString groupSize(); +} diff --git a/mixer/src/main/java/prover/Prover.java b/mixer/src/main/java/prover/Prover.java new file mode 100644 index 0000000..8d0f3c6 --- /dev/null +++ b/mixer/src/main/java/prover/Prover.java @@ -0,0 +1,147 @@ +package prover; + +import com.google.protobuf.ByteString; +import meerkat.crypto.Encryption; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import necessary.General; +import necessary.Group; + +import java.util.Random; + +public class Prover implements Mix2ZeroKnowledgeProver { + + Group group; + General general; + Random rand; + Encryption encryptor; + + public Prover(Group group,Random rand,Encryption encryptor,General general) { + this.group = group; + this.rand = rand; + this.encryptor = encryptor; + this.general = general; + } + + public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, + Crypto.RerandomizableEncryptedMessage in2, + Crypto.RerandomizableEncryptedMessage out1, + Crypto.RerandomizableEncryptedMessage out2, + boolean switched, + Crypto.EncryptionRandomness r1, + Crypto.EncryptionRandomness r2) { + + Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; + if (!switched) + { + 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); + } + 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); + } + return Mixing.ZeroKnowledgeProof.newBuilder() + .setFirst(first) + .setSecond(second) + .setThird(third) + .setFourth(fourth) + .build(); + } + + private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1, + Crypto.RerandomizableEncryptedMessage e2, + 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); + + + return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag); + } + + private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalCiphertext e1, + ElGamalCiphertext e2, + ElGamalCiphertext e1New, + ElGamalCiphertext e2New, + Crypto.EncryptionRandomness x, + boolean flag) { + ByteString g1 = group.getG(); + ByteString h1 = group.div(e1New.getC1(),e1.getC1()); + ByteString g2 = group.getH(); + ByteString h2 = group.div(e1New.getC2(),e1.getC2()); + + ByteString g1Tag = group.getG(); + ByteString h1Tag = group.div(e2New.getC1(),e2.getC1()); + ByteString g2Tag = group.getH(); + ByteString h2Tag = group.div(e2New.getC2(),e2.getC2()); + + ByteString r = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize()); + ByteString u,v,uTag,vTag,c1,c2,z,zTag; + if (flag) + { + c2 = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize()); + zTag = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize()); + //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)); + //step 2 + // c1 = (hash(input + step1) + group size - c2)% group size + c1 = general.mod(general.add(general.hash(g1, h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag, u, v, uTag, vTag), general.sub(group.groupSize(), c2)),group.groupSize()); + //step 3 + //z = (r + c1 * x) % group size; + z = general.mod(general.add(r,general.mul(c1,x.getData())),group.groupSize()); + } + else + { + c1 = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize()); + z = general.mod(encryptor.generateRandomness(rand).getData(),group.groupSize()); + //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)); + //step 2 + // c1 = (hash(input + step1) + group size - c1)% group size + c2 = general.mod(general.add(general.hash(g1, h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag, u, v, uTag, vTag), general.sub(group.groupSize(), c1)),group.groupSize()); + //step 3 + //zTag = (r + c2 * x) % group size; + zTag = general.mod(general.add(r,general.mul(c2,x.getData())),group.groupSize()); + } + 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) + .setC1(c1) + .setC2(c2) + .setZ(z) + .setZTag(zTag) + .build(); + } + + +} + diff --git a/mixer/src/main/java/verifier/Verifier.java b/mixer/src/main/java/verifier/Verifier.java new file mode 100644 index 0000000..b7894df --- /dev/null +++ b/mixer/src/main/java/verifier/Verifier.java @@ -0,0 +1,80 @@ +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; + + +public class Verifier implements Mix2ZeroKnowledgeVerifier { + + /** + * Return true iff the proof is valid. + * @param in1 + * @param in2 + * @param out1 + * @param out2 + * @return + */ + + Group group; + General general; + + public Verifier(Group group,General general) { + this.group = group; + this.general = general; + } + + public boolean verify(Crypto.RerandomizableEncryptedMessage in1, + Crypto.RerandomizableEncryptedMessage in2, + Crypto.RerandomizableEncryptedMessage out1, + Crypto.RerandomizableEncryptedMessage out2, + Mixing.ZeroKnowledgeProof proof) + { + + ElGamalCiphertext e1ElGamal = general.calcRerandomizable2ElGamal(in1); + ElGamalCiphertext e2ElGamal = general.calcRerandomizable2ElGamal(in2); + 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()) && + verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,proof.getFourth()); + } + + public boolean verifyElGamaOrProof(ElGamalCiphertext e1, + ElGamalCiphertext e2, + ElGamalCiphertext e1New, + ElGamalCiphertext e2New, + Mixing.ZeroKnowledgeProof.OrProof orProof) + { + + return //input + orProof.getG1().equals(group.getG())&& + orProof.getH1().equals(group.div(e1New.getC1(), e1.getC1()))&& + orProof.getG2().equals(group.getH())&& + orProof.getH2().equals(group.div(e1New.getC2(), e1.getC2()))&& + // input' + orProof.getG1Tag().equals(group.getG())&& + orProof.getH1Tag().equals(group.div(e2New.getC1(), e2.getC1()))&& + orProof.getG2Tag().equals(group.getH())&& + orProof.getH2Tag().equals(group.div(e2New.getC2(), e2.getC2())) && + // hash + // assert (c1 + c2 ) % group size == hash (imput + step1) % group size + general.mod((general.add(orProof.getC1(),orProof.getC2())),group.groupSize()) + .equals(general.mod(general.hash(orProof.getG1(), orProof.getH1(), orProof.getG2(), orProof.getH2(), + orProof.getG1Tag(), orProof.getH1Tag(), orProof.getG2Tag(), orProof.getH2Tag(), + orProof.getV(),orProof.getU(),orProof.getVTag(),orProof.getUTag()) , group.groupSize()))&& + // proof + // g1 ^ z == u * ( h1 ^ c1 ) && g2 ^ z == v * ( h2 ^ c1 ) && the same for tag case + group.pow(orProof.getG1(), orProof.getZ()).equals(group.mul(orProof.getU(), group.pow(orProof.getH1(),orProof.getC1()))) && + group.pow(orProof.getG2(), orProof.getZ()).equals(group.mul(orProof.getV(), group.pow(orProof.getH2(),orProof.getC1()))) && + group.pow(orProof.getG1Tag(), orProof.getZTag()).equals(group.mul(orProof.getUTag(), group.pow(orProof.getH1Tag(),orProof.getC2()))) && + group.pow(orProof.getG2Tag(), orProof.getZTag()).equals(group.mul(orProof.getVTag(), group.pow(orProof.getH2Tag(),orProof.getC2()))); + + } +}