From 1baa567d8e79f9a289ff23953518e9450616d90d Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Tue, 1 Nov 2016 18:03:53 +0200 Subject: [PATCH 01/25] Starting to review and refactor mixer --- .../java/meerkat/mixer/main/BatchHandler.java | 2 +- .../ECElGamalMixProof.java} | 176 +++++++++--------- .../mixer/{prover => proofs}/Prover.java | 78 ++++---- .../mixer/{verifier => proofs}/Verifier.java | 42 ++--- .../{verifier => proofs}/VerifyTable.java | 2 +- .../ZeroKnowledgeOrProofParser.java | 2 +- .../java/meerkat/mixer/CreateTestVector.java | 6 +- .../test/java/meerkat/mixer/MixingTest.java | 6 +- .../meerkat/mixer/ZeroKnowledgeProofTest.java | 4 +- .../java/profiling/ZeroKnowledgeProof.java | 2 +- 10 files changed, 158 insertions(+), 162 deletions(-) rename mixer/src/main/java/meerkat/mixer/{prover/ElGamalProofOrganizer.java => proofs/ECElGamalMixProof.java} (60%) rename mixer/src/main/java/meerkat/mixer/{prover => proofs}/Prover.java (79%) rename mixer/src/main/java/meerkat/mixer/{verifier => proofs}/Verifier.java (67%) rename mixer/src/main/java/meerkat/mixer/{verifier => proofs}/VerifyTable.java (99%) rename mixer/src/main/java/meerkat/mixer/{verifier => proofs}/ZeroKnowledgeOrProofParser.java (99%) diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java index 8356475..28892fa 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java @@ -5,7 +5,7 @@ import meerkat.crypto.mixnet.MixerOutput; import meerkat.protobuf.Crypto; import meerkat.mixer.necessary.AsyncBulletinBoardClient; import meerkat.mixer.necessary.CompleteBatch; -import meerkat.mixer.verifier.VerifyTable; +import meerkat.mixer.proofs.VerifyTable; import java.util.Arrays; import java.util.List; diff --git a/mixer/src/main/java/meerkat/mixer/prover/ElGamalProofOrganizer.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java similarity index 60% rename from mixer/src/main/java/meerkat/mixer/prover/ElGamalProofOrganizer.java rename to mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java index 153dc12..bb41856 100644 --- a/mixer/src/main/java/meerkat/mixer/prover/ElGamalProofOrganizer.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java @@ -1,4 +1,4 @@ -package meerkat.mixer.prover; +package meerkat.mixer.proofs; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -11,9 +11,9 @@ import org.factcenter.qilin.primitives.concrete.ECGroup; /** * use for organize the input for each ZKP * - * both meerkat.mixer.prover and meerkat.mixer.verifier implantation are using it + * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it */ -public class ElGamalProofOrganizer { +public class ECElGamalMixProof { private final ECGroup group; private final ECPoint g; @@ -26,7 +26,7 @@ public class ElGamalProofOrganizer { * @param g - generator of group * @param h - h = g ^ SecretKey */ - public ElGamalProofOrganizer(ECGroup group, ECPoint g, ECPoint h){ + public ECElGamalMixProof(ECGroup group, ECPoint g, ECPoint h){ this.group = group; this.g = g; this.h = h; @@ -34,20 +34,16 @@ public class ElGamalProofOrganizer { this.hEncoded = group.encode(h); } - public enum OrProofOrder { - first, second, third, fourth - } - public enum TrueCouple { left, right, unknown } /** - * can be used by meerkat.mixer.prover only + * can be used by meerkat.mixer.proofs only * * call to the meerkat.mixer.main overload with flag = true */ - protected ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 + protected Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) throws InvalidProtocolBufferException { @@ -60,7 +56,7 @@ public class ElGamalProofOrganizer { * * call to the meerkat.mixer.main overload with flag = false */ - public ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 + public Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException { // flag = false; @@ -71,14 +67,14 @@ public class ElGamalProofOrganizer { * inner method * convert each encrypted message to ElGamalCiphertext * - * @param flag - true if called by meerkat.mixer.prover ( r1,r2,switched are known) + * @param flag - true if called by meerkat.mixer.proofs ( r1,r2,switched are known) * @return ElGamalProofInput * @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't * ElGamalCiphertext */ - private ElGamalProofInput createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 + private Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched,boolean flag) + , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean flag) throws InvalidProtocolBufferException { //convert RerandomizableEncryptedMessage to ElGamalCiphertext @@ -88,47 +84,70 @@ public class ElGamalProofOrganizer { ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); if(flag) { - return new ElGamalProofInput(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched); + return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched); }else { - return new ElGamalProofInput(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); + return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); } } /** - * can be construct by instance of organizer only by calling createProofInput method (all constructors are private) + * Statement to be proved. The statement consists of the four substatements that are ORs of the DLOG equality. * - * in construction it use for preparing the input for prove, while avoiding double converting or calculations + * This can be constructed only by calling createProofInput method on an instance of ECElGamalMixProof (all constructors are private) + * + * in construction it is used for preparing the input for proving, while avoiding double converting or calculations * * use as a container for 4 OrProofInput. */ - public class ElGamalProofInput { + public class Statement { + private final OrStatement first; + private final OrStatement second; + private final OrStatement third; + private final OrStatement fourth; - private final OrProofInput first; - private final OrProofInput second; - private final OrProofInput third; - private final OrProofInput fourth; - private ECPoint convert2ECPoint(ByteString bs){ + public OrStatement getFirst() { + return first; + } + + public OrStatement getSecond() { + return second; + } + + public OrStatement getThird() { + return third; + } + + public OrStatement getFourth() { + return fourth; + } + + /** + * Decode from the serialized representation to an {@link ECPoint} object. + * @param bs + * @return + */ + private ECPoint decodeECPoint(ByteString bs){ return group.decode(bs.toByteArray()); } /** - * @param flag - true if called by meerkat.mixer.prover ( r1,r2,switched are known) + * @param proving - true if called by meerkat.mixer.proofs ( r1,r2,switched are known) */ - private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 + private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched,boolean flag){ + , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean proving){ - ECPoint e1c1 = convert2ECPoint(e1.getC1()); - ECPoint e1c2 = convert2ECPoint(e1.getC2()); - ECPoint e2c1 = convert2ECPoint(e2.getC1()); - ECPoint e2c2 = convert2ECPoint(e2.getC2()); - ECPoint e1Nc1 = convert2ECPoint(e1New.getC1()); - ECPoint e1Nc2 = convert2ECPoint(e1New.getC2()); - ECPoint e2Nc1 = convert2ECPoint(e2New.getC1()); - ECPoint e2Nc2 = convert2ECPoint(e2New.getC2()); + ECPoint e1c1 = decodeECPoint(e1.getC1()); + ECPoint e1c2 = decodeECPoint(e1.getC2()); + ECPoint e2c1 = decodeECPoint(e2.getC1()); + ECPoint e2c2 = decodeECPoint(e2.getC2()); + ECPoint e1Nc1 = decodeECPoint(e1New.getC1()); + ECPoint e1Nc2 = decodeECPoint(e1New.getC2()); + ECPoint e2Nc1 = decodeECPoint(e2New.getC1()); + ECPoint e2Nc2 = decodeECPoint(e2New.getC2()); ECPoint c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1)); ECPoint c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1)); @@ -141,14 +160,12 @@ public class ElGamalProofOrganizer { ECPoint c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2)); - if(!flag){ - - this.first = new OrProofInput(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2); - this.second = new OrProofInput(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1); - this.third = new OrProofInput(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2); - this.fourth = new OrProofInput(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2); - - }else { + if(!proving) { + this.first = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2); + this.second = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1); + this.third = new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2); + this.fourth = new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2); + } else { byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1); byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1); @@ -161,29 +178,29 @@ public class ElGamalProofOrganizer { if (!switched) { - this.first = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 + this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded , r1, TrueCouple.left); - this.second = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 + this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded , r1, TrueCouple.left); - this.third = new OrProofInput(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 + this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded , r2, TrueCouple.right); - this.fourth = new OrProofInput(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 + this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded , r2, TrueCouple.right); } else { - this.first = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 + this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded , r2, TrueCouple.right); - this.second = new OrProofInput(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 + this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded , r1, TrueCouple.right); - this.third = new OrProofInput(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 + this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded , r2, TrueCouple.left); - this.fourth = new OrProofInput(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 + this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded , r1, TrueCouple.left); } @@ -192,57 +209,38 @@ public class ElGamalProofOrganizer { /** - * used by the meerkat.mixer.prover - * call to the meerkat.mixer.main constructor with flag = true + * used by the meerkat.mixer.proofs + * call to the meerkat.mixer.main constructor with proving = true */ - private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 + private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched){ - //flag = true; + //proving = true; this(e1,e2,e1New,e2New,r1,r2,switched,true); } /** - * used by meerkat.mixer.prover - * call to the meerkat.mixer.main constructor with flag = true + * used by meerkat.mixer.proofs + * call to the meerkat.mixer.main constructor with proving = false */ - private ElGamalProofInput(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 + private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ - //flag = false; + //proving = false; this(e1,e2,e1New,e2New,null,null,false,false); } - - /** - * getter for all 4 OrProofInputs - * - * @param orProofOrder - * @return the required OrProof - */ - public OrProofInput getOrProofInput(OrProofOrder orProofOrder) { - switch (orProofOrder) { - - case first: - return this.first; - case second: - return this.second; - case third: - return this.third; - case fourth: - return this.fourth; - } - return null; - } } /** - * can't be constructed (all constructors are private) + * The statement of a single disjunction to be proved: + * Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2) * - * 4 instances will be constructed for each new ElGamalProofInput + * The statement can't be constructed externally (all constructors are private) + * + * 4 instances will be constructed for each new {@link ECElGamalMixProof.Statement} * - * container for all meerkat.mixer.necessary inputs for single OrProof */ - public class OrProofInput{ + public class OrStatement { public final ECPoint g1; public final ECPoint h1; public final ECPoint g2; @@ -252,7 +250,7 @@ public class ElGamalProofOrganizer { public final ECPoint g2Tag; public final ECPoint h2Tag; - // can be access by meerkat.mixer.prover only + // can be access by meerkat.mixer.proofs only protected final byte[] g1Encoded; protected final byte[] h1Encoded; protected final byte[] g2Encoded; @@ -265,10 +263,10 @@ public class ElGamalProofOrganizer { protected final TrueCouple flag; /** - * used by meerkat.mixer.prover only + * used by meerkat.mixer.proofs only */ - private OrProofInput(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag - ,byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded + private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag + , byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded , Crypto.EncryptionRandomness x, TrueCouple flag) { this.g1 = g; this.h1 = h1; @@ -296,7 +294,7 @@ public class ElGamalProofOrganizer { /** * used by meerkat.mixer.verifier */ - private OrProofInput(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) { + private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) { this(h1,h2,h1Tag,h2Tag,null,null,null,null,null,TrueCouple.unknown); } } diff --git a/mixer/src/main/java/meerkat/mixer/prover/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java similarity index 79% rename from mixer/src/main/java/meerkat/mixer/prover/Prover.java rename to mixer/src/main/java/meerkat/mixer/proofs/Prover.java index d540974..5465c9c 100644 --- a/mixer/src/main/java/meerkat/mixer/prover/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -1,4 +1,4 @@ -package meerkat.mixer.prover; +package meerkat.mixer.proofs; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; @@ -26,7 +26,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { private final ECElGamalEncryption encryptor; private final ECPoint g,h; private final BigInteger groupOrderUpperBound; - private final ElGamalProofOrganizer organizer; + private final ECElGamalMixProof organizer; /** * @param rand @@ -41,7 +41,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.group = this.encryptor.getGroup(); this.g = group.getGenerator(); this.h = this.encryptor.getElGamalPK().getPK(); - this.organizer = new ElGamalProofOrganizer(group,g,h); + this.organizer = new ECElGamalMixProof(group,g,h); this.groupOrderUpperBound = group.orderUpperBound(); } @@ -68,12 +68,12 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; - ElGamalProofOrganizer.ElGamalProofInput input = organizer.createProofInput(in1,in2,out1,out2,r1,r2,sw); + ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2,r1,r2,sw); - first = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.first)); - second = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.second)); - third = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.third)); - fourth = createOrProofElGamal(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.fourth)); + first = createOrProofElGamal(statement.getFirst()); + second = createOrProofElGamal(statement.getSecond()); + third = createOrProofElGamal(statement.getThird()); + fourth = createOrProofElGamal(statement.getFourth()); Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() .setI(i) @@ -94,7 +94,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { /** * Fiat–Shamir heuristic - * @param input - protobuf contains all parameters from the first step of the current prove + * @param input - protobuf contains all parameters from the first step of the current proof * @param randomOracle * @return randomOracle.hash(input) */ @@ -105,21 +105,21 @@ public class Prover implements Mix2ZeroKnowledgeProver { /** - * @param orProofInput + * @param orStatement * @return ZKP OrProof: there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2) - * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.prover + * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs */ - private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ElGamalProofOrganizer.OrProofInput orProofInput) { + private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixProof.OrStatement orStatement) { - ECPoint g1 = orProofInput.g1; - ECPoint h1 = orProofInput.h1; - ECPoint g2 = orProofInput.g2; - ECPoint h2 = orProofInput.h2; + ECPoint g1 = orStatement.g1; + ECPoint h1 = orStatement.h1; + ECPoint g2 = orStatement.g2; + ECPoint h2 = orStatement.h2; - ECPoint g1Tag = orProofInput.g1Tag; - ECPoint h1Tag = orProofInput.h1Tag; - ECPoint g2Tag = orProofInput.g2Tag; - ECPoint h2Tag = orProofInput.h2Tag; + ECPoint g1Tag = orStatement.g1Tag; + ECPoint h1Tag = orStatement.h1Tag; + ECPoint g2Tag = orStatement.g2Tag; + ECPoint h2Tag = orStatement.h2Tag; BigInteger r = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); BigInteger c1,c2,z,zTag; @@ -127,7 +127,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle; - switch (orProofInput.flag) { + switch (orStatement.flag) { case left: c2 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); zTag = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); @@ -140,14 +140,14 @@ public class Prover implements Mix2ZeroKnowledgeProver { // c1 = (hash(input + step1) + group size - c2)% group size forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(orProofInput.g1Encoded)) - .setH1(ByteString.copyFrom(orProofInput.h1Encoded)) - .setG2(ByteString.copyFrom(orProofInput.g2Encoded)) - .setH2(ByteString.copyFrom(orProofInput.h2Encoded)) - .setG1Tag(ByteString.copyFrom(orProofInput.g1TagEncoded)) - .setH1Tag(ByteString.copyFrom(orProofInput.h1TagEncoded)) - .setG2Tag(ByteString.copyFrom(orProofInput.g2TagEncoded)) - .setH2Tag(ByteString.copyFrom(orProofInput.h2TagEncoded)) + .setG1(ByteString.copyFrom(orStatement.g1Encoded)) + .setH1(ByteString.copyFrom(orStatement.h1Encoded)) + .setG2(ByteString.copyFrom(orStatement.g2Encoded)) + .setH2(ByteString.copyFrom(orStatement.h2Encoded)) + .setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded)) + .setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded)) + .setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded)) + .setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded)) .setU(ByteString.copyFrom(group.encode(u))) .setV(ByteString.copyFrom(group.encode(v))) .setUTag(ByteString.copyFrom(group.encode(uTag))) @@ -156,7 +156,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { c1 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); //step 3 //z = (r + c1 * x) % group size; - z = r.add(c1.multiply(encryptor.extractRandomness(orProofInput.x))).mod(groupOrderUpperBound); + z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); break; case right: c1 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); @@ -170,14 +170,14 @@ public class Prover implements Mix2ZeroKnowledgeProver { // c1 = (hash(input + step1) + group size - c1)% group size forRandomOracle = Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(orProofInput.g1Encoded)) - .setH1(ByteString.copyFrom(orProofInput.h1Encoded)) - .setG2(ByteString.copyFrom(orProofInput.g2Encoded)) - .setH2(ByteString.copyFrom(orProofInput.h2Encoded)) - .setG1Tag(ByteString.copyFrom(orProofInput.g1TagEncoded)) - .setH1Tag(ByteString.copyFrom(orProofInput.h1TagEncoded)) - .setG2Tag(ByteString.copyFrom(orProofInput.g2TagEncoded)) - .setH2Tag(ByteString.copyFrom(orProofInput.h2TagEncoded)) + .setG1(ByteString.copyFrom(orStatement.g1Encoded)) + .setH1(ByteString.copyFrom(orStatement.h1Encoded)) + .setG2(ByteString.copyFrom(orStatement.g2Encoded)) + .setH2(ByteString.copyFrom(orStatement.h2Encoded)) + .setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded)) + .setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded)) + .setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded)) + .setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded)) .setU(ByteString.copyFrom(group.encode(u))) .setV(ByteString.copyFrom(group.encode(v))) .setUTag(ByteString.copyFrom(group.encode(uTag))) @@ -186,7 +186,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { c2 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); //step 3 //zTag = (r + c2 * x) % group size; - zTag = r.add(c2.multiply(encryptor.extractRandomness(orProofInput.x))).mod(groupOrderUpperBound); + zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); break; default: return null; diff --git a/mixer/src/main/java/meerkat/mixer/verifier/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java similarity index 67% rename from mixer/src/main/java/meerkat/mixer/verifier/Verifier.java rename to mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index ed08512..d1bd4e3 100644 --- a/mixer/src/main/java/meerkat/mixer/verifier/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -1,4 +1,4 @@ -package meerkat.mixer.verifier; +package meerkat.mixer.proofs; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; @@ -6,8 +6,6 @@ import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; -import meerkat.mixer.prover.ElGamalProofOrganizer; -import meerkat.mixer.prover.Prover; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -20,20 +18,20 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { private final ECGroup group; private final RandomOracle randomOracle; private final ECPoint g,h; - private final ElGamalProofOrganizer organizer; + private final ECElGamalMixProof organizer; private final ZeroKnowledgeOrProofParser parser; /** * constructor - * @param encryptor should be as the encryptor used by meerkat.mixer.prover - * @param randomOracle should be as the random oracle used by meerkat.mixer.prover + * @param encryptor should be as the encryptor used by meerkat.mixer.proofs + * @param randomOracle should be as the random oracle used by meerkat.mixer.proofs */ public Verifier(ECElGamalEncryption encryptor, RandomOracle randomOracle) { this.group = encryptor.getGroup(); this.g = group.getGenerator(); this.h = encryptor.getElGamalPK().getPK(); this.randomOracle = randomOracle; - this.organizer = new ElGamalProofOrganizer(group,g,h); + this.organizer = new ECElGamalMixProof(group,g,h); this.parser = new ZeroKnowledgeOrProofParser(group); } @@ -54,32 +52,32 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { - ElGamalProofOrganizer.ElGamalProofInput input = organizer.createProofInput(in1,in2,out1,out2); - return verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.first), proof.getFirst())&& - verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.second), proof.getSecond())&& - verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.third), proof.getThird())&& - verifyElGamaOrProof(input.getOrProofInput(ElGamalProofOrganizer.OrProofOrder.fourth), proof.getFourth()); + ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2); + return verifyElGamaOrProof(statement.getFirst(), proof.getFirst())&& + verifyElGamaOrProof(statement.getSecond(), proof.getSecond())&& + verifyElGamaOrProof(statement.getThird(), proof.getThird())&& + verifyElGamaOrProof(statement.getFourth(), proof.getFourth()); } /** * - * @param orProofInput + * @param orStatement * @param orProof * @return verify single or proof */ - private boolean verifyElGamaOrProof(ElGamalProofOrganizer.OrProofInput orProofInput, + private boolean verifyElGamaOrProof(ECElGamalMixProof.OrStatement orStatement, Mixing.ZeroKnowledgeProof.OrProof orProof) { ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof); - return container.g1.equals(orProofInput.g1) && - container.h1.equals(orProofInput.h1) && - container.g2.equals(orProofInput.g2) && - container.h2.equals(orProofInput.h2) && - container.g1Tag.equals(orProofInput.g1Tag) && - container.h1Tag.equals(orProofInput.h1Tag) && - container.g2Tag.equals(orProofInput.g2Tag) && - container.h2Tag.equals(orProofInput.h2Tag) && + return container.g1.equals(orStatement.g1) && + container.h1.equals(orStatement.h1) && + container.g2.equals(orStatement.g2) && + container.h2.equals(orStatement.h2) && + container.g1Tag.equals(orStatement.g1Tag) && + container.h1Tag.equals(orStatement.h1Tag) && + container.g2Tag.equals(orStatement.g2Tag) && + container.h2Tag.equals(orStatement.h2Tag) && container.c1.add(container.c2).mod(group.orderUpperBound()) .equals(Prover.hash(container.forRandomOracle,randomOracle).mod(group.orderUpperBound())) && group.multiply(container.g1, container.z) diff --git a/mixer/src/main/java/meerkat/mixer/verifier/VerifyTable.java b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java similarity index 99% rename from mixer/src/main/java/meerkat/mixer/verifier/VerifyTable.java rename to mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java index 2bb3781..ac3f6a5 100644 --- a/mixer/src/main/java/meerkat/mixer/verifier/VerifyTable.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java @@ -1,4 +1,4 @@ -package meerkat.mixer.verifier; +package meerkat.mixer.proofs; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; diff --git a/mixer/src/main/java/meerkat/mixer/verifier/ZeroKnowledgeOrProofParser.java b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java similarity index 99% rename from mixer/src/main/java/meerkat/mixer/verifier/ZeroKnowledgeOrProofParser.java rename to mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java index 01ff344..bdd2b4c 100644 --- a/mixer/src/main/java/meerkat/mixer/verifier/ZeroKnowledgeOrProofParser.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java @@ -1,4 +1,4 @@ -package meerkat.mixer.verifier; +package meerkat.mixer.proofs; import com.google.protobuf.ByteString; import meerkat.protobuf.Mixing; diff --git a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java index fe45e1b..af6a865 100644 --- a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java +++ b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java @@ -5,9 +5,9 @@ import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.mixer.mixing.Mixer; import meerkat.mixer.mixing.MixerOutput; -import meerkat.mixer.prover.Prover; -import meerkat.mixer.verifier.Verifier; -import meerkat.mixer.verifier.VerifyTable; +import meerkat.mixer.proofs.Prover; +import meerkat.mixer.proofs.Verifier; +import meerkat.mixer.proofs.VerifyTable; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; import org.factcenter.qilin.primitives.RandomOracle; diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index f9ec6f8..229196c 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -8,9 +8,9 @@ import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.mixer.mixing.Mixer; -import meerkat.mixer.prover.Prover; -import meerkat.mixer.verifier.Verifier; -import meerkat.mixer.verifier.VerifyTable; +import meerkat.mixer.proofs.Prover; +import meerkat.mixer.proofs.Verifier; +import meerkat.mixer.proofs.VerifyTable; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; import org.factcenter.qilin.primitives.RandomOracle; diff --git a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java b/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java index 4f2daca..cb4d86b 100644 --- a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java @@ -5,8 +5,8 @@ import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.mixer.prover.Prover; -import meerkat.mixer.verifier.Verifier; +import meerkat.mixer.proofs.Prover; +import meerkat.mixer.proofs.Verifier; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index 7d38bf1..d676a34 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -4,7 +4,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.mixer.prover.Prover; +import meerkat.mixer.proofs.Prover; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; From 5b268cd7797a3823a282a0b468747aac8d305ba4 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 2 Nov 2016 00:31:49 +0200 Subject: [PATCH 02/25] More refactoring for mixer --- .../mixer/proofs/ECElGamalMixParams.java | 336 ++++++++++++++++++ .../mixer/proofs/ECElGamalMixProof.java | 301 ---------------- .../java/meerkat/mixer/proofs/Prover.java | 16 +- .../java/meerkat/mixer/proofs/Verifier.java | 16 +- 4 files changed, 352 insertions(+), 317 deletions(-) create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java delete mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java new file mode 100644 index 0000000..d601d1a --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java @@ -0,0 +1,336 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.Crypto; +import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.concrete.ECGroup; + +/** + * use for organize the input for each ZKP + * + * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it + */ +public class ECElGamalMixParams { + + private final ECGroup group; + private final ECPoint g; + private final ECPoint h; + private final byte[] gEncoded; + private final byte[] hEncoded; + + + /** + * Decode from the serialized representation to an {@link ECPoint} object. + * @param bs + * @return + */ + private ECPoint decodeECPoint(ByteString bs){ + return group.decode(bs.toByteArray()); + } + + /** + * @param group + * @param g - generator of group + * @param h - h = g ^ SecretKey + */ + public ECElGamalMixParams(ECGroup group, ECPoint g, ECPoint h){ + this.group = group; + this.g = g; + this.h = h; + this.gEncoded = group.encode(g); + this.hEncoded = group.encode(h); + } + + public enum TrueCouple { + left, right, unknown + } + + + /** + * can be used by anyone, e.g meerkat.mixer.verifier + * + * call to the meerkat.mixer.main overload with flag = false + */ + public Statement createStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 + , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException { + + ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); + ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); + ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); + ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); + return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); + } + + /** + + * convert each encrypted message to ElGamalCiphertext + * + * @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't + * ElGamalCiphertext + */ + protected ProverStatement createProverStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 + , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 + , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) + throws InvalidProtocolBufferException { + + //convert RerandomizableEncryptedMessage to ElGamalCiphertext + ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); + ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); + ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); + ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); + + return new ProverStatement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched); + } + + + /** + * Statement to be proved. + * + * The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality. + * + * A Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private) + * + */ + public class Statement { + + /** + * Denote the first ciphertext pair e1=(e1c1,e1c2), e2=(e2c1,e2c2) and the second + * e1N=(e1Nc1, e1Nc2) and e2N=(e2Nc1,e2Nc2). + * Then ci_ejNDivek = ejNci/ekci + */ + ECPoint c1_e1NDive1; + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c1_e2NDive1; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c1_e1NDive2; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c1_e2NDive2; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c2_e1NDive1; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c2_e2NDive1; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c2_e1NDive2; + + /** + * See {@link #c1_e1NDive1} + */ + ECPoint c2_e2NDive2; + + + private final OrStatement orStatements[] = new OrStatement[4]; + + + public OrStatement getOrStatement(int num) { + if (orStatements[0] == null) + generateOrStatements(); + + return orStatements[num]; + } + + public void setOrStatement(int num, OrStatement orStatement) { + orStatements[num] = orStatement; + } + + + + /** + * Generate and set the four substatements. + */ + protected void generateOrStatements() { + setOrStatement(0, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2)); + setOrStatement(1, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1)); + setOrStatement(2, new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2)); + setOrStatement(3, new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2)); + } + + + private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 + , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ + + ECPoint e1c1 = decodeECPoint(e1.getC1()); + ECPoint e1c2 = decodeECPoint(e1.getC2()); + ECPoint e2c1 = decodeECPoint(e2.getC1()); + ECPoint e2c2 = decodeECPoint(e2.getC2()); + ECPoint e1Nc1 = decodeECPoint(e1New.getC1()); + ECPoint e1Nc2 = decodeECPoint(e1New.getC2()); + ECPoint e2Nc1 = decodeECPoint(e2New.getC1()); + ECPoint e2Nc2 = decodeECPoint(e2New.getC2()); + + c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1)); + c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1)); + c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1)); + c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1)); + c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2)); + c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2)); + c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2)); + c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2)); + } + } + + public class ProverStatement extends Statement { + /** + * True iff the ciphertexts were switched (i.e., decrypt(e1N) == decrypt(e2) and decrypt(e2N) == decrypt(e1) + */ + boolean switched; + + /** + * Encryption randomness for e1 rerandomization + */ + Crypto.EncryptionRandomness r1; + + /** + * Encryption randomnesss for e2 rerandomization + */ + Crypto.EncryptionRandomness r2; + + @Override + protected void generateOrStatements() { + byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1); + byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1); + byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2); + byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2); + byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1); + byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1); + byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2); + byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2); + + + if (!switched) { + setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 + , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded + , r1, TrueCouple.left)); + setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 + , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded + , r1, TrueCouple.left)); + setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 + , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded + , r2, TrueCouple.right)); + setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 + , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded + , r2, TrueCouple.right)); + } else { + setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 + , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded + , r2, TrueCouple.right)); + setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 + , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded + , r1, TrueCouple.right)); + setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 + , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded + , r2, TrueCouple.left)); + setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 + , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded + , r1, TrueCouple.left)); + } + } + + + @Override + public OrProverStatement getOrStatement(int num) { + OrStatement orStatement = super.getOrStatement(num); + if (!(orStatement instanceof OrProverStatement)) + throw new RuntimeException("ProverStatement should always have OrProverStatement substatements!!"); + + return (OrProverStatement) orStatement; + } + + private ProverStatement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2, + ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New, + Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) { + super(e1, e2, e1New, e2New); + this.r1 = r1; + this.r2 = r2; + this.switched = switched; + } + + } + + /** + * The statement of a single disjunction to be proved: + * Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2) + * + * The statement can't be constructed externally (all constructors are private) + * + * 4 instances will be constructed for each new {@link ECElGamalMixParams.Statement} + * + */ + public class OrStatement { + public final ECPoint g1; + public final ECPoint h1; + public final ECPoint g2; + public final ECPoint h2; + public final ECPoint g1Tag; + public final ECPoint h1Tag; + public final ECPoint g2Tag; + public final ECPoint h2Tag; + + + /** + * used by meerkat.mixer.proofs only + */ + private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) { + this.g1 = g; + this.h1 = h1; + this.g2 = h; + this.h2 = h2; + this.g1Tag = g; + this.h1Tag = h1Tag; + this.g2Tag = h; + this.h2Tag = h2Tag; + + + + } + } + + public class OrProverStatement extends OrStatement { + protected final byte[] g1Encoded; + protected final byte[] h1Encoded; + protected final byte[] g2Encoded; + protected final byte[] h2Encoded; + protected final byte[] g1TagEncoded; + protected final byte[] h1TagEncoded; + protected final byte[] g2TagEncoded; + protected final byte[] h2TagEncoded; + protected final Crypto.EncryptionRandomness x; + protected final TrueCouple flag; + + private OrProverStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag, + byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded, + Crypto.EncryptionRandomness x, TrueCouple flag) { + super(h1, h2, h1Tag, h2Tag); + this.g1Encoded = gEncoded; + this.h1Encoded = h1Encoded; + this.g2Encoded = hEncoded; + this.h2Encoded = h2Encoded; + this.g1TagEncoded = gEncoded; + this.h1TagEncoded = h1TagEncoded; + this.g2TagEncoded = hEncoded; + this.h2TagEncoded = h2TagEncoded; + + this.x = x; + this.flag = flag; + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java deleted file mode 100644 index bb41856..0000000 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProof.java +++ /dev/null @@ -1,301 +0,0 @@ -package meerkat.mixer.proofs; - -import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.protobuf.ConcreteCrypto; -import meerkat.protobuf.Crypto; -import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.concrete.ECGroup; - -/** - * use for organize the input for each ZKP - * - * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it - */ -public class ECElGamalMixProof { - - private final ECGroup group; - private final ECPoint g; - private final ECPoint h; - private final byte[] gEncoded; - private final byte[] hEncoded; - - /** - * @param group - * @param g - generator of group - * @param h - h = g ^ SecretKey - */ - public ECElGamalMixProof(ECGroup group, ECPoint g, ECPoint h){ - this.group = group; - this.g = g; - this.h = h; - this.gEncoded = group.encode(g); - this.hEncoded = group.encode(h); - } - - public enum TrueCouple { - left, right, unknown - } - - /** - * can be used by meerkat.mixer.proofs only - * - * call to the meerkat.mixer.main overload with flag = true - */ - protected Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 - , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) throws InvalidProtocolBufferException { - - //boolean flag = true; - return createProofInput(in1,in2,out1,out2,r1,r2,switched,true); - } - - /** - * can be used by anyone, e.g meerkat.mixer.verifier - * - * call to the meerkat.mixer.main overload with flag = false - */ - public Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 - , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException { - - // flag = false; - return createProofInput(in1,in2,out1,out2,null,null,false,false); - } - - /** - * inner method - * convert each encrypted message to ElGamalCiphertext - * - * @param flag - true if called by meerkat.mixer.proofs ( r1,r2,switched are known) - * @return ElGamalProofInput - * @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't - * ElGamalCiphertext - */ - private Statement createProofInput(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 - , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean flag) - throws InvalidProtocolBufferException { - - //convert RerandomizableEncryptedMessage to ElGamalCiphertext - ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); - ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); - ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); - ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); - - if(flag) { - return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched); - }else { - return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); - } - } - - - /** - * Statement to be proved. The statement consists of the four substatements that are ORs of the DLOG equality. - * - * This can be constructed only by calling createProofInput method on an instance of ECElGamalMixProof (all constructors are private) - * - * in construction it is used for preparing the input for proving, while avoiding double converting or calculations - * - * use as a container for 4 OrProofInput. - */ - public class Statement { - private final OrStatement first; - private final OrStatement second; - private final OrStatement third; - private final OrStatement fourth; - - - public OrStatement getFirst() { - return first; - } - - public OrStatement getSecond() { - return second; - } - - public OrStatement getThird() { - return third; - } - - public OrStatement getFourth() { - return fourth; - } - - /** - * Decode from the serialized representation to an {@link ECPoint} object. - * @param bs - * @return - */ - private ECPoint decodeECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); - } - - - /** - * @param proving - true if called by meerkat.mixer.proofs ( r1,r2,switched are known) - */ - private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 - , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched, boolean proving){ - - ECPoint e1c1 = decodeECPoint(e1.getC1()); - ECPoint e1c2 = decodeECPoint(e1.getC2()); - ECPoint e2c1 = decodeECPoint(e2.getC1()); - ECPoint e2c2 = decodeECPoint(e2.getC2()); - ECPoint e1Nc1 = decodeECPoint(e1New.getC1()); - ECPoint e1Nc2 = decodeECPoint(e1New.getC2()); - ECPoint e2Nc1 = decodeECPoint(e2New.getC1()); - ECPoint e2Nc2 = decodeECPoint(e2New.getC2()); - - ECPoint c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1)); - ECPoint c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1)); - ECPoint c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1)); - ECPoint c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1)); - - ECPoint c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2)); - ECPoint c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2)); - ECPoint c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2)); - ECPoint c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2)); - - - if(!proving) { - this.first = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2); - this.second = new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1); - this.third = new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2); - this.fourth = new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2); - } else { - - byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1); - byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1); - byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2); - byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2); - byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1); - byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1); - byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2); - byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2); - - - if (!switched) { - this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded - , r1, TrueCouple.left); - this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded - , r1, TrueCouple.left); - this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 - , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.right); - this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 - , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.right); - } else { - this.first = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded - , r2, TrueCouple.right); - this.second = new OrStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded - , r1, TrueCouple.right); - this.third = new OrStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 - , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.left); - this.fourth = new OrStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 - , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r1, TrueCouple.left); - } - } - } - - - /** - * used by the meerkat.mixer.proofs - * call to the meerkat.mixer.main constructor with proving = true - */ - private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 - , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched){ - //proving = true; - this(e1,e2,e1New,e2New,r1,r2,switched,true); - } - - /** - * used by meerkat.mixer.proofs - * call to the meerkat.mixer.main constructor with proving = false - */ - private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 - , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ - //proving = false; - this(e1,e2,e1New,e2New,null,null,false,false); - } - } - - - /** - * The statement of a single disjunction to be proved: - * Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2) - * - * The statement can't be constructed externally (all constructors are private) - * - * 4 instances will be constructed for each new {@link ECElGamalMixProof.Statement} - * - */ - public class OrStatement { - public final ECPoint g1; - public final ECPoint h1; - public final ECPoint g2; - public final ECPoint h2; - public final ECPoint g1Tag; - public final ECPoint h1Tag; - public final ECPoint g2Tag; - public final ECPoint h2Tag; - - // can be access by meerkat.mixer.proofs only - protected final byte[] g1Encoded; - protected final byte[] h1Encoded; - protected final byte[] g2Encoded; - protected final byte[] h2Encoded; - protected final byte[] g1TagEncoded; - protected final byte[] h1TagEncoded; - protected final byte[] g2TagEncoded; - protected final byte[] h2TagEncoded; - protected final Crypto.EncryptionRandomness x; - protected final TrueCouple flag; - - /** - * used by meerkat.mixer.proofs only - */ - private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag - , byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded - , Crypto.EncryptionRandomness x, TrueCouple flag) { - this.g1 = g; - this.h1 = h1; - this.g2 = h; - this.h2 = h2; - this.g1Tag = g; - this.h1Tag = h1Tag; - this.g2Tag = h; - this.h2Tag = h2Tag; - - this.g1Encoded = gEncoded; - this.h1Encoded = h1Encoded; - this.g2Encoded = hEncoded; - this.h2Encoded = h2Encoded; - this.g1TagEncoded = gEncoded; - this.h1TagEncoded = h1TagEncoded; - this.g2TagEncoded = hEncoded; - this.h2TagEncoded = h2TagEncoded; - - this.x = x; - this.flag = flag; - - } - - /** - * used by meerkat.mixer.verifier - */ - private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) { - this(h1,h2,h1Tag,h2Tag,null,null,null,null,null,TrueCouple.unknown); - } - } -} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index 5465c9c..cc8e46b 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -26,7 +26,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { private final ECElGamalEncryption encryptor; private final ECPoint g,h; private final BigInteger groupOrderUpperBound; - private final ECElGamalMixProof organizer; + private final ECElGamalMixParams organizer; /** * @param rand @@ -41,7 +41,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.group = this.encryptor.getGroup(); this.g = group.getGenerator(); this.h = this.encryptor.getElGamalPK().getPK(); - this.organizer = new ECElGamalMixProof(group,g,h); + this.organizer = new ECElGamalMixParams(group,g,h); this.groupOrderUpperBound = group.orderUpperBound(); } @@ -68,12 +68,12 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; - ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2,r1,r2,sw); + ECElGamalMixParams.ProverStatement statement = organizer.createProverStatement(in1,in2,out1,out2,r1,r2,sw); - first = createOrProofElGamal(statement.getFirst()); - second = createOrProofElGamal(statement.getSecond()); - third = createOrProofElGamal(statement.getThird()); - fourth = createOrProofElGamal(statement.getFourth()); + first = createOrProofElGamal(statement.getOrStatement(0)); + second = createOrProofElGamal(statement.getOrStatement(1)); + third = createOrProofElGamal(statement.getOrStatement(2)); + fourth = createOrProofElGamal(statement.getOrStatement(3)); Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() .setI(i) @@ -109,7 +109,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { * @return ZKP OrProof: there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2) * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs */ - private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixProof.OrStatement orStatement) { + private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixParams.OrProverStatement orStatement) { ECPoint g1 = orStatement.g1; ECPoint h1 = orStatement.h1; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index d1bd4e3..2dc9254 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -18,7 +18,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { private final ECGroup group; private final RandomOracle randomOracle; private final ECPoint g,h; - private final ECElGamalMixProof organizer; + private final ECElGamalMixParams organizer; private final ZeroKnowledgeOrProofParser parser; /** @@ -31,7 +31,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { this.g = group.getGenerator(); this.h = encryptor.getElGamalPK().getPK(); this.randomOracle = randomOracle; - this.organizer = new ECElGamalMixProof(group,g,h); + this.organizer = new ECElGamalMixParams(group,g,h); this.parser = new ZeroKnowledgeOrProofParser(group); } @@ -52,11 +52,11 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { - ECElGamalMixProof.Statement statement = organizer.createProofInput(in1,in2,out1,out2); - return verifyElGamaOrProof(statement.getFirst(), proof.getFirst())&& - verifyElGamaOrProof(statement.getSecond(), proof.getSecond())&& - verifyElGamaOrProof(statement.getThird(), proof.getThird())&& - verifyElGamaOrProof(statement.getFourth(), proof.getFourth()); + ECElGamalMixParams.Statement statement = organizer.createStatement(in1,in2,out1,out2); + return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&& + verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&& + verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&& + verifyElGamaOrProof(statement.getOrStatement(3), proof.getFourth()); } @@ -67,7 +67,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { * @param orProof * @return verify single or proof */ - private boolean verifyElGamaOrProof(ECElGamalMixProof.OrStatement orStatement, + private boolean verifyElGamaOrProof(ECElGamalMixParams.OrStatement orStatement, Mixing.ZeroKnowledgeProof.OrProof orProof) { ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof); return container.g1.equals(orStatement.g1) && From aac7a50a94a9ddfa32a0db8d566e075e249e5943 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 2 Nov 2016 11:59:20 +0200 Subject: [PATCH 03/25] Yet more mixer refactoring --- .../crypto/concrete/ECElGamalEncryption.java | 74 +++++++-- .../java/meerkat/crypto/concrete/Util.java | 29 ++++ .../main/proto/meerkat/concrete_crypto.proto | 10 +- .../src/main/proto/meerkat/mixing.proto | 64 ++++---- .../mixer/proofs/ECElGamalMixParams.java | 99 ++++++------ .../java/meerkat/mixer/proofs/Prover.java | 149 ++++++++++-------- .../java/meerkat/mixer/proofs/Verifier.java | 8 +- .../proofs/ZeroKnowledgeOrProofParser.java | 50 +++--- .../java/meerkat/mixer/RerandomizeTest.java | 4 +- mixer/src/test/java/meerkat/mixer/Utils.java | 10 +- .../meerkat/mixer/ZeroKnowledgeProofTest.java | 10 +- .../profiling/Convert/ByteString2ECPoint.java | 4 +- 12 files changed, 307 insertions(+), 204 deletions(-) create mode 100644 meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java 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 31ad4c1..7264cd0 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/ECElGamalEncryption.java @@ -80,6 +80,45 @@ public class ECElGamalEncryption implements Encryption { elGamalPK = new ECElGamal.PK(group, ((ECPublicKeyParameters) keyParam).getQ()); } + /** + * Encode a group element into a protobuf. + * @param p + * @return + */ + public ConcreteCrypto.GroupElement encodeElement(ECPoint p) { + return encodeElement(group, p); + } + + + /** + * Encode a group element into a protobuf. + * + * @param group group to use for encoding + * @param p element to encode. + * @return + */ + public static ConcreteCrypto.GroupElement encodeElement(ECGroup group, ECPoint p) { + return ConcreteCrypto.GroupElement.newBuilder().setData(ByteString.copyFrom(p.getEncoded(true))).build(); + } + + /** + * Decode from the serialized representation to an {@link ECPoint} object. + * @param bs + * @return + */ + public ECPoint decodeElement(ConcreteCrypto.GroupElement bs) { + return decodeElement(group, bs); + } + + /** + * Decode from the serialized representation to an {@link ECPoint} object. + * @param group group to use for decoding. + * @param bs + * @return + */ + public static ECPoint decodeElement(ECGroup group, ConcreteCrypto.GroupElement bs) { + return group.decode(bs.getData().toByteArray()); + } @Override public Crypto.RerandomizableEncryptedMessage encrypt(Message plaintext, Crypto.EncryptionRandomness rnd) { @@ -95,11 +134,11 @@ public class ECElGamalEncryption implements Encryption { byte[] msg = out.toByteArray(); ECPoint encodedMsg = group.injectiveEncode(msg, new PRGRandom(msg)); - BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); + BigInteger rndInt = extractRandomness(rnd); Pair cipherText = elGamalPK.encrypt(encodedMsg, rndInt); ConcreteCrypto.ElGamalCiphertext encodedCipherText = ConcreteCrypto.ElGamalCiphertext.newBuilder() - .setC1(ByteString.copyFrom(cipherText.a.getEncoded(true))) - .setC2(ByteString.copyFrom(cipherText.b.getEncoded(true))) + .setC1(encodeElement(cipherText.a)) + .setC2(encodeElement(cipherText.b)) .build(); return Crypto.RerandomizableEncryptedMessage.newBuilder() @@ -118,34 +157,49 @@ public class ECElGamalEncryption implements Encryption { @Override public Crypto.RerandomizableEncryptedMessage rerandomize(Crypto.RerandomizableEncryptedMessage msg, Crypto.EncryptionRandomness rnd) throws InvalidProtocolBufferException { - BigInteger rndInt = BigIntegers.fromUnsignedByteArray(rnd.getData().toByteArray()); + BigInteger rndInt = extractRandomness(rnd); Pair randomizer = elGamalPK.encrypt(curve.getInfinity(), rndInt); ConcreteCrypto.ElGamalCiphertext originalEncodedCipher= ConcreteCrypto.ElGamalCiphertext.parseFrom(msg.getData()); Pair originalCipher = new Pair( - curve.decodePoint(originalEncodedCipher.getC1().toByteArray()), - curve.decodePoint(originalEncodedCipher.getC2().toByteArray())); + decodeElement(originalEncodedCipher.getC1()), + decodeElement(originalEncodedCipher.getC2())); Pair newCipher = elGamalPK.add(originalCipher, randomizer); return Crypto.RerandomizableEncryptedMessage.newBuilder() .setData( ConcreteCrypto.ElGamalCiphertext.newBuilder() - .setC1(ByteString.copyFrom(newCipher.a.getEncoded(true))) - .setC2(ByteString.copyFrom(newCipher.b.getEncoded(true))) + .setC1(encodeElement(newCipher.a)) + .setC2(encodeElement(newCipher.b)) .build().toByteString() ).build(); } @Override public Crypto.EncryptionRandomness generateRandomness(Random rand) { - BigInteger randomInt = new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand); + BigInteger randomInt = generateRandomExponent(rand); Crypto.EncryptionRandomness retval = Crypto.EncryptionRandomness.newBuilder() .setData(ByteString.copyFrom(BigIntegers.asUnsignedByteArray(randomInt))).build(); return retval; } + /** + * Return the discrete log of a random element in the group (i.e., a random value in Z_{groupOrder}) + * @param rand + * @return + */ + public BigInteger generateRandomExponent(Random rand) { + return new BigInteger(group.getCurveParams().getN().bitLength() - 1, rand); + } + + /** + * Extract (deserialize) the random exponent from a {@link Crypto.EncryptionRandomness} protobuf. + * + * @param encryptionRandomness + * @return + */ public BigInteger extractRandomness(Crypto.EncryptionRandomness encryptionRandomness){ - return new BigInteger(1,encryptionRandomness.getData().toByteArray()); + return BigIntegers.fromUnsignedByteArray(encryptionRandomness.getData().toByteArray()); } } diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java new file mode 100644 index 0000000..4508d0c --- /dev/null +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java @@ -0,0 +1,29 @@ +package meerkat.crypto.concrete; + +import com.google.protobuf.ByteString; +import meerkat.protobuf.Crypto; + +import java.math.BigInteger; + +/** + * Created by talm on 02/11/16. + */ +public class Util { + /** + * Decode a BigInteger from a protobuf + * @param i + * @return + */ + public static BigInteger decodeBigInteger(Crypto.BigInteger i) { + return new BigInteger(i.getData().toByteArray()); + } + + /** + * Encode a BigInteger in a protobuf. + * @param i + * @return + */ + public static Crypto.BigInteger encodeBigInteger(BigInteger i) { + return Crypto.BigInteger.newBuilder().setData(ByteString.copyFrom(i.toByteArray())).build(); + } +} diff --git a/meerkat-common/src/main/proto/meerkat/concrete_crypto.proto b/meerkat-common/src/main/proto/meerkat/concrete_crypto.proto index d8c40d3..4fa6857 100644 --- a/meerkat-common/src/main/proto/meerkat/concrete_crypto.proto +++ b/meerkat-common/src/main/proto/meerkat/concrete_crypto.proto @@ -14,9 +14,13 @@ message ElGamalPublicKey { bytes subject_public_key_info = 1; } -// An El-Gamal ciphertext // Each group element should be an ASN.1 encoded curve point with compression. +message GroupElement { + bytes data = 1; +} + +// An El-Gamal ciphertext message ElGamalCiphertext { - bytes c1 = 1; // First group element - bytes c2 = 2; // Second group element + GroupElement c1 = 1; // First group element + GroupElement c2 = 2; // Second group element } \ No newline at end of file diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index 83c87d6..abbd0a1 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -5,49 +5,51 @@ package meerkat; option java_package = "meerkat.protobuf"; import 'meerkat/crypto.proto'; +import 'meerkat/concrete_crypto.proto'; -message Plaintext{ +message Plaintext { bytes data = 1; } message ZeroKnowledgeProof { message OrProof { - message ForRandomOracle{ - bytes g1 = 1; - bytes h1 = 2; - bytes g2 = 3; - bytes h2 = 4; - bytes g1Tag = 5; - bytes h1Tag = 6; - bytes g2Tag = 7; - bytes h2Tag = 8; - bytes u = 9; - bytes v = 10; - bytes uTag = 11; - bytes vTag = 12; + message FirstMessage { + GroupElement g1 = 1; + GroupElement h1 = 2; + GroupElement g2 = 3; + GroupElement h2 = 4; + GroupElement g1Tag = 5; + GroupElement h1Tag = 6; + GroupElement g2Tag = 7; + GroupElement h2Tag = 8; + GroupElement u = 9; + GroupElement v = 10; + GroupElement uTag = 11; + GroupElement vTag = 12; } - //input : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag; - bytes g1 = 1; - bytes h1 = 2; - bytes g2 = 3; - bytes h2 = 4; - bytes g1Tag = 5; - bytes h1Tag = 6; - bytes g2Tag = 7; - bytes h2Tag = 8; + //statement parameters : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag; + GroupElement g1 = 1; + GroupElement h1 = 2; + GroupElement g2 = 3; + GroupElement h2 = 4; + GroupElement g1Tag = 5; + GroupElement h1Tag = 6; + GroupElement g2Tag = 7; + GroupElement h2Tag = 8; //calc: u, v, uTag, vTag; - bytes u = 9; - bytes v = 10; - bytes uTag = 11; - bytes vTag = 12; + GroupElement u = 9; + GroupElement v = 10; + GroupElement uTag = 11; + GroupElement vTag = 12; //generated: c1,c2,z,zTag - bytes c1 = 13; - bytes c2 = 14; - bytes z = 15; - bytes zTag = 16; + BigInteger c1 = 13; + BigInteger c2 = 14; + BigInteger z = 15; + BigInteger zTag = 16; } + message Location{ int32 i = 1; int32 j = 2; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java index d601d1a..895253c 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java @@ -15,33 +15,26 @@ import org.factcenter.qilin.primitives.concrete.ECGroup; */ public class ECElGamalMixParams { + private final ECElGamalEncryption encryptor; private final ECGroup group; private final ECPoint g; private final ECPoint h; - private final byte[] gEncoded; - private final byte[] hEncoded; + // Cache encoded formats to save multiple re-encodings + private final ConcreteCrypto.GroupElement gEncoded; + private final ConcreteCrypto.GroupElement hEncoded; /** - * Decode from the serialized representation to an {@link ECPoint} object. - * @param bs - * @return + * @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and + * second base (h) are taken from the encryptor (second base is the public key) */ - private ECPoint decodeECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); - } - - /** - * @param group - * @param g - generator of group - * @param h - h = g ^ SecretKey - */ - public ECElGamalMixParams(ECGroup group, ECPoint g, ECPoint h){ - this.group = group; - this.g = g; - this.h = h; - this.gEncoded = group.encode(g); - this.hEncoded = group.encode(h); + public ECElGamalMixParams(ECElGamalEncryption encryptor){ + this.encryptor = encryptor; + this.group = encryptor.getGroup(); + this.g = group.getGenerator(); + this.h = encryptor.getElGamalPK().getPK(); + this.gEncoded = encryptor.encodeElement(g); + this.hEncoded = encryptor.encodeElement(h); } public enum TrueCouple { @@ -165,17 +158,17 @@ public class ECElGamalMixParams { } - private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2 - , ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ + private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2, + ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ - ECPoint e1c1 = decodeECPoint(e1.getC1()); - ECPoint e1c2 = decodeECPoint(e1.getC2()); - ECPoint e2c1 = decodeECPoint(e2.getC1()); - ECPoint e2c2 = decodeECPoint(e2.getC2()); - ECPoint e1Nc1 = decodeECPoint(e1New.getC1()); - ECPoint e1Nc2 = decodeECPoint(e1New.getC2()); - ECPoint e2Nc1 = decodeECPoint(e2New.getC1()); - ECPoint e2Nc2 = decodeECPoint(e2New.getC2()); + ECPoint e1c1 = encryptor.decodeElement(e1.getC1()); + ECPoint e1c2 = encryptor.decodeElement(e1.getC2()); + ECPoint e2c1 = encryptor.decodeElement(e2.getC1()); + ECPoint e2c2 = encryptor.decodeElement(e2.getC2()); + ECPoint e1Nc1 = encryptor.decodeElement(e1New.getC1()); + ECPoint e1Nc2 = encryptor.decodeElement(e1New.getC2()); + ECPoint e2Nc1 = encryptor.decodeElement(e2New.getC1()); + ECPoint e2Nc2 = encryptor.decodeElement(e2New.getC2()); c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1)); c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1)); @@ -188,6 +181,9 @@ public class ECElGamalMixParams { } } + /** + * A statement with additional witness information that enables us to generate a ZK proof. + */ public class ProverStatement extends Statement { /** * True iff the ciphertexts were switched (i.e., decrypt(e1N) == decrypt(e2) and decrypt(e2N) == decrypt(e1) @@ -206,14 +202,14 @@ public class ECElGamalMixParams { @Override protected void generateOrStatements() { - byte[] c1_e1NDive1Encoded = group.encode(c1_e1NDive1); - byte[] c1_e2NDive1Encoded = group.encode(c1_e2NDive1); - byte[] c1_e1NDive2Encoded = group.encode(c1_e1NDive2); - byte[] c1_e2NDive2Encoded = group.encode(c1_e2NDive2); - byte[] c2_e1NDive1Encoded = group.encode(c2_e1NDive1); - byte[] c2_e2NDive1Encoded = group.encode(c2_e2NDive1); - byte[] c2_e1NDive2Encoded = group.encode(c2_e1NDive2); - byte[] c2_e2NDive2Encoded = group.encode(c2_e2NDive2); + ConcreteCrypto.GroupElement c1_e1NDive1Encoded = encryptor.encodeElement(c1_e1NDive1); + ConcreteCrypto.GroupElement c1_e2NDive1Encoded = encryptor.encodeElement(c1_e2NDive1); + ConcreteCrypto.GroupElement c1_e1NDive2Encoded = encryptor.encodeElement(c1_e1NDive2); + ConcreteCrypto.GroupElement c1_e2NDive2Encoded = encryptor.encodeElement(c1_e2NDive2); + ConcreteCrypto.GroupElement c2_e1NDive1Encoded = encryptor.encodeElement(c2_e1NDive1); + ConcreteCrypto.GroupElement c2_e2NDive1Encoded = encryptor.encodeElement(c2_e2NDive1); + ConcreteCrypto.GroupElement c2_e1NDive2Encoded = encryptor.encodeElement(c2_e1NDive2); + ConcreteCrypto.GroupElement c2_e2NDive2Encoded = encryptor.encodeElement(c2_e2NDive2); if (!switched) { @@ -304,20 +300,29 @@ public class ECElGamalMixParams { } } + /** + * An {@link OrStatement} with additional info needed to generate a ZK proof. + */ public class OrProverStatement extends OrStatement { - protected final byte[] g1Encoded; - protected final byte[] h1Encoded; - protected final byte[] g2Encoded; - protected final byte[] h2Encoded; - protected final byte[] g1TagEncoded; - protected final byte[] h1TagEncoded; - protected final byte[] g2TagEncoded; - protected final byte[] h2TagEncoded; + protected final Crypto.EncryptionRandomness x; protected final TrueCouple flag; + // We cache the encoded versions since we need them as input to the random oracle + // when using the Fiat-Shamir heuristic. + + protected final ConcreteCrypto.GroupElement g1Encoded; + protected final ConcreteCrypto.GroupElement h1Encoded; + protected final ConcreteCrypto.GroupElement g2Encoded; + protected final ConcreteCrypto.GroupElement h2Encoded; + + protected final ConcreteCrypto.GroupElement g1TagEncoded; + protected final ConcreteCrypto.GroupElement h1TagEncoded; + protected final ConcreteCrypto.GroupElement g2TagEncoded; + protected final ConcreteCrypto.GroupElement h2TagEncoded; + private OrProverStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag, - byte[] h1Encoded, byte[] h2Encoded, byte[] h1TagEncoded, byte[] h2TagEncoded, + ConcreteCrypto.GroupElement h1Encoded, ConcreteCrypto.GroupElement h2Encoded, ConcreteCrypto.GroupElement h1TagEncoded, ConcreteCrypto.GroupElement h2TagEncoded, Crypto.EncryptionRandomness x, TrueCouple flag) { super(h1, h2, h1Tag, h2Tag); this.g1Encoded = gEncoded; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index cc8e46b..cfa4407 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -1,8 +1,8 @@ package meerkat.mixer.proofs; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -26,14 +26,14 @@ public class Prover implements Mix2ZeroKnowledgeProver { private final ECElGamalEncryption encryptor; private final ECPoint g,h; private final BigInteger groupOrderUpperBound; - private final ECElGamalMixParams organizer; + private final ECElGamalMixParams mixParams; /** * @param rand * @param encryptor * @param randomOracle - use for Fiat–Shamir heuristic */ - public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) { + public Prover(Random rand, ECElGamalEncryption encryptor, RandomOracle randomOracle) { this.rand = rand; this.encryptor = encryptor; @@ -41,16 +41,16 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.group = this.encryptor.getGroup(); this.g = group.getGenerator(); this.h = this.encryptor.getElGamalPK().getPK(); - this.organizer = new ECElGamalMixParams(group,g,h); + this.mixParams = new ECElGamalMixParams(encryptor); this.groupOrderUpperBound = group.orderUpperBound(); } /** * @param in1 * @param in2 - * @param out1 - if sw then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1) - * @param out2 - if sw then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2) - * @param sw - flag + * @param out1 - if switched then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1) + * @param out2 - if switched then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2) + * @param switched - flag * @param i - column of in1 and out1 in encryption table * @param j - column of in2 and out2 in encryption table * @param layer - row of in1,in2 in encryption table @@ -63,17 +63,17 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, - boolean sw,int i,int j, int layer, + boolean switched,int i,int j, int layer, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; - ECElGamalMixParams.ProverStatement statement = organizer.createProverStatement(in1,in2,out1,out2,r1,r2,sw); + ECElGamalMixParams.ProverStatement statement = mixParams.createProverStatement(in1,in2,out1,out2,r1,r2,switched); - first = createOrProofElGamal(statement.getOrStatement(0)); - second = createOrProofElGamal(statement.getOrStatement(1)); - third = createOrProofElGamal(statement.getOrStatement(2)); - fourth = createOrProofElGamal(statement.getOrStatement(3)); + first = createOrProof(statement.getOrStatement(0)); + second = createOrProof(statement.getOrStatement(1)); + third = createOrProof(statement.getOrStatement(2)); + fourth = createOrProof(statement.getOrStatement(3)); Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() .setI(i) @@ -98,18 +98,28 @@ public class Prover implements Mix2ZeroKnowledgeProver { * @param randomOracle * @return randomOracle.hash(input) */ - public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle input, RandomOracle randomOracle) { + public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.FirstMessage input, RandomOracle randomOracle) { byte[] arr = input.toByteArray(); return new BigInteger(1,randomOracle.hash(arr,arr.length)); } /** + * Generate a ZK proof that there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2). + * + * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g1}(h1)==log_{g1}(h2)): + *
    + *
  1. Prover chooses a random r, and sends g1^r, g2^r
  2. + *
  3. Verifier chooses a random c and sends c
  4. + *
  5. Prover computes
  6. + *
+ * + * * @param orStatement - * @return ZKP OrProof: there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2) + * @return ZKP OrProof: * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs */ - private Mixing.ZeroKnowledgeProof.OrProof createOrProofElGamal(ECElGamalMixParams.OrProverStatement orStatement) { + private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) { ECPoint g1 = orStatement.g1; ECPoint h1 = orStatement.h1; @@ -121,16 +131,19 @@ public class Prover implements Mix2ZeroKnowledgeProver { ECPoint g2Tag = orStatement.g2Tag; ECPoint h2Tag = orStatement.h2Tag; - BigInteger r = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); + // Randomness for the ZK proof + BigInteger r = encryptor.generateRandomExponent(rand); + + BigInteger c1,c2,z,zTag; ECPoint u,v,uTag,vTag; - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle; + Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; switch (orStatement.flag) { case left: - c2 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); - zTag = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); + c2 = encryptor.generateRandomExponent(rand); + zTag = encryptor.generateRandomExponent(rand); //step 1 u = group.multiply(g1, r); v = group.multiply(g2, r); @@ -138,29 +151,29 @@ public class Prover implements Mix2ZeroKnowledgeProver { vTag = group.add(group.multiply(g2Tag, zTag), group.negate(group.multiply(h2Tag, c2))); //step 2 // c1 = (hash(input + step1) + group size - c2)% group size - forRandomOracle = - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(orStatement.g1Encoded)) - .setH1(ByteString.copyFrom(orStatement.h1Encoded)) - .setG2(ByteString.copyFrom(orStatement.g2Encoded)) - .setH2(ByteString.copyFrom(orStatement.h2Encoded)) - .setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded)) - .setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded)) - .setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded)) - .setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded)) - .setU(ByteString.copyFrom(group.encode(u))) - .setV(ByteString.copyFrom(group.encode(v))) - .setUTag(ByteString.copyFrom(group.encode(uTag))) - .setVTag(ByteString.copyFrom(group.encode(vTag))) + firstMessage = + Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() + .setG1(orStatement.g1Encoded) + .setH1(orStatement.h1Encoded) + .setG2(orStatement.g2Encoded) + .setH2(orStatement.h2Encoded) + .setG1Tag(orStatement.g1TagEncoded) + .setH1Tag(orStatement.h1TagEncoded) + .setG2Tag(orStatement.g2TagEncoded) + .setH2Tag(orStatement.h2TagEncoded) + .setU(encryptor.encodeElement(u)) + .setV(encryptor.encodeElement(v)) + .setUTag(encryptor.encodeElement(uTag)) + .setVTag(encryptor.encodeElement(vTag)) .build(); - c1 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); + c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); //step 3 //z = (r + c1 * x) % group size; z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); break; case right: - c1 = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); - z = encryptor.extractRandomness(encryptor.generateRandomness(rand)).mod(groupOrderUpperBound); + c1 = encryptor.generateRandomExponent(rand); + z = encryptor.generateRandomExponent(rand); //step 1 uTag = group.multiply(g1Tag, r); vTag = group.multiply(g2Tag, r); @@ -168,22 +181,22 @@ public class Prover implements Mix2ZeroKnowledgeProver { v = group.add(group.multiply(g2, z), group.negate(group.multiply(h2, c1))); //step 2 // c1 = (hash(input + step1) + group size - c1)% group size - forRandomOracle = - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(orStatement.g1Encoded)) - .setH1(ByteString.copyFrom(orStatement.h1Encoded)) - .setG2(ByteString.copyFrom(orStatement.g2Encoded)) - .setH2(ByteString.copyFrom(orStatement.h2Encoded)) - .setG1Tag(ByteString.copyFrom(orStatement.g1TagEncoded)) - .setH1Tag(ByteString.copyFrom(orStatement.h1TagEncoded)) - .setG2Tag(ByteString.copyFrom(orStatement.g2TagEncoded)) - .setH2Tag(ByteString.copyFrom(orStatement.h2TagEncoded)) - .setU(ByteString.copyFrom(group.encode(u))) - .setV(ByteString.copyFrom(group.encode(v))) - .setUTag(ByteString.copyFrom(group.encode(uTag))) - .setVTag(ByteString.copyFrom(group.encode(vTag))) + firstMessage = + Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() + .setG1(orStatement.g1Encoded) + .setH1(orStatement.h1Encoded) + .setG2(orStatement.g2Encoded) + .setH2(orStatement.h2Encoded) + .setG1Tag(orStatement.g1TagEncoded) + .setH1Tag(orStatement.h1TagEncoded) + .setG2Tag(orStatement.g2TagEncoded) + .setH2Tag(orStatement.h2TagEncoded) + .setU(encryptor.encodeElement(u)) + .setV(encryptor.encodeElement(v)) + .setUTag(encryptor.encodeElement(uTag)) + .setVTag(encryptor.encodeElement(vTag)) .build(); - c2 = hash(forRandomOracle,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); + c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); //step 3 //zTag = (r + c2 * x) % group size; zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); @@ -194,22 +207,22 @@ public class Prover implements Mix2ZeroKnowledgeProver { return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() - .setG1(forRandomOracle.getG1()) - .setH1(forRandomOracle.getH1()) - .setG2(forRandomOracle.getG2()) - .setH2(forRandomOracle.getH2()) - .setG1Tag(forRandomOracle.getG1()) - .setH1Tag(forRandomOracle.getH1Tag()) - .setG2Tag(forRandomOracle.getG2Tag()) - .setH2Tag(forRandomOracle.getH2Tag()) - .setU(forRandomOracle.getU()) - .setV(forRandomOracle.getV()) - .setUTag(forRandomOracle.getUTag()) - .setVTag(forRandomOracle.getVTag()) - .setC1(ByteString.copyFrom(c1.toByteArray())) - .setC2(ByteString.copyFrom(c2.toByteArray())) - .setZ(ByteString.copyFrom(z.toByteArray())) - .setZTag(ByteString.copyFrom(zTag.toByteArray())) + .setG1(firstMessage.getG1()) + .setH1(firstMessage.getH1()) + .setG2(firstMessage.getG2()) + .setH2(firstMessage.getH2()) + .setG1Tag(firstMessage.getG1()) + .setH1Tag(firstMessage.getH1Tag()) + .setG2Tag(firstMessage.getG2Tag()) + .setH2Tag(firstMessage.getH2Tag()) + .setU(firstMessage.getU()) + .setV(firstMessage.getV()) + .setUTag(firstMessage.getUTag()) + .setVTag(firstMessage.getVTag()) + .setC1(Util.encodeBigInteger(c1)) + .setC2(Util.encodeBigInteger(c2)) + .setZ(Util.encodeBigInteger(z)) + .setZTag(Util.encodeBigInteger(zTag)) .build(); } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index 2dc9254..92ca859 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -18,7 +18,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { private final ECGroup group; private final RandomOracle randomOracle; private final ECPoint g,h; - private final ECElGamalMixParams organizer; + private final ECElGamalMixParams mixParams; private final ZeroKnowledgeOrProofParser parser; /** @@ -31,7 +31,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { this.g = group.getGenerator(); this.h = encryptor.getElGamalPK().getPK(); this.randomOracle = randomOracle; - this.organizer = new ECElGamalMixParams(group,g,h); + this.mixParams = new ECElGamalMixParams(encryptor); this.parser = new ZeroKnowledgeOrProofParser(group); } @@ -52,7 +52,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { - ECElGamalMixParams.Statement statement = organizer.createStatement(in1,in2,out1,out2); + ECElGamalMixParams.Statement statement = mixParams.createStatement(in1,in2,out1,out2); return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&& verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&& verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&& @@ -79,7 +79,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { container.g2Tag.equals(orStatement.g2Tag) && container.h2Tag.equals(orStatement.h2Tag) && container.c1.add(container.c2).mod(group.orderUpperBound()) - .equals(Prover.hash(container.forRandomOracle,randomOracle).mod(group.orderUpperBound())) && + .equals(Prover.hash(container.firstMessage,randomOracle).mod(group.orderUpperBound())) && group.multiply(container.g1, container.z) .equals(group.add(container.u, group.multiply(container.h1,container.c1))) && group.multiply(container.g2, container.z) diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java index bdd2b4c..a2ab318 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java @@ -1,6 +1,7 @@ package meerkat.mixer.proofs; -import com.google.protobuf.ByteString; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -32,15 +33,6 @@ public class ZeroKnowledgeOrProofParser { this.group = group; } - /** - * convert ByteString to ECPoint - * @param bs - * @return - */ - public ECPoint convert2ECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); - } - /** * inner class @@ -52,15 +44,15 @@ public class ZeroKnowledgeOrProofParser { public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag; public final ECPoint u,v,uTag,vTag; public final BigInteger c1,c2,z,zTag; - public final Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle; + public final Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; /** * constructor * @param orProof */ private ZeroKnowledgeOrProofContainer(Mixing.ZeroKnowledgeProof.OrProof orProof){ - this.forRandomOracle = - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() + this.firstMessage = + Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() .setG1(orProof.getG1()) .setH1(orProof.getH1()) .setG2(orProof.getG2()) @@ -74,22 +66,22 @@ public class ZeroKnowledgeOrProofParser { .setUTag(orProof.getUTag()) .setVTag(orProof.getVTag()) .build(); - this.g1 = convert2ECPoint(orProof.getG1()); - this.g2 = convert2ECPoint(orProof.getG2()); - this.h1 = convert2ECPoint(orProof.getH1()); - this.h2 = convert2ECPoint(orProof.getH2()); - this.g1Tag = convert2ECPoint(orProof.getG1Tag()); - this.g2Tag = convert2ECPoint(orProof.getG2Tag()); - this.h1Tag = convert2ECPoint(orProof.getH1Tag()); - this.h2Tag = convert2ECPoint(orProof.getH2Tag()); - this.u = convert2ECPoint(orProof.getU()); - this.v = convert2ECPoint(orProof.getV()); - this.uTag = convert2ECPoint(orProof.getUTag()); - this.vTag = convert2ECPoint(orProof.getVTag()); - this.c1 = new BigInteger(orProof.getC1().toByteArray()); - this.c2 = new BigInteger(orProof.getC2().toByteArray()); - this.z = new BigInteger(orProof.getZ().toByteArray()); - this.zTag = new BigInteger(orProof.getZTag().toByteArray()); + this.g1 = ECElGamalEncryption.decodeElement(group, orProof.getG1()); + this.g2 = ECElGamalEncryption.decodeElement(group, orProof.getG2()); + this.h1 = ECElGamalEncryption.decodeElement(group, orProof.getH1()); + this.h2 = ECElGamalEncryption.decodeElement(group, orProof.getH2()); + this.g1Tag = ECElGamalEncryption.decodeElement(group, orProof.getG1Tag()); + this.g2Tag = ECElGamalEncryption.decodeElement(group, orProof.getG2Tag()); + this.h1Tag = ECElGamalEncryption.decodeElement(group, orProof.getH1Tag()); + this.h2Tag = ECElGamalEncryption.decodeElement(group, orProof.getH2Tag()); + this.u = ECElGamalEncryption.decodeElement(group, orProof.getU()); + this.v = ECElGamalEncryption.decodeElement(group, orProof.getV()); + this.uTag = ECElGamalEncryption.decodeElement(group, orProof.getUTag()); + this.vTag = ECElGamalEncryption.decodeElement(group, orProof.getVTag()); + this.c1 = Util.decodeBigInteger(orProof.getC1()); + this.c2 = Util.decodeBigInteger(orProof.getC2()); + this.z = Util.decodeBigInteger(orProof.getZ()); + this.zTag = Util.decodeBigInteger(orProof.getZTag()); } } } diff --git a/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java b/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java index dea0069..860dafd 100644 --- a/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java +++ b/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java @@ -43,8 +43,8 @@ public class RerandomizeTest { h = enc.getElGamalPK().getPK(); } - private ECPoint convert2ECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); + private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){ + return enc.decodeElement(bs); } public void oneRerandomizeTest() throws InvalidProtocolBufferException { diff --git a/mixer/src/test/java/meerkat/mixer/Utils.java b/mixer/src/test/java/meerkat/mixer/Utils.java index 06329ef..c402876 100644 --- a/mixer/src/test/java/meerkat/mixer/Utils.java +++ b/mixer/src/test/java/meerkat/mixer/Utils.java @@ -62,11 +62,11 @@ public class Utils { public static T decrypt(Class plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher) throws InvalidProtocolBufferException { ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData()); - ByteString c1encoded = cipherText.getC1(); - ByteString c2encoded = cipherText.getC2(); + ConcreteCrypto.GroupElement c1encoded = cipherText.getC1(); + ConcreteCrypto.GroupElement c2encoded = cipherText.getC2(); - ECPoint c1 = group.decode(c1encoded.toByteArray()); - ECPoint c2 = group.decode(c2encoded.toByteArray()); + ECPoint c1 = ECElGamalEncryption.decodeElement(group, c1encoded); + ECPoint c2 = ECElGamalEncryption.decodeElement(group, c2encoded); assert (group.contains(c1)); assert (group.contains(c2)); @@ -87,7 +87,7 @@ public class Utils { } } - static Random random = new Random(); + static Random random = new Random(0); public static Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) { Voting.PlaintextBallot.Builder ballot = Voting.PlaintextBallot.newBuilder(); diff --git a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java b/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java index cb4d86b..0f7e729 100644 --- a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java @@ -9,6 +9,7 @@ import meerkat.mixer.proofs.Prover; import meerkat.mixer.proofs.Verifier; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; import meerkat.protobuf.Voting; //import meerkat.protobuf.Voting.PlaintextBallot; import org.bouncycastle.math.ec.ECPoint; @@ -51,8 +52,8 @@ public class ZeroKnowledgeProofTest { prover = new Prover(new Random(),enc,randomOracle); } - private ECPoint convert2ECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); + private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){ + return enc.decodeElement(bs); } public void oneZKPTest() throws InvalidProtocolBufferException { @@ -89,7 +90,10 @@ public class ZeroKnowledgeProofTest { assertEquals (h.multiply(enc.extractRandomness(r2)), group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2())))); - assertTrue (verifier.verify(e1,e2,e1New,e2New,prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2))); + + Mixing.ZeroKnowledgeProof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2); + + assertTrue (verifier.verify(e1,e2,e1New,e2New, proof)); } @Test diff --git a/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java b/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java index f9b5b2e..5e885f8 100644 --- a/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java +++ b/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java @@ -45,8 +45,8 @@ public class ByteString2ECPoint { (enc.encrypt(msg, enc.generateRandomness(rand))); } } - private ECPoint convert2ECPoint(ByteString bs){ - return group.decode(bs.toByteArray()); + private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){ + return enc.decodeElement(bs); } public void ByteString2ECPointProfiling() throws InvalidProtocolBufferException { From 97f52bfd820f3bea5ddf68313eeb7104933cfff5 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 9 Nov 2016 15:21:16 +0200 Subject: [PATCH 04/25] Fixed fatmain bug in build.gradle-template --- build.gradle-template | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/build.gradle-template b/build.gradle-template index 638c953..f80c9f3 100644 --- a/build.gradle-template +++ b/build.gradle-template @@ -131,17 +131,19 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { destinationDir = buildDir - def fatMain = hasProperty('fatmain') ? fatmain : mainClassName + def fatMain + + if (this.hasProperty('fatmain')) { + fatMain = fatmain + appendix = "fat-${fatMain}" + } else { + fatMain = mainClassName + appendix = "fat" + } applicationClass fatMain - def testJar = hasProperty('test') - - if (hasProperty('fatmain')) { - appendix = "fat-${fatMain}" - } else { - appendix = "fat" - } + def testJar = this.hasProperty('test') if (testJar) { from sourceSets.test.output From 9db8efd75b3b048e4b414e55546ee0c35b5e87ce Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Mon, 28 Nov 2016 13:51:24 +0200 Subject: [PATCH 05/25] Updated to gradle 3.2.1 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 7047800..1527da9 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.1-all.zip -distributionSha256Sum=43be380834a13e28e9504c21f67fe1a8895ab54f314a6596601896dca7213482 +distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-all.zip +distributionSha256Sum=0209696f1723f607c475109cf3ed8b51c8a91bb0cda05af0d4bd980bdefe75cd From b7ef2c10e19b9ed73abf0a7760866753f3d07018 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 11 Jan 2017 17:01:14 +0200 Subject: [PATCH 06/25] rewriting mixing proofs --- .../src/main/proto/meerkat/mixing.proto | 66 ++-- .../crypto/concrete/ECElGamalUtils.java | 5 +- .../mixer/proofs/ECElGamalMixParams.java | 358 ++++++------------ .../mixer/proofs/ECElGamalMixProtocols.java | 65 ++++ .../java/meerkat/mixer/proofs/Prover.java | 66 ++-- .../meerkat/mixer/proofs/SigmaProtocol.java | 26 ++ .../mixer/proofs/SigmaProtocolAnd.java | 59 +++ .../mixer/proofs/SigmaProtocolOr2.java | 82 ++++ .../java/meerkat/mixer/proofs/Verifier.java | 98 +++-- 9 files changed, 484 insertions(+), 341 deletions(-) create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/meerkat-common/src/main/proto/meerkat/mixing.proto index abbd0a1..eebce4b 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/meerkat-common/src/main/proto/meerkat/mixing.proto @@ -11,43 +11,37 @@ message Plaintext { bytes data = 1; } -message ZeroKnowledgeProof { - message OrProof { +message Mix2Proof { + // Proof that log_g(a) = log_h(b) = x + message DlogProof { message FirstMessage { - GroupElement g1 = 1; - GroupElement h1 = 2; - GroupElement g2 = 3; - GroupElement h2 = 4; - GroupElement g1Tag = 5; - GroupElement h1Tag = 6; - GroupElement g2Tag = 7; - GroupElement h2Tag = 8; - GroupElement u = 9; - GroupElement v = 10; - GroupElement uTag = 11; - GroupElement vTag = 12; + GroupElement gr = 1; // g^r + GroupElement hr = 2; // h^r } - //statement parameters : g1,h1, g2, h2, g1Tag, h1Tag, g2Tag, h2Tag; - GroupElement g1 = 1; - GroupElement h1 = 2; - GroupElement g2 = 3; - GroupElement h2 = 4; - GroupElement g1Tag = 5; - GroupElement h1Tag = 6; - GroupElement g2Tag = 7; - GroupElement h2Tag = 8; + message FinalMessage { + BigInteger xcr = 1; // xc+r, where c is the challenge + } + } - //calc: u, v, uTag, vTag; - GroupElement u = 9; - GroupElement v = 10; - GroupElement uTag = 11; - GroupElement vTag = 12; + message AndProof { + message FirstMessage { + DlogProof.FirstMessage clause0 = 1; + DlogProof.FirstMessage clause1 = 2; + } + message FinalMessage { + DlogProof.FinalMessage clause0 = 1; + DlogProof.FinalMessage clause1 = 2; + } + } - //generated: c1,c2,z,zTag - BigInteger c1 = 13; - BigInteger c2 = 14; - BigInteger z = 15; - BigInteger zTag = 16; + message FirstMessage { + AndProof.FirstMessage clause0 = 1; + AndProof.FirstMessage clause1 = 2; + } + message FinalMessage { + AndProof.FinalMessage clause0 = 1; + AndProof.FinalMessage clause1 = 2; + BigInteger c0 = 3; // Challenge for clause 0; challenge for clause 1 is computed from real challenge and c0 } message Location{ @@ -56,9 +50,7 @@ message ZeroKnowledgeProof { int32 layer = 3; } - OrProof first = 1; - OrProof second = 2; - OrProof third = 3; - OrProof fourth = 4; + FirstMessage firstMessage = 1; + FinalMessage finalMessage = 2; Location location = 5; } 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 e26e00b..c40128c 100644 --- a/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java +++ b/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java @@ -5,6 +5,7 @@ import com.google.protobuf.GeneratedMessage; import com.google.protobuf.InvalidProtocolBufferException; import com.google.protobuf.Message; import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; import org.bouncycastle.jce.spec.ECParameterSpec; import org.bouncycastle.jce.spec.ECPublicKeySpec; @@ -66,8 +67,8 @@ public class ECElGamalUtils { public static T decrypt(Class plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher) throws InvalidProtocolBufferException { ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData()); - ByteString c1encoded = cipherText.getC1(); - ByteString c2encoded = cipherText.getC2(); + GroupElement c1encoded = cipherText.getC1(); + GroupElement c2encoded = cipherText.getC2(); ECPoint c1 = group.decode(c1encoded.toByteArray()); ECPoint c2 = group.decode(c2encoded.toByteArray()); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java index 895253c..56c02d6 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java @@ -1,28 +1,31 @@ package meerkat.mixer.proofs; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; +import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; +import meerkat.protobuf.Crypto.EncryptionRandomness; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECGroup; +import java.math.BigInteger; + /** - * use for organize the input for each ZKP + * used for organizing the input for each ZKP * * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it */ public class ECElGamalMixParams { - private final ECElGamalEncryption encryptor; - private final ECGroup group; - private final ECPoint g; - private final ECPoint h; + final ECElGamalEncryption encryptor; + final ECGroup group; + final ECPoint g; + final ECPoint h; // Cache encoded formats to save multiple re-encodings - private final ConcreteCrypto.GroupElement gEncoded; - private final ConcreteCrypto.GroupElement hEncoded; + private final GroupElement gEncoded; + private final GroupElement hEncoded; /** * @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and @@ -45,297 +48,156 @@ public class ECElGamalMixParams { /** * can be used by anyone, e.g meerkat.mixer.verifier * - * call to the meerkat.mixer.main overload with flag = false + * call to the meerkat.mixer.main overload with trueClauseIndex = false */ - public Statement createStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 - , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException { + public Mix2Statement createStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2, + Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2) throws InvalidProtocolBufferException { - ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); - ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); - ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); - ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); - return new Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); + ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); + ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); + ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); + ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); + return new Mix2Statement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal); } /** * convert each encrypted message to ElGamalCiphertext * - * @throws InvalidProtocolBufferException - in case that at least one of the encrypted messages isn't + * @throws InvalidProtocolBufferException - in case one or more of the encrypted messages isn't * ElGamalCiphertext */ - protected ProverStatement createProverStatement(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2 - , Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2 - , Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) - throws InvalidProtocolBufferException { + protected Mix2StatementWitness createMix2Witness(EncryptionRandomness r1, EncryptionRandomness r2, boolean switched) { + // if (!switched), dlogW1 is witness for a ~ c, dlogW2 is witness for b ~ d, + // otherwise, dlogW1 is witness for a ~ d, dlogW2 is witness for b ~ c + DlogStatementWitness dlogW1 = new DlogStatementWitness(encryptor.extractRandomness(r1)); + DlogStatementWitness dlogW2 = new DlogStatementWitness(encryptor.extractRandomness(r2)); - //convert RerandomizableEncryptedMessage to ElGamalCiphertext - ConcreteCrypto.ElGamalCiphertext in1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in1); - ConcreteCrypto.ElGamalCiphertext in2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(in2); - ConcreteCrypto.ElGamalCiphertext out1ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out1); - ConcreteCrypto.ElGamalCiphertext out2ElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(out2); + AndStatementWitness andW = new AndStatementWitness(dlogW1, dlogW2); - return new ProverStatement(in1ElGamal, in2ElGamal, out1ElGamal, out2ElGamal, r1, r2, switched); + return new Mix2StatementWitness(switched ? 1 : 0, andW); } /** - * Statement to be proved. + * Mix2Statement to be proved. * * The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality. * - * A Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private) + * A Mix2Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private) * */ - public class Statement { + public class Mix2Statement { - /** - * Denote the first ciphertext pair e1=(e1c1,e1c2), e2=(e2c1,e2c2) and the second - * e1N=(e1Nc1, e1Nc2) and e2N=(e2Nc1,e2Nc2). - * Then ci_ejNDivek = ejNci/ekci - */ - ECPoint c1_e1NDive1; - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c1_e2NDive1; + public final AndStatement[] clauses = new AndStatement[2]; - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c1_e1NDive2; + private Mix2Statement(ElGamalCiphertext a, ElGamalCiphertext b, + ElGamalCiphertext c, ElGamalCiphertext d){ - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c1_e2NDive2; + ECPoint a1 = encryptor.decodeElement(a.getC1()); + ECPoint a2 = encryptor.decodeElement(a.getC2()); + ECPoint b1 = encryptor.decodeElement(b.getC1()); + ECPoint b2 = encryptor.decodeElement(b.getC2()); + ECPoint c1 = encryptor.decodeElement(c.getC1()); + ECPoint c2 = encryptor.decodeElement(c.getC2()); + ECPoint d1 = encryptor.decodeElement(d.getC1()); + ECPoint d2 = encryptor.decodeElement(d.getC2()); - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c2_e1NDive1; + ECPoint c1_div_a1 = group.add(c1, group.negate(a1)); + ECPoint d1_div_a1 = group.add(d1, group.negate(a1)); + ECPoint c1_div_b1 = group.add(c1, group.negate(b1)); + ECPoint d1_div_b1 = group.add(d1, group.negate(b1)); + ECPoint c2_div_a2 = group.add(c2, group.negate(a2)); + ECPoint d2_div_a2 = group.add(d2, group.negate(a2)); + ECPoint c2_div_b2 = group.add(c2, group.negate(b2)); + ECPoint d2_div_b2 = group.add(d2, group.negate(b2)); - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c2_e2NDive1; + // "Straight assignment" (a ~ c, b ~ d) + DlogStatement s0_0 = new DlogStatement(c1_div_a1, c2_div_a2); + DlogStatement s0_1 = new DlogStatement(d1_div_b1, d2_div_b2); + clauses[0] = new AndStatement(s0_0, s0_1); - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c2_e1NDive2; - - /** - * See {@link #c1_e1NDive1} - */ - ECPoint c2_e2NDive2; - - - private final OrStatement orStatements[] = new OrStatement[4]; - - - public OrStatement getOrStatement(int num) { - if (orStatements[0] == null) - generateOrStatements(); - - return orStatements[num]; - } - - public void setOrStatement(int num, OrStatement orStatement) { - orStatements[num] = orStatement; + // "Switched assignment" (a ~ d, b ~ c) + DlogStatement s1_0 = new DlogStatement(d1_div_a1, d2_div_a2); + DlogStatement s1_1 = new DlogStatement(c1_div_b1, c2_div_b2); + clauses[1] = new AndStatement(s1_0, s1_1); } + } + /** + * Witness information that enables us to generate a ZK proof for the 2-ciphertext mix + */ + public class Mix2StatementWitness { /** - * Generate and set the four substatements. + * Which of the two clauses is the true one */ - protected void generateOrStatements() { - setOrStatement(0, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e1NDive2,c2_e1NDive2)); - setOrStatement(1, new OrStatement(c1_e1NDive1,c2_e1NDive1,c1_e2NDive1,c2_e2NDive1)); - setOrStatement(2, new OrStatement(c1_e1NDive2,c2_e1NDive2,c1_e2NDive2,c2_e2NDive2)); - setOrStatement(3, new OrStatement(c1_e2NDive1,c2_e2NDive1,c1_e2NDive2,c2_e2NDive2)); + public final int trueClauseIndex; + + public final AndStatementWitness witness; + + private Mix2StatementWitness(int trueClauseIndex, AndStatementWitness witness) { + + this.trueClauseIndex = trueClauseIndex; + assert (trueClauseIndex >= 0 && trueClauseIndex < 2); + this.witness = witness; } + } - private Statement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2, - ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New){ + /** + * Statement consisting of a conjunction of two {@link DlogStatement}s + */ + public class AndStatement { + public final DlogStatement[] clauses = new DlogStatement[2]; - ECPoint e1c1 = encryptor.decodeElement(e1.getC1()); - ECPoint e1c2 = encryptor.decodeElement(e1.getC2()); - ECPoint e2c1 = encryptor.decodeElement(e2.getC1()); - ECPoint e2c2 = encryptor.decodeElement(e2.getC2()); - ECPoint e1Nc1 = encryptor.decodeElement(e1New.getC1()); - ECPoint e1Nc2 = encryptor.decodeElement(e1New.getC2()); - ECPoint e2Nc1 = encryptor.decodeElement(e2New.getC1()); - ECPoint e2Nc2 = encryptor.decodeElement(e2New.getC2()); + private AndStatement(DlogStatement clause0, DlogStatement clause1) { + this.clauses[0] = clause0; + this.clauses[1] = clause1; + } + } - c1_e1NDive1 = group.add(e1Nc1, group.negate(e1c1)); - c1_e2NDive1 = group.add(e2Nc1, group.negate(e1c1)); - c1_e1NDive2 = group.add(e1Nc1, group.negate(e2c1)); - c1_e2NDive2 = group.add(e2Nc1, group.negate(e2c1)); - c2_e1NDive1 = group.add(e1Nc2, group.negate(e1c2)); - c2_e2NDive1 = group.add(e2Nc2, group.negate(e1c2)); - c2_e1NDive2 = group.add(e1Nc2, group.negate(e2c2)); - c2_e2NDive2 = group.add(e2Nc2, group.negate(e2c2)); + public class AndStatementWitness { + public final DlogStatementWitness[] witnesses = new DlogStatementWitness[2]; + + private AndStatementWitness(DlogStatementWitness witness0, DlogStatementWitness witness1) { + this.witnesses[0] = witness0; + this.witnesses[1] = witness1; } } /** - * A statement with additional witness information that enables us to generate a ZK proof. + * The parameters for a statement of discrete-log equality + * + * log_{g}(a)==log_{h}(b) */ - public class ProverStatement extends Statement { - /** - * True iff the ciphertexts were switched (i.e., decrypt(e1N) == decrypt(e2) and decrypt(e2N) == decrypt(e1) - */ - boolean switched; - - /** - * Encryption randomness for e1 rerandomization - */ - Crypto.EncryptionRandomness r1; - - /** - * Encryption randomnesss for e2 rerandomization - */ - Crypto.EncryptionRandomness r2; - - @Override - protected void generateOrStatements() { - ConcreteCrypto.GroupElement c1_e1NDive1Encoded = encryptor.encodeElement(c1_e1NDive1); - ConcreteCrypto.GroupElement c1_e2NDive1Encoded = encryptor.encodeElement(c1_e2NDive1); - ConcreteCrypto.GroupElement c1_e1NDive2Encoded = encryptor.encodeElement(c1_e1NDive2); - ConcreteCrypto.GroupElement c1_e2NDive2Encoded = encryptor.encodeElement(c1_e2NDive2); - ConcreteCrypto.GroupElement c2_e1NDive1Encoded = encryptor.encodeElement(c2_e1NDive1); - ConcreteCrypto.GroupElement c2_e2NDive1Encoded = encryptor.encodeElement(c2_e2NDive1); - ConcreteCrypto.GroupElement c2_e1NDive2Encoded = encryptor.encodeElement(c2_e1NDive2); - ConcreteCrypto.GroupElement c2_e2NDive2Encoded = encryptor.encodeElement(c2_e2NDive2); - - - if (!switched) { - setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded - , r1, TrueCouple.left)); - setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded - , r1, TrueCouple.left)); - setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 - , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.right)); - setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 - , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.right)); - } else { - setOrStatement(0, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e1NDive2, c2_e1NDive2 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e1NDive2Encoded, c2_e1NDive2Encoded - , r2, TrueCouple.right)); - setOrStatement(1, new OrProverStatement(c1_e1NDive1, c2_e1NDive1, c1_e2NDive1, c2_e2NDive1 - , c1_e1NDive1Encoded, c2_e1NDive1Encoded, c1_e2NDive1Encoded, c2_e2NDive1Encoded - , r1, TrueCouple.right)); - setOrStatement(2, new OrProverStatement(c1_e1NDive2, c2_e1NDive2, c1_e2NDive2, c2_e2NDive2 - , c1_e1NDive2Encoded, c2_e1NDive2Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r2, TrueCouple.left)); - setOrStatement(3, new OrProverStatement(c1_e2NDive1, c2_e2NDive1, c1_e2NDive2, c2_e2NDive2 - , c1_e2NDive1Encoded, c2_e2NDive1Encoded, c1_e2NDive2Encoded, c2_e2NDive2Encoded - , r1, TrueCouple.left)); - } - } - - - @Override - public OrProverStatement getOrStatement(int num) { - OrStatement orStatement = super.getOrStatement(num); - if (!(orStatement instanceof OrProverStatement)) - throw new RuntimeException("ProverStatement should always have OrProverStatement substatements!!"); - - return (OrProverStatement) orStatement; - } - - private ProverStatement(ConcreteCrypto.ElGamalCiphertext e1, ConcreteCrypto.ElGamalCiphertext e2, - ConcreteCrypto.ElGamalCiphertext e1New, ConcreteCrypto.ElGamalCiphertext e2New, - Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2, boolean switched) { - super(e1, e2, e1New, e2New); - this.r1 = r1; - this.r2 = r2; - this.switched = switched; - } - - } - - /** - * The statement of a single disjunction to be proved: - * Either there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or there exists x s.t. (g1' ^ x == h1 and g2' ^ x == h2) - * - * The statement can't be constructed externally (all constructors are private) - * - * 4 instances will be constructed for each new {@link ECElGamalMixParams.Statement} - * - */ - public class OrStatement { - public final ECPoint g1; - public final ECPoint h1; - public final ECPoint g2; - public final ECPoint h2; - public final ECPoint g1Tag; - public final ECPoint h1Tag; - public final ECPoint g2Tag; - public final ECPoint h2Tag; - - - /** - * used by meerkat.mixer.proofs only - */ - private OrStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag) { - this.g1 = g; - this.h1 = h1; - this.g2 = h; - this.h2 = h2; - this.g1Tag = g; - this.h1Tag = h1Tag; - this.g2Tag = h; - this.h2Tag = h2Tag; - + public class DlogStatement { + public final ECPoint g; + public final ECPoint a; + public final ECPoint h; + public final ECPoint b; + private DlogStatement(ECPoint a, ECPoint b) { + this.g = ECElGamalMixParams.this.g; + this.a = a; + this.h = ECElGamalMixParams.this.h; + this.b = b; } } /** - * An {@link OrStatement} with additional info needed to generate a ZK proof. + * Witness for correctness of a {@link DlogStatement} */ - public class OrProverStatement extends OrStatement { - - protected final Crypto.EncryptionRandomness x; - protected final TrueCouple flag; - - // We cache the encoded versions since we need them as input to the random oracle - // when using the Fiat-Shamir heuristic. - - protected final ConcreteCrypto.GroupElement g1Encoded; - protected final ConcreteCrypto.GroupElement h1Encoded; - protected final ConcreteCrypto.GroupElement g2Encoded; - protected final ConcreteCrypto.GroupElement h2Encoded; - - protected final ConcreteCrypto.GroupElement g1TagEncoded; - protected final ConcreteCrypto.GroupElement h1TagEncoded; - protected final ConcreteCrypto.GroupElement g2TagEncoded; - protected final ConcreteCrypto.GroupElement h2TagEncoded; - - private OrProverStatement(ECPoint h1, ECPoint h2, ECPoint h1Tag, ECPoint h2Tag, - ConcreteCrypto.GroupElement h1Encoded, ConcreteCrypto.GroupElement h2Encoded, ConcreteCrypto.GroupElement h1TagEncoded, ConcreteCrypto.GroupElement h2TagEncoded, - Crypto.EncryptionRandomness x, TrueCouple flag) { - super(h1, h2, h1Tag, h2Tag); - this.g1Encoded = gEncoded; - this.h1Encoded = h1Encoded; - this.g2Encoded = hEncoded; - this.h2Encoded = h2Encoded; - this.g1TagEncoded = gEncoded; - this.h1TagEncoded = h1TagEncoded; - this.g2TagEncoded = hEncoded; - this.h2TagEncoded = h2TagEncoded; + public class DlogStatementWitness { + /** + * The actual discrete logarithm (i.e., a=g^x, b=h^x) + */ + BigInteger x; + public DlogStatementWitness(BigInteger x) { this.x = x; - this.flag = flag; } } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java new file mode 100644 index 0000000..62d7c6d --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java @@ -0,0 +1,65 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.concrete.ECGroup; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Prover, Simulator and Verifier + */ +public class ECElGamalMixProtocols { + final ECElGamalMixParams params; + final ECGroup group; + final ECElGamalEncryption encryptor; + final ECPoint g; + final ECPoint h; + final Random rand; + + + public ECElGamalMixProtocols(ECElGamalMixParams params, Random rand) { + this.params = params; + this.rand = rand; + group = params.group; + encryptor = params.encryptor; + g = params.g; + h = params.h; + } + + public class DlogStatementSchnorrProver implements SigmaProtocol.Prover { + ECElGamalMixParams.DlogStatement statement; + ECElGamalMixParams.DlogStatementWitness witness; + + BigInteger r = null; + + public DlogStatementSchnorrProver(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { + this.statement = statement; + this.witness = witness; + } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage() { + r = encryptor.generateRandomExponent(rand); + ECPoint gr = group.multiply(statement.g, r); + ECPoint hr = group.multiply(statement.h, r); + + Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + .setGr(encryptor.encodeElement(gr)) + .setHr(encryptor.encodeElement(hr)) + .build(); + + return firstMessage; + } + + @Override + public Crypto.BigInteger getFinalMessage(BigInteger challenge) { + return Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound())); + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index cfa4407..91a3c24 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -46,34 +46,34 @@ public class Prover implements Mix2ZeroKnowledgeProver { } /** - * @param in1 - * @param in2 - * @param out1 - if switched then out1 = rerandomize(in2,r2) else out1 = rerandomize(in1,r1) - * @param out2 - if switched then out2 = rerandomize(in1,r1) else out1 = rerandomize(in2,r2) - * @param switched - flag - * @param i - column of in1 and out1 in encryption table - * @param j - column of in2 and out2 in encryption table - * @param layer - row of in1,in2 in encryption table + * @param a + * @param b + * @param c - if switched then c = rerandomize(b,r2) else c = rerandomize(a,r1) + * @param d - if switched then d = rerandomize(a,r1) else d = rerandomize(b,r2) + * @param switched - trueClauseIndex + * @param i - column of a and c in encryption table + * @param j - column of b and d in encryption table + * @param layer - row of a,b in encryption table * @param r1 * @param r2 - * @return - a valid ZKP that indeed out1,out2 calculated as required + * @return - a valid ZKP that indeed c,d calculated as required * @throws InvalidProtocolBufferException */ - public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, - Crypto.RerandomizableEncryptedMessage in2, - Crypto.RerandomizableEncryptedMessage out1, - Crypto.RerandomizableEncryptedMessage out2, + public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage a, + Crypto.RerandomizableEncryptedMessage b, + Crypto.RerandomizableEncryptedMessage c, + Crypto.RerandomizableEncryptedMessage d, boolean switched,int i,int j, int layer, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { - Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; + Mixing.Mix2Proof first,second,third,fourth; - ECElGamalMixParams.ProverStatement statement = mixParams.createProverStatement(in1,in2,out1,out2,r1,r2,switched); + ECElGamalMixParams.MixStatementWitness statement = mixParams.createProverStatement(a,b,c,d,r1,r2,switched); - first = createOrProof(statement.getOrStatement(0)); - second = createOrProof(statement.getOrStatement(1)); - third = createOrProof(statement.getOrStatement(2)); - fourth = createOrProof(statement.getOrStatement(3)); + first = createOrProof(statement.getDlogStatement(0)); + second = createOrProof(statement.getDlogStatement(1)); + third = createOrProof(statement.getDlogStatement(2)); + fourth = createOrProof(statement.getDlogStatement(3)); Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() .setI(i) @@ -98,18 +98,36 @@ public class Prover implements Mix2ZeroKnowledgeProver { * @param randomOracle * @return randomOracle.hash(input) */ - public static BigInteger hash(Mixing.ZeroKnowledgeProof.OrProof.FirstMessage input, RandomOracle randomOracle) { + public static BigInteger hash(Mixing.Mix2Proof.FirstMessage input, RandomOracle randomOracle) { byte[] arr = input.toByteArray(); return new BigInteger(1,randomOracle.hash(arr,arr.length)); } + + Mixing.Mix2Proof.DlogProof.FirstMessage createDlogProof(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { + + BigInteger r = encryptor.generateRandomExponent(rand); + ECPoint gr = group.multiply(statement.g, r); + ECPoint hr = group.multiply(statement.h, r); + + Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + .setGr(group.encode(gr)) + .setHr(group.encode(hr)) + .build(); + + BigInteger challenge = Prover.hash() + } + + + + /** - * Generate a ZK proof that there exists x s.t (g1 ^ x == h1 and g2 ^ x == h2) or (g1' ^ x == h1 and g2' ^ x == h2). + * Generate a ZK proof that there exists x s.t (g ^ x == a and h ^ x == b) or (g' ^ x == a and h' ^ x == b). * - * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g1}(h1)==log_{g1}(h2)): + * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g}(a)==log_{g}(b)): *
    - *
  1. Prover chooses a random r, and sends g1^r, g2^r
  2. + *
  3. Prover chooses a random r, and sends g^r, h^r
  4. *
  5. Verifier chooses a random c and sends c
  6. *
  7. Prover computes
  8. *
@@ -140,7 +158,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; - switch (orStatement.flag) { + switch (orStatement.trueClauseIndex) { case left: c2 = encryptor.generateRandomExponent(rand); zTag = encryptor.generateRandomExponent(rand); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java new file mode 100644 index 0000000..c0e6c59 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java @@ -0,0 +1,26 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; + +import java.math.BigInteger; + +/** + * Generic Sigma Protocol. + * The challenge is always a {@link java.math.BigInteger}. + */ +public interface SigmaProtocol { + public interface Prover { + public Message getFirstMessage(); + public Message getFinalMessage(BigInteger challenge); + } + + public interface Simulator { + public Message getFirstMessage(); + public BigInteger getChallenge(); + public Message getFinalMessage(); + } + + public interface Verifier { + public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage); + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java new file mode 100644 index 0000000..4dc2424 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java @@ -0,0 +1,59 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; + +import java.math.BigInteger; + +/** + * Generic conjuction of sigma protocols + */ +public class SigmaProtocolAnd { + abstract public class Prover implements SigmaProtocol.Prover { + final SigmaProtocol.Prover[] provers; + + abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); + abstract protected Message buildConcatenatedFinalMessage(Message... finalMessages); + + public Prover(SigmaProtocol.Prover... provers) { + this.provers = provers; + } + + @Override + public Message getFirstMessage() { + Message[] firstMessages = new Message[provers.length]; + for (int i = 0; i < firstMessages.length; ++i) { + firstMessages[i] = provers[i].getFirstMessage(); + } + return buildConcatenatedFirstMessage(firstMessages); + } + + @Override + public Message getFinalMessage(BigInteger challenge) { + Message[] finalMessages = new Message[provers.length]; + for (int i = 0; i < finalMessages.length; ++i) { + finalMessages[i] = provers[i].getFinalMessage(challenge); + } + return buildConcatenatedFinalMessage(finalMessages); + } + } + + abstract public class Verifier implements SigmaProtocol.Verifier { + final SigmaProtocol.Verifier[] verifiers; + + abstract protected Message getFirstMessage(Message concatenated, int verifier); + abstract protected Message getFinalMessage(Message concatenated, int verifier); + + public Verifier(SigmaProtocol.Verifier... verifiers) { + this.verifiers = verifiers; + } + + public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { + boolean ok = true; + + for (int i = 0; i < verifiers.length; ++i) { + ok &= verifiers[i].verify(getFirstMessage(firstMessage, i), challenge, getFinalMessage(finalMessage, i)); + } + return ok; + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java new file mode 100644 index 0000000..febb8af --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java @@ -0,0 +1,82 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; + +import java.math.BigInteger; + +/** + * Disjunction of 2 Sigma protocol statements + */ +public class SigmaProtocolOr2 { + abstract public class Prover implements SigmaProtocol.Prover { + final SigmaProtocol.Prover prover; + final SigmaProtocol.Simulator simulator; + final int proverIdx; + + abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); + abstract protected Message buildConcatenatedFinalMessage(BigInteger firstChallenge, Message... finalMessages); + + /** + * Subtract two challenges in an appropriate way (e.g., mod group order) + * @param c1 + * @param c2 + * @return + */ + abstract protected BigInteger subtractChallenge(BigInteger c1, BigInteger c2); + + /** + * + * @param prover + * @param simulator + * @param proverIdx Which index should the prover be inserted at (0 means first, 1 means second) + */ + public Prover(SigmaProtocol.Prover prover, SigmaProtocol.Simulator simulator, int proverIdx) { + this.prover = prover; + this.simulator = simulator; + this.proverIdx = proverIdx; + assert (proverIdx >= 0 && proverIdx < 2); + } + + @Override + public Message getFirstMessage() { + if (proverIdx == 0) { + return buildConcatenatedFirstMessage(prover.getFirstMessage(), simulator.getFirstMessage()); + } else { + return buildConcatenatedFirstMessage(simulator.getFirstMessage(), prover.getFirstMessage()); + } + } + + + @Override + public Message getFinalMessage(BigInteger challenge) { + BigInteger realchallenge = subtractChallenge(challenge, simulator.getChallenge()); + if (proverIdx == 0) { + return buildConcatenatedFinalMessage(realchallenge, prover.getFinalMessage(realchallenge), simulator.getFinalMessage()); + } else { + return buildConcatenatedFinalMessage(simulator.getChallenge(), simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); + } + } + } + + abstract public class Verifier implements SigmaProtocol.Verifier { + final SigmaProtocol.Verifier[] verifiers; + + abstract protected Message getFirstMessage(Message concatenated, int verifier); + abstract protected BigInteger getFirstChallenge(Message concatenated); + abstract protected Message getFinalMessage(Message concatenated, int verifier); + + + public Verifier(SigmaProtocol.Verifier... verifiers) { + this.verifiers = verifiers; + } + + public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { + + BigInteger firstChallenge = getFirstChallenge(finalMessage); + BigInteger secondChallenge = challenge.subtract(firstChallenge); + return verifiers[0].verify(getFirstMessage(firstMessage, 0), firstChallenge, getFinalMessage(finalMessage, 0)) & + verifiers[0].verify(getFirstMessage(firstMessage, 1), secondChallenge, getFinalMessage(finalMessage, 1)); + } + } + +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index 92ca859..6c0034d 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -2,13 +2,17 @@ package meerkat.mixer.proofs; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; +import java.math.BigInteger; + /** * implements Mix2ZeroKnowledgeVerifier */ @@ -52,42 +56,76 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { - ECElGamalMixParams.Statement statement = mixParams.createStatement(in1,in2,out1,out2); - return verifyElGamaOrProof(statement.getOrStatement(0), proof.getFirst())&& - verifyElGamaOrProof(statement.getOrStatement(1), proof.getSecond())&& - verifyElGamaOrProof(statement.getOrStatement(2), proof.getThird())&& - verifyElGamaOrProof(statement.getOrStatement(3), proof.getFourth()); + ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); + return verifyFiatShamirOrProof(statement, proof.getFirst(), proof.getSecond()); } /** - * - * @param orStatement - * @param orProof - * @return verify single or proof + * Verify a Schnorr proof of discrete log equality, given the entire transcript of the ZKP. + * @param statement + * @param firstMessage + * @param challenge + * @param finalMessage + * @return */ - private boolean verifyElGamaOrProof(ECElGamalMixParams.OrStatement orStatement, - Mixing.ZeroKnowledgeProof.OrProof orProof) { - ZeroKnowledgeOrProofParser.ZeroKnowledgeOrProofContainer container = parser.parseOrProof(orProof); - return container.g1.equals(orStatement.g1) && - container.h1.equals(orStatement.h1) && - container.g2.equals(orStatement.g2) && - container.h2.equals(orStatement.h2) && - container.g1Tag.equals(orStatement.g1Tag) && - container.h1Tag.equals(orStatement.h1Tag) && - container.g2Tag.equals(orStatement.g2Tag) && - container.h2Tag.equals(orStatement.h2Tag) && - container.c1.add(container.c2).mod(group.orderUpperBound()) - .equals(Prover.hash(container.firstMessage,randomOracle).mod(group.orderUpperBound())) && - group.multiply(container.g1, container.z) - .equals(group.add(container.u, group.multiply(container.h1,container.c1))) && - group.multiply(container.g2, container.z) - .equals(group.add(container.v, group.multiply(container.h2,container.c1))) && - group.multiply(container.g1Tag, container.zTag) - .equals(group.add(container.uTag, group.multiply(container.h1Tag,container.c2))) && - group.multiply(container.g2Tag, container.zTag) - .equals(group.add(container.vTag, group.multiply(container.h2Tag,container.c2))); + boolean verifyInteractiveDlogProof(ECElGamalMixParams.DlogStatement statement, + Mixing.ZeroKnowledgeProof.DlogProof.FirstMessage firstMessage, + BigInteger challenge, + Mixing.ZeroKnowledgeProof.DlogProof.FinalMessage finalMessage) { + GroupElement grEncoded = firstMessage.getGr(); + ECPoint gr = group.decode(grEncoded.toByteArray()); + GroupElement hrEncoded = firstMessage.getHr(); + ECPoint hr = group.decode(hrEncoded.toByteArray()); + + BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); + + boolean gGood = group.add(gr, group.multiply(statement.a,challenge)).equals(group.multiply(statement.g,xcr)); + boolean hGood = group.add(hr, group.multiply(statement.b,challenge)).equals(group.multiply(statement.h,xcr)); + return gGood && hGood; + } + + /** + * Verify a conjuction of two Dlog Proofs, given a complete transcript of the ZKP + * @param statement + * @param firstMessage + * @param challenge + * @param finalMessage + * @return + */ + boolean verifyInteractiveAndProof(ECElGamalMixParams.AndStatement statement, + Mixing.ZeroKnowledgeProof.AndProof.FirstMessage firstMessage, + BigInteger challenge, + Mixing.ZeroKnowledgeProof.AndProof.FinalMessage finalMessage) { + return verifyInteractiveDlogProof(statement.clauses[0], firstMessage.getClause0(), challenge, finalMessage.getClause0()) && + verifyInteractiveDlogProof(statement.clauses[1], firstMessage.getClause1(), challenge, finalMessage.getClause1()); + } + + /** + * Verify a disjunction of two Dlog-equality statement conjuctions, given the entire transcript of the ZKP. + * @param statement + * @param firstMessage + * @param challenge + * @param finalMessage + * @return + */ + boolean verifyInteractiveMix2Proof(ECElGamalMixParams.Mix2Statement statement, + Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage, + BigInteger challenge, + Mixing.ZeroKnowledgeProof.OrProof.FinalMessage finalMessage) { + BigInteger c0 = Util.decodeBigInteger(finalMessage.getC0()); + BigInteger c1 = challenge.subtract(c0).mod(group.orderUpperBound()); + + return verifyInteractiveAndProof(statement.clauses[0], firstMessage.getClause0(), c0, finalMessage.getClause0()) && + verifyInteractiveAndProof(statement.clauses[1], firstMessage.getClause1(), c1, finalMessage.getClause1()); + } + + + boolean verifyFiatShamirOrProof(ECElGamalMixParams.Mix2Statement statement, Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage, + Mixing.ZeroKnowledgeProof.OrProof.FinalMessage finalMessage) { + BigInteger challenge = Prover.hash(firstMessage, randomOracle).mod(group.orderUpperBound()); + return verifyInteractiveMix2Proof(statement, firstMessage, challenge, finalMessage); } } From 723d348443b1f39c1c6fa3c80ea50e0119da4dea Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 11 Jan 2017 22:09:01 +0200 Subject: [PATCH 07/25] Working on mixing code rewrite --- .../mixer/proofs/ECElGamalMixProtocols.java | 231 ++++++++++++++++++ .../meerkat/mixer/proofs/SigmaProtocol.java | 3 +- .../mixer/proofs/SigmaProtocolAnd.java | 36 ++- .../mixer/proofs/SigmaProtocolOr2.java | 22 +- 4 files changed, 282 insertions(+), 10 deletions(-) diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java index 62d7c6d..b657cfb 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java @@ -3,6 +3,8 @@ package meerkat.mixer.proofs; import com.google.protobuf.Message; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.Util; +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; @@ -32,6 +34,7 @@ public class ECElGamalMixProtocols { h = params.h; } + public class DlogStatementSchnorrProver implements SigmaProtocol.Prover { ECElGamalMixParams.DlogStatement statement; ECElGamalMixParams.DlogStatementWitness witness; @@ -62,4 +65,232 @@ public class ECElGamalMixProtocols { return Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound())); } } + + public class DlogStatementSchnorrVerifier implements SigmaProtocol.Verifier { + final ECElGamalMixParams.DlogStatement statement; + + public DlogStatementSchnorrVerifier(ECElGamalMixParams.DlogStatement statement) { + this.statement = statement; + } + + @Override + public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { + assert(firstMessage instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && + finalMessage instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); + return verify((Mixing.Mix2Proof.DlogProof.FirstMessage) firstMessage, challenge, + (Mixing.Mix2Proof.DlogProof.FinalMessage) finalMessage); + } + + public boolean verify(Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage, BigInteger challenge, + Mixing.Mix2Proof.DlogProof.FinalMessage finalMessage) { + GroupElement grEncoded = firstMessage.getGr(); + ECPoint gr = group.decode(grEncoded.toByteArray()); + + GroupElement hrEncoded = firstMessage.getHr(); + ECPoint hr = group.decode(hrEncoded.toByteArray()); + + BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); + + boolean gGood = group.add(gr, group.multiply(statement.a,challenge)).equals(group.multiply(statement.g,xcr)); + boolean hGood = group.add(hr, group.multiply(statement.b,challenge)).equals(group.multiply(statement.h,xcr)); + return gGood && hGood; + } + + } + + public class DlogStatementSchnorrSimulator implements SigmaProtocol.Simulator { + ECElGamalMixParams.DlogStatement statement; + BigInteger response = null; + + public DlogStatementSchnorrSimulator(ECElGamalMixParams.DlogStatement statement) { + this.statement = statement; + } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(BigInteger challenge) { + response = encryptor.generateRandomExponent(rand); + + ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a,challenge)); + ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b,challenge)); + return Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + .setGr(encryptor.encodeElement(u)) + .setHr(encryptor.encodeElement(v)) + .build(); + } + + @Override + public Crypto.BigInteger getFinalMessage() { + return Util.encodeBigInteger(response); + } + } + + /** + * Prover for plaintext equivalence of a pair of ciphertexts. + */ + public class CiphertextPairEquivalenceProver extends SigmaProtocolAnd.Prover { + public CiphertextPairEquivalenceProver(ECElGamalMixParams.AndStatement statement, + ECElGamalMixParams.AndStatementWitness witness) { + super(new DlogStatementSchnorrProver(statement.clauses[0], witness.witnesses[0]), + new DlogStatementSchnorrProver(statement.clauses[1], witness.witnesses[1])); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { + assert (firstMessages.length == 2); + assert (firstMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && + firstMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage); + + return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[0]) + .setClause1((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[1]) + .build(); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FinalMessage buildConcatenatedFinalMessage(Message... finalMessages) { + assert(finalMessages.length == 2); + assert (finalMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage && + finalMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); + + return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[0]) + .setClause1((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[1]) + .build(); + } + } + + public class CiphertextPairEquivalenceVerifier extends SigmaProtocolAnd.Verifier { + public CiphertextPairEquivalenceVerifier(ECElGamalMixParams.AndStatement statement) { + super(new DlogStatementSchnorrVerifier(statement.clauses[0]), new DlogStatementSchnorrVerifier(statement.clauses[1])); + } + + @Override + protected Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(Message concatenated, int verifier) { + assert(concatenated instanceof Mixing.Mix2Proof.AndProof.FirstMessage); + Mixing.Mix2Proof.AndProof.FirstMessage msg = (Mixing.Mix2Proof.AndProof.FirstMessage) concatenated; + if (verifier == 0) + return msg.getClause0(); + else + return msg.getClause1(); + } + + @Override + protected Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage(Message concatenated, int verifier) { + assert(concatenated instanceof Mixing.Mix2Proof.AndProof.FinalMessage); + Mixing.Mix2Proof.AndProof.FinalMessage msg = (Mixing.Mix2Proof.AndProof.FinalMessage) concatenated; + if (verifier == 0) + return msg.getClause0(); + else + return msg.getClause1(); + } + } + + public class CiphertextPairEquivalenceSimulator extends SigmaProtocolAnd.Simulator { + public CiphertextPairEquivalenceSimulator(ECElGamalMixParams.AndStatement statement) { + super(new DlogStatementSchnorrSimulator(statement.clauses[0]), new DlogStatementSchnorrSimulator(statement.clauses[1])); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { + assert (firstMessages.length == 2); + assert (firstMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && + firstMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage); + + return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[0]) + .setClause1((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[1]) + .build(); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FinalMessage buildConcatenatedFinalMessage(Message... finalMessages) { + assert(finalMessages.length == 2); + assert (finalMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage && + finalMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); + + return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[0]) + .setClause1((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[1]) + .build(); + } + } + + public class Mix2Prover extends SigmaProtocolOr2.Prover { + public Mix2Prover(ECElGamalMixParams.Mix2Statement statement, ECElGamalMixParams.Mix2StatementWitness witness) { + super(new CiphertextPairEquivalenceProver(statement.clauses[witness.trueClauseIndex], witness.witness), + new CiphertextPairEquivalenceSimulator(statement.clauses[1 - witness.trueClauseIndex]), + witness.trueClauseIndex); + } + + @Override + protected Mixing.Mix2Proof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { + assert(firstMessages.length == 2); + + assert (firstMessages[0] instanceof Mixing.Mix2Proof.AndProof.FirstMessage && + firstMessages[1] instanceof Mixing.Mix2Proof.AndProof.FirstMessage); + + return Mixing.Mix2Proof.FirstMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.AndProof.FirstMessage)firstMessages[0]) + .setClause1((Mixing.Mix2Proof.AndProof.FirstMessage)firstMessages[1]) + .build(); + } + + @Override + protected Mixing.Mix2Proof.FinalMessage buildConcatenatedFinalMessage(BigInteger firstChallenge, + Message... finalMessages) { + assert(finalMessages.length == 2); + assert (finalMessages[0] instanceof Mixing.Mix2Proof.AndProof.FinalMessage && + finalMessages[1] instanceof Mixing.Mix2Proof.AndProof.FinalMessage); + + return Mixing.Mix2Proof.FinalMessage.newBuilder() + .setClause0((Mixing.Mix2Proof.AndProof.FinalMessage)finalMessages[0]) + .setClause1((Mixing.Mix2Proof.AndProof.FinalMessage)finalMessages[1]) + .setC0(Util.encodeBigInteger(firstChallenge)) + .build(); + } + + @Override + protected BigInteger generateChallenge() { + return encryptor.generateRandomExponent(rand); + } + + @Override + protected BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { + return c1.subtract(c2).mod(group.orderUpperBound()); + } + } + + public class Mix2Verifier extends SigmaProtocolOr2.Verifier { + public Mix2Verifier(ECElGamalMixParams.Mix2Statement statement) { + super(new CiphertextPairEquivalenceVerifier(statement.clauses[0]), new CiphertextPairEquivalenceVerifier(statement.clauses[1])); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FirstMessage getFirstMessage(Message concatenated, int verifier) { + assert(concatenated instanceof Mixing.Mix2Proof.FirstMessage); + Mixing.Mix2Proof.FirstMessage msg = (Mixing.Mix2Proof.FirstMessage) concatenated; + if (verifier == 0) + return msg.getClause0(); + else + return msg.getClause1(); + } + + @Override + protected BigInteger getFirstChallenge(Message concatenated) { + assert(concatenated instanceof Mixing.Mix2Proof.FinalMessage); + Mixing.Mix2Proof.FinalMessage msg = (Mixing.Mix2Proof.FinalMessage) concatenated; + + return Util.decodeBigInteger(msg.getC0()); + } + + @Override + protected Mixing.Mix2Proof.AndProof.FinalMessage getFinalMessage(Message concatenated, int verifier) { + assert(concatenated instanceof Mixing.Mix2Proof.FinalMessage); + Mixing.Mix2Proof.FinalMessage msg = (Mixing.Mix2Proof.FinalMessage) concatenated; + if (verifier == 0) + return msg.getClause0(); + else + return msg.getClause1(); + } + } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java index c0e6c59..b3b09c6 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java @@ -15,8 +15,7 @@ public interface SigmaProtocol { } public interface Simulator { - public Message getFirstMessage(); - public BigInteger getChallenge(); + public Message getFirstMessage(BigInteger challenge); public Message getFinalMessage(); } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java index 4dc2424..4837b75 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java @@ -8,7 +8,7 @@ import java.math.BigInteger; * Generic conjuction of sigma protocols */ public class SigmaProtocolAnd { - abstract public class Prover implements SigmaProtocol.Prover { + static abstract public class Prover implements SigmaProtocol.Prover { final SigmaProtocol.Prover[] provers; abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); @@ -37,7 +37,7 @@ public class SigmaProtocolAnd { } } - abstract public class Verifier implements SigmaProtocol.Verifier { + static abstract public class Verifier implements SigmaProtocol.Verifier { final SigmaProtocol.Verifier[] verifiers; abstract protected Message getFirstMessage(Message concatenated, int verifier); @@ -56,4 +56,36 @@ public class SigmaProtocolAnd { return ok; } } + + static abstract public class Simulator implements SigmaProtocol.Simulator { + final SigmaProtocol.Simulator[] simulators; + + abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); + abstract protected Message buildConcatenatedFinalMessage(Message... finalMessages); + + public Simulator(SigmaProtocol.Simulator... simulators) { + this.simulators = simulators; + } + + @Override + public Message getFirstMessage(BigInteger challenge) { + Message[] firstMessages = new Message[simulators.length]; + + for (int i = 0; i < firstMessages.length; ++i) { + firstMessages[i] = simulators[i].getFirstMessage(challenge); + } + return buildConcatenatedFirstMessage(firstMessages); + } + + @Override + public Message getFinalMessage() { + Message[] finalMessages = new Message[simulators.length]; + + for (int i = 0; i < finalMessages.length; ++i) { + finalMessages[i] = simulators[i].getFinalMessage(); + } + return buildConcatenatedFinalMessage(finalMessages); + } + } + } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java index febb8af..889c51d 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java @@ -8,7 +8,7 @@ import java.math.BigInteger; * Disjunction of 2 Sigma protocol statements */ public class SigmaProtocolOr2 { - abstract public class Prover implements SigmaProtocol.Prover { + static abstract public class Prover implements SigmaProtocol.Prover { final SigmaProtocol.Prover prover; final SigmaProtocol.Simulator simulator; final int proverIdx; @@ -16,6 +16,15 @@ public class SigmaProtocolOr2 { abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); abstract protected Message buildConcatenatedFinalMessage(BigInteger firstChallenge, Message... finalMessages); + BigInteger simChallenge; + + /** + * Generate a random challenge in an appropriate way (e.g., mod group order) + * @return + */ + abstract protected BigInteger generateChallenge(); + + /** * Subtract two challenges in an appropriate way (e.g., mod group order) * @param c1 @@ -39,26 +48,27 @@ public class SigmaProtocolOr2 { @Override public Message getFirstMessage() { + simChallenge = generateChallenge(); if (proverIdx == 0) { - return buildConcatenatedFirstMessage(prover.getFirstMessage(), simulator.getFirstMessage()); + return buildConcatenatedFirstMessage(prover.getFirstMessage(), simulator.getFirstMessage(simChallenge)); } else { - return buildConcatenatedFirstMessage(simulator.getFirstMessage(), prover.getFirstMessage()); + return buildConcatenatedFirstMessage(simulator.getFirstMessage(simChallenge), prover.getFirstMessage()); } } @Override public Message getFinalMessage(BigInteger challenge) { - BigInteger realchallenge = subtractChallenge(challenge, simulator.getChallenge()); + BigInteger realchallenge = subtractChallenge(challenge, simChallenge); if (proverIdx == 0) { return buildConcatenatedFinalMessage(realchallenge, prover.getFinalMessage(realchallenge), simulator.getFinalMessage()); } else { - return buildConcatenatedFinalMessage(simulator.getChallenge(), simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); + return buildConcatenatedFinalMessage(simChallenge, simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); } } } - abstract public class Verifier implements SigmaProtocol.Verifier { + static abstract public class Verifier implements SigmaProtocol.Verifier { final SigmaProtocol.Verifier[] verifiers; abstract protected Message getFirstMessage(Message concatenated, int verifier); From a5cceaa6c03c29064ca724817c98df6af18802a2 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Thu, 12 Jan 2017 11:05:38 +0200 Subject: [PATCH 08/25] Writing tests for new ZKPs --- .../mixnet/Mix2ZeroKnowledgeProver.java | 2 +- .../mixnet/Mix2ZeroKnowledgeVerifier.java | 2 +- .../meerkat/crypto/mixnet/MixerOutput.java | 2 +- .../meerkat/mixer/main/BatchConverter.java | 8 +- .../main/java/meerkat/mixer/mixing/Mixer.java | 8 +- .../meerkat/mixer/mixing/MixerOutput.java | 10 +- .../meerkat/mixer/proofs/Concatenator.java | 21 ++ .../mixer/proofs/ECElGamalMixParams.java | 10 +- .../mixer/proofs/ECElGamalMixProtocols.java | 233 +++--------- .../mixer/proofs/ProtobufConcatenators.java | 107 ++++++ .../java/meerkat/mixer/proofs/Prover.java | 345 +++++++++--------- .../meerkat/mixer/proofs/SigmaFiatShamir.java | 42 +++ .../meerkat/mixer/proofs/SigmaProtocol.java | 28 +- .../mixer/proofs/SigmaProtocolAnd.java | 91 ----- .../mixer/proofs/SigmaProtocolAnd2.java | 87 +++++ .../mixer/proofs/SigmaProtocolOr2.java | 87 +++-- .../java/meerkat/mixer/proofs/Verifier.java | 89 +---- .../meerkat/mixer/proofs/VerifyTable.java | 10 +- .../proofs/ZeroKnowledgeOrProofParser.java | 142 +++---- .../java/meerkat/mixer/CreateTestVector.java | 6 +- .../java/meerkat/mixer/ECParamTestBase.java | 44 +++ ...ledgeProofTest.java => Mix2ProofTest.java} | 20 +- .../test/java/meerkat/mixer/MixingTest.java | 24 +- .../mixer/proofs/AndStatementSigmaTest.java | 52 +++ .../proofs/DlogStatementSchnorrSigmaTest.java | 86 +++++ .../meerkat/mixer/proofs/NIZKContainers.java | 13 + .../mixer/proofs/SigmaProtocolTest.java | 116 ++++++ 27 files changed, 997 insertions(+), 688 deletions(-) create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/Concatenator.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java delete mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java create mode 100644 mixer/src/test/java/meerkat/mixer/ECParamTestBase.java rename mixer/src/test/java/meerkat/mixer/{ZeroKnowledgeProofTest.java => Mix2ProofTest.java} (85%) create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java 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 487483e..70f611f 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java @@ -8,7 +8,7 @@ import meerkat.protobuf.Mixing; * Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts. */ public interface Mix2ZeroKnowledgeProver { - public Mixing.ZeroKnowledgeProof prove(Crypto.RerandomizableEncryptedMessage in1, + public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1, Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, 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 f98f0ac..45bf692 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java @@ -20,5 +20,5 @@ public interface Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, - Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException; + Mixing.Mix2Proof proof) throws InvalidProtocolBufferException; } diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java b/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java index eb71e61..1de10f5 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java +++ b/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java @@ -7,7 +7,7 @@ import meerkat.protobuf.Mixing; * Created by Tzlil on 1/18/2016. */ public interface MixerOutput { - public Mixing.ZeroKnowledgeProof[][] getProofs(); + public Mixing.Mix2Proof[][] getProofs(); public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages(); public int getN(); } diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java index 1ad8204..ea3580d 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java @@ -59,8 +59,8 @@ public class BatchConverter { .setData(Integer2ByteString(n)) .build()); - for (Mixing.ZeroKnowledgeProof[] zkpLayer : mixerOutput.getProofs()) { - for (Mixing.ZeroKnowledgeProof zkp : zkpLayer) { + for (Mixing.Mix2Proof[] zkpLayer : mixerOutput.getProofs()) { + for (Mixing.Mix2Proof zkp : zkpLayer) { result.add(BulletinBoardAPI.BatchChunk.newBuilder() .setData(zkp.toByteString()) .build()); @@ -90,12 +90,12 @@ public class BatchConverter { } int nDiv2 = n >>1; - Mixing.ZeroKnowledgeProof[][] proofs = new Mixing.ZeroKnowledgeProof[layers][nDiv2]; + Mixing.Mix2Proof[][] proofs = new Mixing.Mix2Proof[layers][nDiv2]; for (int layer = 0; layer < layers; layer++) { for (int proofIndex = 0 ; proofIndex < nDiv2 ; proofIndex ++) { - proofs[layer][proofIndex] = Mixing.ZeroKnowledgeProof.parseFrom(batchChunkList.remove(0).getData()); + proofs[layer][proofIndex] = Mixing.Mix2Proof.parseFrom(batchChunkList.remove(0).getData()); } } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java index fbe091c..a304e2f 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java @@ -6,7 +6,7 @@ import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.MixerOutput; import meerkat.protobuf.Crypto.EncryptionRandomness; import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage; -import meerkat.protobuf.Mixing.ZeroKnowledgeProof; +import meerkat.protobuf.Mixing.Mix2Proof; import java.util.List; import java.util.Random; @@ -135,14 +135,14 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { * @return zero knowledge proofs table * @throws InvalidProtocolBufferException */ - private ZeroKnowledgeProof[][] generateZeroKnowledgeProofTable(int n, int layers, MixNetwork mixNetwork + private Mix2Proof[][] generateMix2ProofTable(int n, int layers, MixNetwork mixNetwork , RerandomizableEncryptedMessage[][] encryptionTable , EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { Switch[] switchesLayer; int index1,index2; int switchIndex = 0; int nDiv2 = n >> 1; - ZeroKnowledgeProof[][] proofsTable = new ZeroKnowledgeProof[layers][nDiv2]; + Mix2Proof[][] proofsTable = new Mix2Proof[layers][nDiv2]; RerandomizableEncryptedMessage e1,e2; EncryptionRandomness r1,r2; @@ -185,7 +185,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { EncryptionRandomness[][] randomnesses = generateRandomnessesForRerandomize(n,layers,random); MixNetwork mixNetwork = generateMixNetwork(n,random); rerandomize(layers,mixNetwork,encryptionTable,randomnesses); - ZeroKnowledgeProof[][] proofsTable = generateZeroKnowledgeProofTable(n,layers,mixNetwork,encryptionTable,randomnesses); + Mix2Proof[][] proofsTable = generateMix2ProofTable(n,layers,mixNetwork,encryptionTable,randomnesses); return new meerkat.mixer.mixing.MixerOutput(n,layers,proofsTable, encryptionTable); } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java b/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java index 64636cc..eef60a4 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java @@ -14,7 +14,7 @@ import java.io.IOException; * container for meerkat.mixer.mixing.mix result. */ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ - private final Mixing.ZeroKnowledgeProof[][] proofs; + private final Mixing.Mix2Proof[][] proofs; private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages; private final int n; private final int layers; @@ -27,7 +27,7 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ * at each other level contains the re encrypted votes * @param proofs in each cell (level,switch) contains the match zero knowledge proof */ - public MixerOutput(int n,int layers,Mixing.ZeroKnowledgeProof[][] proofs + public MixerOutput(int n,int layers,Mixing.Mix2Proof[][] proofs , Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) { this.proofs = proofs; this.encryptedMessages = encryptedMessages; @@ -38,7 +38,7 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ @Override - public Mixing.ZeroKnowledgeProof[][] getProofs() { + public Mixing.Mix2Proof[][] getProofs() { return proofs; } @@ -91,8 +91,8 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ * @param proof * @throws IOException */ - private void writeProofToFile(String proofsDir, Mixing.ZeroKnowledgeProof proof) throws IOException { - Mixing.ZeroKnowledgeProof.Location location = proof.getLocation(); + private void writeProofToFile(String proofsDir, Mixing.Mix2Proof proof) throws IOException { + Mixing.Mix2Proof.Location location = proof.getLocation(); int layer = location.getLayer(); int i = location.getI(); int j = location.getJ(); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Concatenator.java b/mixer/src/main/java/meerkat/mixer/proofs/Concatenator.java new file mode 100644 index 0000000..470fced --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/Concatenator.java @@ -0,0 +1,21 @@ +package meerkat.mixer.proofs; + +/** + * Created by talm on 11/01/17. + */ + + +public interface Concatenator { + public interface Pair{ + public OutType concatenate(InType1 msg1, InType2 msg2); + public InType1 getMsg1(OutType msg); + public InType2 getMsg2(OutType msg); + } + + public interface Triplet{ + public OutType concatenate(InType1 msg1, InType2 msg2, InType3 msg3); + public InType1 getMsg1of3(OutType msg); + public InType2 getMsg2of3(OutType msg); + public InType3 getMsg3of3(OutType msg); + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java index 56c02d6..273d435 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java @@ -91,7 +91,7 @@ public class ECElGamalMixParams { public final AndStatement[] clauses = new AndStatement[2]; - private Mix2Statement(ElGamalCiphertext a, ElGamalCiphertext b, + Mix2Statement(ElGamalCiphertext a, ElGamalCiphertext b, ElGamalCiphertext c, ElGamalCiphertext d){ ECPoint a1 = encryptor.decodeElement(a.getC1()); @@ -137,7 +137,7 @@ public class ECElGamalMixParams { public final AndStatementWitness witness; - private Mix2StatementWitness(int trueClauseIndex, AndStatementWitness witness) { + Mix2StatementWitness(int trueClauseIndex, AndStatementWitness witness) { this.trueClauseIndex = trueClauseIndex; assert (trueClauseIndex >= 0 && trueClauseIndex < 2); @@ -152,7 +152,7 @@ public class ECElGamalMixParams { public class AndStatement { public final DlogStatement[] clauses = new DlogStatement[2]; - private AndStatement(DlogStatement clause0, DlogStatement clause1) { + AndStatement(DlogStatement clause0, DlogStatement clause1) { this.clauses[0] = clause0; this.clauses[1] = clause1; } @@ -161,7 +161,7 @@ public class ECElGamalMixParams { public class AndStatementWitness { public final DlogStatementWitness[] witnesses = new DlogStatementWitness[2]; - private AndStatementWitness(DlogStatementWitness witness0, DlogStatementWitness witness1) { + AndStatementWitness(DlogStatementWitness witness0, DlogStatementWitness witness1) { this.witnesses[0] = witness0; this.witnesses[1] = witness1; } @@ -179,7 +179,7 @@ public class ECElGamalMixParams { public final ECPoint b; - private DlogStatement(ECPoint a, ECPoint b) { + DlogStatement(ECPoint a, ECPoint b) { this.g = ECElGamalMixParams.this.g; this.a = a; this.h = ECElGamalMixParams.this.h; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java index b657cfb..bfebbc8 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java @@ -1,18 +1,18 @@ package meerkat.mixer.proofs; -import com.google.protobuf.Message; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.Util; -import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.ConcreteCrypto.GroupElement; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; +import meerkat.protobuf.Mixing.Mix2Proof.AndProof; +import meerkat.protobuf.Mixing.Mix2Proof.DlogProof; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECGroup; import java.math.BigInteger; import java.util.Random; +import static meerkat.protobuf.Mixing.Mix2Proof.DlogProof.*; + /** * Prover, Simulator and Verifier */ @@ -25,6 +25,8 @@ public class ECElGamalMixProtocols { final Random rand; + final ChallengeGenerator challengeGenerator = new ChallengeGenerator(); + public ECElGamalMixProtocols(ECElGamalMixParams params, Random rand) { this.params = params; this.rand = rand; @@ -34,8 +36,16 @@ public class ECElGamalMixProtocols { h = params.h; } + public class ChallengeGenerator implements SigmaProtocolOr2.ChallengeGenerator { + @Override + public BigInteger generateChallenge() { return encryptor.generateRandomExponent(rand); } - public class DlogStatementSchnorrProver implements SigmaProtocol.Prover { + @Override + public BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { return c1.subtract(c2).mod(group.orderUpperBound()); } + } + + + public class DlogStatementSchnorrProver implements SigmaProtocol.Prover { ECElGamalMixParams.DlogStatement statement; ECElGamalMixParams.DlogStatementWitness witness; @@ -47,12 +57,12 @@ public class ECElGamalMixProtocols { } @Override - public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage() { + public FirstMessage getFirstMessage() { r = encryptor.generateRandomExponent(rand); ECPoint gr = group.multiply(statement.g, r); ECPoint hr = group.multiply(statement.h, r); - Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + FirstMessage firstMessage = FirstMessage.newBuilder() .setGr(encryptor.encodeElement(gr)) .setHr(encryptor.encodeElement(hr)) .build(); @@ -61,12 +71,17 @@ public class ECElGamalMixProtocols { } @Override - public Crypto.BigInteger getFinalMessage(BigInteger challenge) { - return Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound())); + public FinalMessage getFinalMessage(BigInteger challenge) { + return FinalMessage.newBuilder() + .setXcr(Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound()))) + .build(); } + + @Override + public void reset() { r = null; } } - public class DlogStatementSchnorrVerifier implements SigmaProtocol.Verifier { + public class DlogStatementSchnorrVerifier implements SigmaProtocol.Verifier { final ECElGamalMixParams.DlogStatement statement; public DlogStatementSchnorrVerifier(ECElGamalMixParams.DlogStatement statement) { @@ -74,20 +89,13 @@ public class ECElGamalMixProtocols { } @Override - public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { - assert(firstMessage instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && - finalMessage instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); - return verify((Mixing.Mix2Proof.DlogProof.FirstMessage) firstMessage, challenge, - (Mixing.Mix2Proof.DlogProof.FinalMessage) finalMessage); - } - - public boolean verify(Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage, BigInteger challenge, - Mixing.Mix2Proof.DlogProof.FinalMessage finalMessage) { + public boolean verify(FirstMessage firstMessage, BigInteger challenge, + FinalMessage finalMessage) { GroupElement grEncoded = firstMessage.getGr(); - ECPoint gr = group.decode(grEncoded.toByteArray()); + ECPoint gr = encryptor.decodeElement(grEncoded); GroupElement hrEncoded = firstMessage.getHr(); - ECPoint hr = group.decode(hrEncoded.toByteArray()); + ECPoint hr = encryptor.decodeElement(hrEncoded); BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); @@ -98,7 +106,7 @@ public class ECElGamalMixProtocols { } - public class DlogStatementSchnorrSimulator implements SigmaProtocol.Simulator { + public class DlogStatementSchnorrSimulator implements SigmaProtocol.Simulator { ECElGamalMixParams.DlogStatement statement; BigInteger response = null; @@ -107,190 +115,69 @@ public class ECElGamalMixProtocols { } @Override - public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(BigInteger challenge) { + public FirstMessage getFirstMessage(BigInteger challenge) { response = encryptor.generateRandomExponent(rand); ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a,challenge)); ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b,challenge)); - return Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + return FirstMessage.newBuilder() .setGr(encryptor.encodeElement(u)) .setHr(encryptor.encodeElement(v)) .build(); } @Override - public Crypto.BigInteger getFinalMessage() { - return Util.encodeBigInteger(response); + public FinalMessage getFinalMessage() { + + return FinalMessage.newBuilder() + .setXcr(Util.encodeBigInteger(response)) + .build(); } + + @Override + public void reset() { response = null; } } /** * Prover for plaintext equivalence of a pair of ciphertexts. */ - public class CiphertextPairEquivalenceProver extends SigmaProtocolAnd.Prover { - public CiphertextPairEquivalenceProver(ECElGamalMixParams.AndStatement statement, - ECElGamalMixParams.AndStatementWitness witness) { - super(new DlogStatementSchnorrProver(statement.clauses[0], witness.witnesses[0]), + public class AndStatementProver + extends SigmaProtocolAnd2.Prover { + public AndStatementProver(ECElGamalMixParams.AndStatement statement, + ECElGamalMixParams.AndStatementWitness witness) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new DlogStatementSchnorrProver(statement.clauses[0], witness.witnesses[0]), new DlogStatementSchnorrProver(statement.clauses[1], witness.witnesses[1])); } + } - @Override - protected Mixing.Mix2Proof.AndProof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { - assert (firstMessages.length == 2); - assert (firstMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && - firstMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage); - - return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[0]) - .setClause1((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[1]) - .build(); - } - - @Override - protected Mixing.Mix2Proof.AndProof.FinalMessage buildConcatenatedFinalMessage(Message... finalMessages) { - assert(finalMessages.length == 2); - assert (finalMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage && - finalMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); - - return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[0]) - .setClause1((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[1]) - .build(); + public class AndStatementVerifier + extends SigmaProtocolAnd2.Verifier { + public AndStatementVerifier(ECElGamalMixParams.AndStatement statement) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + new DlogStatementSchnorrVerifier(statement.clauses[0]), new DlogStatementSchnorrVerifier(statement.clauses[1])); } } - public class CiphertextPairEquivalenceVerifier extends SigmaProtocolAnd.Verifier { - public CiphertextPairEquivalenceVerifier(ECElGamalMixParams.AndStatement statement) { - super(new DlogStatementSchnorrVerifier(statement.clauses[0]), new DlogStatementSchnorrVerifier(statement.clauses[1])); - } - - @Override - protected Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(Message concatenated, int verifier) { - assert(concatenated instanceof Mixing.Mix2Proof.AndProof.FirstMessage); - Mixing.Mix2Proof.AndProof.FirstMessage msg = (Mixing.Mix2Proof.AndProof.FirstMessage) concatenated; - if (verifier == 0) - return msg.getClause0(); - else - return msg.getClause1(); - } - - @Override - protected Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage(Message concatenated, int verifier) { - assert(concatenated instanceof Mixing.Mix2Proof.AndProof.FinalMessage); - Mixing.Mix2Proof.AndProof.FinalMessage msg = (Mixing.Mix2Proof.AndProof.FinalMessage) concatenated; - if (verifier == 0) - return msg.getClause0(); - else - return msg.getClause1(); - } - } - - public class CiphertextPairEquivalenceSimulator extends SigmaProtocolAnd.Simulator { - public CiphertextPairEquivalenceSimulator(ECElGamalMixParams.AndStatement statement) { - super(new DlogStatementSchnorrSimulator(statement.clauses[0]), new DlogStatementSchnorrSimulator(statement.clauses[1])); - } - - @Override - protected Mixing.Mix2Proof.AndProof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { - assert (firstMessages.length == 2); - assert (firstMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage && - firstMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FirstMessage); - - return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[0]) - .setClause1((Mixing.Mix2Proof.DlogProof.FirstMessage)firstMessages[1]) - .build(); - } - - @Override - protected Mixing.Mix2Proof.AndProof.FinalMessage buildConcatenatedFinalMessage(Message... finalMessages) { - assert(finalMessages.length == 2); - assert (finalMessages[0] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage && - finalMessages[1] instanceof Mixing.Mix2Proof.DlogProof.FinalMessage); - - return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[0]) - .setClause1((Mixing.Mix2Proof.DlogProof.FinalMessage)finalMessages[1]) - .build(); + public class AndStatementSimulator extends SigmaProtocolAnd2.Simulator { + public AndStatementSimulator(ECElGamalMixParams.AndStatement statement) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + new DlogStatementSchnorrSimulator(statement.clauses[0]), new DlogStatementSchnorrSimulator(statement.clauses[1])); } } public class Mix2Prover extends SigmaProtocolOr2.Prover { public Mix2Prover(ECElGamalMixParams.Mix2Statement statement, ECElGamalMixParams.Mix2StatementWitness witness) { - super(new CiphertextPairEquivalenceProver(statement.clauses[witness.trueClauseIndex], witness.witness), - new CiphertextPairEquivalenceSimulator(statement.clauses[1 - witness.trueClauseIndex]), + super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, + new AndStatementProver(statement.clauses[witness.trueClauseIndex], witness.witness), + new AndStatementSimulator(statement.clauses[1 - witness.trueClauseIndex]), witness.trueClauseIndex); } - - @Override - protected Mixing.Mix2Proof.FirstMessage buildConcatenatedFirstMessage(Message... firstMessages) { - assert(firstMessages.length == 2); - - assert (firstMessages[0] instanceof Mixing.Mix2Proof.AndProof.FirstMessage && - firstMessages[1] instanceof Mixing.Mix2Proof.AndProof.FirstMessage); - - return Mixing.Mix2Proof.FirstMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.AndProof.FirstMessage)firstMessages[0]) - .setClause1((Mixing.Mix2Proof.AndProof.FirstMessage)firstMessages[1]) - .build(); - } - - @Override - protected Mixing.Mix2Proof.FinalMessage buildConcatenatedFinalMessage(BigInteger firstChallenge, - Message... finalMessages) { - assert(finalMessages.length == 2); - assert (finalMessages[0] instanceof Mixing.Mix2Proof.AndProof.FinalMessage && - finalMessages[1] instanceof Mixing.Mix2Proof.AndProof.FinalMessage); - - return Mixing.Mix2Proof.FinalMessage.newBuilder() - .setClause0((Mixing.Mix2Proof.AndProof.FinalMessage)finalMessages[0]) - .setClause1((Mixing.Mix2Proof.AndProof.FinalMessage)finalMessages[1]) - .setC0(Util.encodeBigInteger(firstChallenge)) - .build(); - } - - @Override - protected BigInteger generateChallenge() { - return encryptor.generateRandomExponent(rand); - } - - @Override - protected BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { - return c1.subtract(c2).mod(group.orderUpperBound()); - } } public class Mix2Verifier extends SigmaProtocolOr2.Verifier { public Mix2Verifier(ECElGamalMixParams.Mix2Statement statement) { - super(new CiphertextPairEquivalenceVerifier(statement.clauses[0]), new CiphertextPairEquivalenceVerifier(statement.clauses[1])); - } - - @Override - protected Mixing.Mix2Proof.AndProof.FirstMessage getFirstMessage(Message concatenated, int verifier) { - assert(concatenated instanceof Mixing.Mix2Proof.FirstMessage); - Mixing.Mix2Proof.FirstMessage msg = (Mixing.Mix2Proof.FirstMessage) concatenated; - if (verifier == 0) - return msg.getClause0(); - else - return msg.getClause1(); - } - - @Override - protected BigInteger getFirstChallenge(Message concatenated) { - assert(concatenated instanceof Mixing.Mix2Proof.FinalMessage); - Mixing.Mix2Proof.FinalMessage msg = (Mixing.Mix2Proof.FinalMessage) concatenated; - - return Util.decodeBigInteger(msg.getC0()); - } - - @Override - protected Mixing.Mix2Proof.AndProof.FinalMessage getFinalMessage(Message concatenated, int verifier) { - assert(concatenated instanceof Mixing.Mix2Proof.FinalMessage); - Mixing.Mix2Proof.FinalMessage msg = (Mixing.Mix2Proof.FinalMessage) concatenated; - if (verifier == 0) - return msg.getClause0(); - else - return msg.getClause1(); + super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, + new AndStatementVerifier(statement.clauses[0]), new AndStatementVerifier(statement.clauses[1])); } } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java b/mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java new file mode 100644 index 0000000..98c74ef --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java @@ -0,0 +1,107 @@ +package meerkat.mixer.proofs; + +import meerkat.crypto.concrete.Util; +import meerkat.protobuf.Mixing; + +import java.math.BigInteger; + +/** + * Created by talm on 12/01/17. + */ +public class ProtobufConcatenators { + public final static ConcatAnd1 concatAnd1 = new ConcatAnd1(); + public final static ConcatAnd2 concatAnd2 = new ConcatAnd2(); + public final static ConcatMix1 concatMix1 = new ConcatMix1(); + public final static ConcatMix2 concatMix2 = new ConcatMix2(); + public final static ConcatNIZK concatNIZK = new ConcatNIZK(); + + public static class ConcatAnd1 implements Concatenator.Pair { + @Override + public Mixing.Mix2Proof.AndProof.FirstMessage concatenate(Mixing.Mix2Proof.DlogProof.FirstMessage msg1, Mixing.Mix2Proof.DlogProof.FirstMessage msg2) { + return Mixing.Mix2Proof.AndProof.FirstMessage.newBuilder() + .setClause0(msg1) + .setClause1(msg2) + .build(); + } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getMsg1(Mixing.Mix2Proof.AndProof.FirstMessage msg) { return msg.getClause0(); } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getMsg2(Mixing.Mix2Proof.AndProof.FirstMessage msg) { return msg.getClause1(); } + } + + public static class ConcatAnd2 implements Concatenator.Pair { + @Override + public Mixing.Mix2Proof.AndProof.FinalMessage concatenate(Mixing.Mix2Proof.DlogProof.FinalMessage msg1, Mixing.Mix2Proof.DlogProof.FinalMessage msg2) { + return Mixing.Mix2Proof.AndProof.FinalMessage.newBuilder() + .setClause0(msg1) + .setClause1(msg2) + .build(); + } + + @Override + public Mixing.Mix2Proof.DlogProof.FinalMessage getMsg1(Mixing.Mix2Proof.AndProof.FinalMessage msg) { return msg.getClause0(); } + + @Override + public Mixing.Mix2Proof.DlogProof.FinalMessage getMsg2(Mixing.Mix2Proof.AndProof.FinalMessage msg) { return msg.getClause1(); } + } + + public static class ConcatMix1 implements Concatenator.Pair { + @Override + public Mixing.Mix2Proof.FirstMessage concatenate(Mixing.Mix2Proof.AndProof.FirstMessage msg1, Mixing.Mix2Proof.AndProof.FirstMessage msg2) { + return Mixing.Mix2Proof.FirstMessage.newBuilder() + .setClause0(msg1) + .setClause1(msg2) + .build(); + } + + @Override + public Mixing.Mix2Proof.AndProof.FirstMessage getMsg1(Mixing.Mix2Proof.FirstMessage msg) { return msg.getClause0(); } + + @Override + public Mixing.Mix2Proof.AndProof.FirstMessage getMsg2(Mixing.Mix2Proof.FirstMessage msg) { return msg.getClause1(); } + } + + public static class ConcatMix2 implements Concatenator.Triplet { + @Override + public Mixing.Mix2Proof.FinalMessage concatenate(BigInteger msg1, Mixing.Mix2Proof.AndProof.FinalMessage msg2, Mixing.Mix2Proof.AndProof.FinalMessage msg3) { + return Mixing.Mix2Proof.FinalMessage.newBuilder() + .setC0(Util.encodeBigInteger(msg1)) + .setClause0(msg2) + .setClause1(msg3) + .build(); + } + + @Override + public BigInteger getMsg1of3(Mixing.Mix2Proof.FinalMessage msg) { return Util.decodeBigInteger(msg.getC0()); } + + @Override + public Mixing.Mix2Proof.AndProof.FinalMessage getMsg2of3(Mixing.Mix2Proof.FinalMessage msg) { return msg.getClause0(); } + + @Override + public Mixing.Mix2Proof.AndProof.FinalMessage getMsg3of3(Mixing.Mix2Proof.FinalMessage msg) { return msg.getClause1(); } + } + + + public static class ConcatNIZK implements Concatenator.Pair { + + @Override + public Mixing.Mix2Proof concatenate(Mixing.Mix2Proof.FirstMessage msg1, Mixing.Mix2Proof.FinalMessage msg2) { + return Mixing.Mix2Proof.newBuilder() + .setFirstMessage(msg1) + .setFinalMessage(msg2) + .build(); + } + + @Override + public Mixing.Mix2Proof.FirstMessage getMsg1(Mixing.Mix2Proof msg) { + return msg.getFirstMessage(); + } + + @Override + public Mixing.Mix2Proof.FinalMessage getMsg2(Mixing.Mix2Proof msg) { + return msg.getFinalMessage(); + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index 91a3c24..9a8a2f3 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -19,7 +19,7 @@ import java.util.Random; * this implementation assumes that each RerandomizableEncryptedMessage is ElGamalCiphertext */ public class Prover implements Mix2ZeroKnowledgeProver { - +// private final ECGroup group; private final RandomOracle randomOracle; private final Random rand; @@ -27,6 +27,8 @@ public class Prover implements Mix2ZeroKnowledgeProver { private final ECPoint g,h; private final BigInteger groupOrderUpperBound; private final ECElGamalMixParams mixParams; + final ECElGamalMixProtocols mixProtocols; + final SigmaFiatShamir mix2NIZK; /** * @param rand @@ -43,6 +45,8 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.h = this.encryptor.getElGamalPK().getPK(); this.mixParams = new ECElGamalMixParams(encryptor); this.groupOrderUpperBound = group.orderUpperBound(); + this.mixProtocols = new ECElGamalMixProtocols(mixParams, rand); // We don't need randomness for the verifier + this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); } /** @@ -66,182 +70,179 @@ public class Prover implements Mix2ZeroKnowledgeProver { boolean switched,int i,int j, int layer, Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { - Mixing.Mix2Proof first,second,third,fourth; - ECElGamalMixParams.MixStatementWitness statement = mixParams.createProverStatement(a,b,c,d,r1,r2,switched); - first = createOrProof(statement.getDlogStatement(0)); - second = createOrProof(statement.getDlogStatement(1)); - third = createOrProof(statement.getDlogStatement(2)); - fourth = createOrProof(statement.getDlogStatement(3)); + ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(a,b,c,d); + ECElGamalMixParams.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); - Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() - .setI(i) - .setJ(j) - .setLayer(layer) - .build(); + ECElGamalMixProtocols.Mix2Prover prover = mixProtocols.new Mix2Prover(statement, witness); - Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder() - .setFirst(first) - .setSecond(second) - .setThird(third) - .setFourth(fourth) - .setLocation(location) - .build(); - return result; + return mix2NIZK.generateNizk(prover); + +// Mixing.Mix2Proof first,second,third,fourth; +// +// ECElGamalMixParams.MixStatementWitness statement = mixParams.createProverStatement(a,b,c,d,r1,r2,switched); +// +// first = createOrProof(statement.getDlogStatement(0)); +// second = createOrProof(statement.getDlogStatement(1)); +// third = createOrProof(statement.getDlogStatement(2)); +// fourth = createOrProof(statement.getDlogStatement(3)); +// +// Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() +// .setI(i) +// .setJ(j) +// .setLayer(layer) +// .build(); +// +// Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder() +// .setFirst(first) +// .setSecond(second) +// .setThird(third) +// .setFourth(fourth) +// .setLocation(location) +// .build(); +// return result; } +// +// +// Mixing.Mix2Proof.DlogProof.FirstMessage createDlogProof(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { +// +// BigInteger r = encryptor.generateRandomExponent(rand); +// ECPoint gr = group.multiply(statement.g, r); +// ECPoint hr = group.multiply(statement.h, r); +// +// Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() +// .setGr(group.encode(gr)) +// .setHr(group.encode(hr)) +// .build(); +// +// BigInteger challenge = Prover.hash() +// } +// +// +// +// +// /** +// * Generate a ZK proof that there exists x s.t (g ^ x == a and h ^ x == b) or (g' ^ x == a and h' ^ x == b). +// * +// * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g}(a)==log_{g}(b)): +// *
    +// *
  1. Prover chooses a random r, and sends g^r, h^r
  2. +// *
  3. Verifier chooses a random c and sends c
  4. +// *
  5. Prover computes
  6. +// *
+// * +// * +// * @param orStatement +// * @return ZKP OrProof: +// * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs +// */ +// private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) { +// +// ECPoint g1 = orStatement.g1; +// ECPoint h1 = orStatement.h1; +// ECPoint g2 = orStatement.g2; +// ECPoint h2 = orStatement.h2; +// +// ECPoint g1Tag = orStatement.g1Tag; +// ECPoint h1Tag = orStatement.h1Tag; +// ECPoint g2Tag = orStatement.g2Tag; +// ECPoint h2Tag = orStatement.h2Tag; +// +// // Randomness for the ZK proof +// BigInteger r = encryptor.generateRandomExponent(rand); +// +// +// BigInteger c1,c2,z,zTag; +// ECPoint u,v,uTag,vTag; +// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; +// +// +// switch (orStatement.trueClauseIndex) { +// case left: +// c2 = encryptor.generateRandomExponent(rand); +// zTag = encryptor.generateRandomExponent(rand); +// //step 1 +// 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 +// firstMessage = +// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() +// .setG1(orStatement.g1Encoded) +// .setH1(orStatement.h1Encoded) +// .setG2(orStatement.g2Encoded) +// .setH2(orStatement.h2Encoded) +// .setG1Tag(orStatement.g1TagEncoded) +// .setH1Tag(orStatement.h1TagEncoded) +// .setG2Tag(orStatement.g2TagEncoded) +// .setH2Tag(orStatement.h2TagEncoded) +// .setU(encryptor.encodeElement(u)) +// .setV(encryptor.encodeElement(v)) +// .setUTag(encryptor.encodeElement(uTag)) +// .setVTag(encryptor.encodeElement(vTag)) +// .build(); +// c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); +// //step 3 +// //z = (r + c1 * x) % group size; +// z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); +// break; +// case right: +// c1 = encryptor.generateRandomExponent(rand); +// z = encryptor.generateRandomExponent(rand); +// //step 1 +// 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 +// firstMessage = +// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() +// .setG1(orStatement.g1Encoded) +// .setH1(orStatement.h1Encoded) +// .setG2(orStatement.g2Encoded) +// .setH2(orStatement.h2Encoded) +// .setG1Tag(orStatement.g1TagEncoded) +// .setH1Tag(orStatement.h1TagEncoded) +// .setG2Tag(orStatement.g2TagEncoded) +// .setH2Tag(orStatement.h2TagEncoded) +// .setU(encryptor.encodeElement(u)) +// .setV(encryptor.encodeElement(v)) +// .setUTag(encryptor.encodeElement(uTag)) +// .setVTag(encryptor.encodeElement(vTag)) +// .build(); +// c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); +// //step 3 +// //zTag = (r + c2 * x) % group size; +// zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); +// break; +// default: +// return null; +// } +// +// +// return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() +// .setG1(firstMessage.getG1()) +// .setH1(firstMessage.getH1()) +// .setG2(firstMessage.getG2()) +// .setH2(firstMessage.getH2()) +// .setG1Tag(firstMessage.getG1()) +// .setH1Tag(firstMessage.getH1Tag()) +// .setG2Tag(firstMessage.getG2Tag()) +// .setH2Tag(firstMessage.getH2Tag()) +// .setU(firstMessage.getU()) +// .setV(firstMessage.getV()) +// .setUTag(firstMessage.getUTag()) +// .setVTag(firstMessage.getVTag()) +// .setC1(Util.encodeBigInteger(c1)) +// .setC2(Util.encodeBigInteger(c2)) +// .setZ(Util.encodeBigInteger(z)) +// .setZTag(Util.encodeBigInteger(zTag)) +// .build(); +// } - - /** - * Fiat–Shamir heuristic - * @param input - protobuf contains all parameters from the first step of the current proof - * @param randomOracle - * @return randomOracle.hash(input) - */ - public static BigInteger hash(Mixing.Mix2Proof.FirstMessage input, RandomOracle randomOracle) { - byte[] arr = input.toByteArray(); - return new BigInteger(1,randomOracle.hash(arr,arr.length)); - } - - - - Mixing.Mix2Proof.DlogProof.FirstMessage createDlogProof(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { - - BigInteger r = encryptor.generateRandomExponent(rand); - ECPoint gr = group.multiply(statement.g, r); - ECPoint hr = group.multiply(statement.h, r); - - Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() - .setGr(group.encode(gr)) - .setHr(group.encode(hr)) - .build(); - - BigInteger challenge = Prover.hash() - } - - - - - /** - * Generate a ZK proof that there exists x s.t (g ^ x == a and h ^ x == b) or (g' ^ x == a and h' ^ x == b). - * - * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g}(a)==log_{g}(b)): - *
    - *
  1. Prover chooses a random r, and sends g^r, h^r
  2. - *
  3. Verifier chooses a random c and sends c
  4. - *
  5. Prover computes
  6. - *
- * - * - * @param orStatement - * @return ZKP OrProof: - * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs - */ - private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) { - - ECPoint g1 = orStatement.g1; - ECPoint h1 = orStatement.h1; - ECPoint g2 = orStatement.g2; - ECPoint h2 = orStatement.h2; - - ECPoint g1Tag = orStatement.g1Tag; - ECPoint h1Tag = orStatement.h1Tag; - ECPoint g2Tag = orStatement.g2Tag; - ECPoint h2Tag = orStatement.h2Tag; - - // Randomness for the ZK proof - BigInteger r = encryptor.generateRandomExponent(rand); - - - BigInteger c1,c2,z,zTag; - ECPoint u,v,uTag,vTag; - Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; - - - switch (orStatement.trueClauseIndex) { - case left: - c2 = encryptor.generateRandomExponent(rand); - zTag = encryptor.generateRandomExponent(rand); - //step 1 - 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 - firstMessage = - Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() - .setG1(orStatement.g1Encoded) - .setH1(orStatement.h1Encoded) - .setG2(orStatement.g2Encoded) - .setH2(orStatement.h2Encoded) - .setG1Tag(orStatement.g1TagEncoded) - .setH1Tag(orStatement.h1TagEncoded) - .setG2Tag(orStatement.g2TagEncoded) - .setH2Tag(orStatement.h2TagEncoded) - .setU(encryptor.encodeElement(u)) - .setV(encryptor.encodeElement(v)) - .setUTag(encryptor.encodeElement(uTag)) - .setVTag(encryptor.encodeElement(vTag)) - .build(); - c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); - //step 3 - //z = (r + c1 * x) % group size; - z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); - break; - case right: - c1 = encryptor.generateRandomExponent(rand); - z = encryptor.generateRandomExponent(rand); - //step 1 - 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 - firstMessage = - Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() - .setG1(orStatement.g1Encoded) - .setH1(orStatement.h1Encoded) - .setG2(orStatement.g2Encoded) - .setH2(orStatement.h2Encoded) - .setG1Tag(orStatement.g1TagEncoded) - .setH1Tag(orStatement.h1TagEncoded) - .setG2Tag(orStatement.g2TagEncoded) - .setH2Tag(orStatement.h2TagEncoded) - .setU(encryptor.encodeElement(u)) - .setV(encryptor.encodeElement(v)) - .setUTag(encryptor.encodeElement(uTag)) - .setVTag(encryptor.encodeElement(vTag)) - .build(); - c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); - //step 3 - //zTag = (r + c2 * x) % group size; - zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); - break; - default: - return null; - } - - - return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() - .setG1(firstMessage.getG1()) - .setH1(firstMessage.getH1()) - .setG2(firstMessage.getG2()) - .setH2(firstMessage.getH2()) - .setG1Tag(firstMessage.getG1()) - .setH1Tag(firstMessage.getH1Tag()) - .setG2Tag(firstMessage.getG2Tag()) - .setH2Tag(firstMessage.getH2Tag()) - .setU(firstMessage.getU()) - .setV(firstMessage.getV()) - .setUTag(firstMessage.getUTag()) - .setVTag(firstMessage.getVTag()) - .setC1(Util.encodeBigInteger(c1)) - .setC2(Util.encodeBigInteger(c2)) - .setZ(Util.encodeBigInteger(z)) - .setZTag(Util.encodeBigInteger(zTag)) - .build(); - } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java new file mode 100644 index 0000000..409ea02 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java @@ -0,0 +1,42 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; +import org.factcenter.qilin.primitives.RandomOracle; + +import java.math.BigInteger; + +/** + * Transform a Sigma protocol into a NIZK using Fiat-Shamir + */ +public class SigmaFiatShamir { + final RandomOracle randomOracle; + final Concatenator.Pair concat; + + public SigmaFiatShamir(Concatenator.Pair concat, RandomOracle randomOracle) { + this.concat = concat; + this.randomOracle = randomOracle; + } + + /** + * Fiat–Shamir heuristic + * @param input - protobuf contains all parameters from the first step of the current proof + * @return randomOracle.hash(input) + */ + public static BigInteger hash(Message input, RandomOracle randomOracle) { + byte[] arr = input.toByteArray(); + return new BigInteger(1,randomOracle.hash(arr,arr.length)); + } + + public NIZKMsgType generateNizk(SigmaProtocol.Prover prover) { + FirstMsgType firstMessage = prover.getFirstMessage(); + BigInteger challenge = hash(firstMessage, randomOracle); + FinalMessageType finalMessage = prover.getFinalMessage(challenge); + return concat.concatenate(firstMessage, finalMessage); + } + + public boolean verifyNizk(NIZKMsgType NIZK, SigmaProtocol.Verifier verifier) { + FirstMsgType firstMessage = concat.getMsg1(NIZK); + BigInteger challenge = hash(firstMessage, randomOracle); + return verifier.verify(firstMessage, challenge, concat.getMsg2(NIZK)); + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java index b3b09c6..6dbac42 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java @@ -9,17 +9,29 @@ import java.math.BigInteger; * The challenge is always a {@link java.math.BigInteger}. */ public interface SigmaProtocol { - public interface Prover { - public Message getFirstMessage(); - public Message getFinalMessage(BigInteger challenge); + public interface Prover { + public FirstMsgType getFirstMessage(); + public FinalMessageType getFinalMessage(BigInteger challenge); + + /** + * Reset the prover (so the next calls to {@link #getFirstMessage()} will + * start a new proof. + */ + public void reset(); } - public interface Simulator { - public Message getFirstMessage(BigInteger challenge); - public Message getFinalMessage(); + public interface Simulator { + public FirstMsgType getFirstMessage(BigInteger challenge); + public FinalMessageType getFinalMessage(); + + /** + * Reset the prover (so the next calls to {@link #getFirstMessage(BigInteger)} will + * start a new proof. + */ + public void reset(); } - public interface Verifier { - public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage); + public interface Verifier { + public boolean verify(FirstMsgType firstMessage, BigInteger challenge, FinalMessageType finalMessage); } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java deleted file mode 100644 index 4837b75..0000000 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd.java +++ /dev/null @@ -1,91 +0,0 @@ -package meerkat.mixer.proofs; - -import com.google.protobuf.Message; - -import java.math.BigInteger; - -/** - * Generic conjuction of sigma protocols - */ -public class SigmaProtocolAnd { - static abstract public class Prover implements SigmaProtocol.Prover { - final SigmaProtocol.Prover[] provers; - - abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); - abstract protected Message buildConcatenatedFinalMessage(Message... finalMessages); - - public Prover(SigmaProtocol.Prover... provers) { - this.provers = provers; - } - - @Override - public Message getFirstMessage() { - Message[] firstMessages = new Message[provers.length]; - for (int i = 0; i < firstMessages.length; ++i) { - firstMessages[i] = provers[i].getFirstMessage(); - } - return buildConcatenatedFirstMessage(firstMessages); - } - - @Override - public Message getFinalMessage(BigInteger challenge) { - Message[] finalMessages = new Message[provers.length]; - for (int i = 0; i < finalMessages.length; ++i) { - finalMessages[i] = provers[i].getFinalMessage(challenge); - } - return buildConcatenatedFinalMessage(finalMessages); - } - } - - static abstract public class Verifier implements SigmaProtocol.Verifier { - final SigmaProtocol.Verifier[] verifiers; - - abstract protected Message getFirstMessage(Message concatenated, int verifier); - abstract protected Message getFinalMessage(Message concatenated, int verifier); - - public Verifier(SigmaProtocol.Verifier... verifiers) { - this.verifiers = verifiers; - } - - public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { - boolean ok = true; - - for (int i = 0; i < verifiers.length; ++i) { - ok &= verifiers[i].verify(getFirstMessage(firstMessage, i), challenge, getFinalMessage(finalMessage, i)); - } - return ok; - } - } - - static abstract public class Simulator implements SigmaProtocol.Simulator { - final SigmaProtocol.Simulator[] simulators; - - abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); - abstract protected Message buildConcatenatedFinalMessage(Message... finalMessages); - - public Simulator(SigmaProtocol.Simulator... simulators) { - this.simulators = simulators; - } - - @Override - public Message getFirstMessage(BigInteger challenge) { - Message[] firstMessages = new Message[simulators.length]; - - for (int i = 0; i < firstMessages.length; ++i) { - firstMessages[i] = simulators[i].getFirstMessage(challenge); - } - return buildConcatenatedFirstMessage(firstMessages); - } - - @Override - public Message getFinalMessage() { - Message[] finalMessages = new Message[simulators.length]; - - for (int i = 0; i < finalMessages.length; ++i) { - finalMessages[i] = simulators[i].getFinalMessage(); - } - return buildConcatenatedFinalMessage(finalMessages); - } - } - -} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java new file mode 100644 index 0000000..d9e473b --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java @@ -0,0 +1,87 @@ +package meerkat.mixer.proofs; + +import java.math.BigInteger; + +/** + * Generic conjuction of sigma protocols + */ +public class SigmaProtocolAnd2 { + static public class Prover + implements SigmaProtocol.Prover { + final SigmaProtocol.Prover[] provers; + + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Pair finalMessageConcatenator; + + public Prover(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, + SigmaProtocol.Prover... provers) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.provers = provers; + } + + @Override + public FirstMessageOut getFirstMessage() { + return firstMessageConcatenator.concatenate(provers[0].getFirstMessage(), provers[1].getFirstMessage()); + } + + @Override + public FinalMessageOut getFinalMessage(BigInteger challenge) { + return finalMessageConcatenator.concatenate(provers[0].getFinalMessage(challenge), provers[1].getFinalMessage(challenge)); + } + + + @Override + public void reset() { provers[0].reset(); provers[1].reset(); } + } + + static public class Verifier + implements SigmaProtocol.Verifier { + final SigmaProtocol.Verifier[] verifiers; + + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Pair finalMessageConcatenator; + + public Verifier(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, + SigmaProtocol.Verifier... verifiers) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.verifiers = verifiers; + } + + @Override + public boolean verify(FirstMessageOut firstMessage, BigInteger challenge, FinalMessageOut finalMessage) { + return verifiers[0].verify(firstMessageConcatenator.getMsg1(firstMessage), challenge, finalMessageConcatenator.getMsg1(finalMessage)) && + verifiers[1].verify(firstMessageConcatenator.getMsg2(firstMessage), challenge, finalMessageConcatenator.getMsg2(finalMessage)); + } + } + + static public class Simulator + implements SigmaProtocol.Simulator { + final SigmaProtocol.Simulator[] simulators; + + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Pair finalMessageConcatenator; + + public Simulator(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, SigmaProtocol.Simulator... simulators) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.simulators = simulators; + } + + @Override + public FirstMessageOut getFirstMessage(BigInteger challenge) { + return firstMessageConcatenator.concatenate(simulators[0].getFirstMessage(challenge), simulators[1].getFirstMessage(challenge)); + } + + @Override + public FinalMessageOut getFinalMessage() { + return finalMessageConcatenator.concatenate(simulators[0].getFinalMessage(), simulators[1].getFinalMessage()); + } + + @Override + public void reset() { simulators[0].reset(); simulators[1].reset(); } + } + +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java index 889c51d..cf2c4ff 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java @@ -1,29 +1,18 @@ package meerkat.mixer.proofs; -import com.google.protobuf.Message; - import java.math.BigInteger; /** * Disjunction of 2 Sigma protocol statements */ public class SigmaProtocolOr2 { - static abstract public class Prover implements SigmaProtocol.Prover { - final SigmaProtocol.Prover prover; - final SigmaProtocol.Simulator simulator; - final int proverIdx; - - abstract protected Message buildConcatenatedFirstMessage(Message... firstMessages); - abstract protected Message buildConcatenatedFinalMessage(BigInteger firstChallenge, Message... finalMessages); - - BigInteger simChallenge; + public interface ChallengeGenerator { /** * Generate a random challenge in an appropriate way (e.g., mod group order) * @return */ - abstract protected BigInteger generateChallenge(); - + public BigInteger generateChallenge(); /** * Subtract two challenges in an appropriate way (e.g., mod group order) @@ -31,7 +20,20 @@ public class SigmaProtocolOr2 { * @param c2 * @return */ - abstract protected BigInteger subtractChallenge(BigInteger c1, BigInteger c2); + public BigInteger subtractChallenge(BigInteger c1, BigInteger c2); + } + + static public class Prover + implements SigmaProtocol.Prover { + final SigmaProtocol.Prover prover; + final SigmaProtocol.Simulator simulator; + final int proverIdx; + + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Triplet finalMessageConcatenator; + final ChallengeGenerator challengeGenerator; + + BigInteger simChallenge; /** * @@ -39,7 +41,11 @@ public class SigmaProtocolOr2 { * @param simulator * @param proverIdx Which index should the prover be inserted at (0 means first, 1 means second) */ - public Prover(SigmaProtocol.Prover prover, SigmaProtocol.Simulator simulator, int proverIdx) { + public Prover(Concatenator.Pair firstMessageConcatenator, Concatenator.Triplet finalMessageConcatenator, ChallengeGenerator challengeGenerator, + SigmaProtocol.Prover prover, SigmaProtocol.Simulator simulator, int proverIdx) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.challengeGenerator = challengeGenerator; this.prover = prover; this.simulator = simulator; this.proverIdx = proverIdx; @@ -47,45 +53,56 @@ public class SigmaProtocolOr2 { } @Override - public Message getFirstMessage() { - simChallenge = generateChallenge(); + public FirstMessageOut getFirstMessage() { + simChallenge = challengeGenerator.generateChallenge(); if (proverIdx == 0) { - return buildConcatenatedFirstMessage(prover.getFirstMessage(), simulator.getFirstMessage(simChallenge)); + return firstMessageConcatenator.concatenate(prover.getFirstMessage(), simulator.getFirstMessage(simChallenge)); } else { - return buildConcatenatedFirstMessage(simulator.getFirstMessage(simChallenge), prover.getFirstMessage()); + return firstMessageConcatenator.concatenate(simulator.getFirstMessage(simChallenge), prover.getFirstMessage()); } } @Override - public Message getFinalMessage(BigInteger challenge) { - BigInteger realchallenge = subtractChallenge(challenge, simChallenge); + public FinalMessageOut getFinalMessage(BigInteger challenge) { + BigInteger realchallenge = challengeGenerator.subtractChallenge(challenge, simChallenge); if (proverIdx == 0) { - return buildConcatenatedFinalMessage(realchallenge, prover.getFinalMessage(realchallenge), simulator.getFinalMessage()); + return finalMessageConcatenator.concatenate(realchallenge, prover.getFinalMessage(realchallenge), simulator.getFinalMessage()); } else { - return buildConcatenatedFinalMessage(simChallenge, simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); + return finalMessageConcatenator.concatenate(simChallenge, simulator.getFinalMessage(), prover.getFinalMessage(realchallenge)); } } + + @Override + public void reset() { prover.reset(); simulator.reset(); simChallenge = null; } } - static abstract public class Verifier implements SigmaProtocol.Verifier { - final SigmaProtocol.Verifier[] verifiers; + static public class Verifier + implements SigmaProtocol.Verifier { - abstract protected Message getFirstMessage(Message concatenated, int verifier); - abstract protected BigInteger getFirstChallenge(Message concatenated); - abstract protected Message getFinalMessage(Message concatenated, int verifier); + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Triplet finalMessageConcatenator; + + final ChallengeGenerator challengeGenerator; + + final SigmaProtocol.Verifier[] verifiers; - public Verifier(SigmaProtocol.Verifier... verifiers) { + public Verifier(Concatenator.Pair firstMessageConcatenator, Concatenator.Triplet finalMessageConcatenator, + ChallengeGenerator challengeGenerator, + SigmaProtocol.Verifier... verifiers) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.challengeGenerator = challengeGenerator; + this.verifiers = verifiers; } - public boolean verify(Message firstMessage, BigInteger challenge, Message finalMessage) { - - BigInteger firstChallenge = getFirstChallenge(finalMessage); - BigInteger secondChallenge = challenge.subtract(firstChallenge); - return verifiers[0].verify(getFirstMessage(firstMessage, 0), firstChallenge, getFinalMessage(finalMessage, 0)) & - verifiers[0].verify(getFirstMessage(firstMessage, 1), secondChallenge, getFinalMessage(finalMessage, 1)); + public boolean verify(FirstMessageOut firstMessage, BigInteger challenge, FinalMessageOut finalMessage) { + BigInteger firstChallenge = finalMessageConcatenator.getMsg1of3(finalMessage); + BigInteger secondChallenge = challengeGenerator.subtractChallenge(challenge, firstChallenge); + return verifiers[0].verify(firstMessageConcatenator.getMsg1(firstMessage), firstChallenge, finalMessageConcatenator.getMsg2of3(finalMessage)) & + verifiers[1].verify(firstMessageConcatenator.getMsg2(firstMessage), secondChallenge, finalMessageConcatenator.getMsg3of3(finalMessage)); } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index 6c0034d..5cf98d9 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -2,16 +2,13 @@ package meerkat.mixer.proofs; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.concrete.Util; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; - -import java.math.BigInteger; +import meerkat.mixer.proofs.ECElGamalMixProtocols.Mix2Verifier; /** * implements Mix2ZeroKnowledgeVerifier @@ -23,7 +20,11 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { private final RandomOracle randomOracle; private final ECPoint g,h; private final ECElGamalMixParams mixParams; - private final ZeroKnowledgeOrProofParser parser; + final ECElGamalMixProtocols mixProtocols; + final SigmaFiatShamir mix2NIZK; + + +// private final ZeroKnowledgeOrProofParser parser; /** * constructor @@ -36,7 +37,9 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { this.h = encryptor.getElGamalPK().getPK(); this.randomOracle = randomOracle; this.mixParams = new ECElGamalMixParams(encryptor); - this.parser = new ZeroKnowledgeOrProofParser(group); + this.mixProtocols = new ECElGamalMixProtocols(mixParams, null); // We don't need randomness for the verifier + this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); +// this.parser = new ZeroKnowledgeOrProofParser(group); } /** @@ -55,77 +58,11 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage in2, Crypto.RerandomizableEncryptedMessage out1, Crypto.RerandomizableEncryptedMessage out2, - Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { + Mixing.Mix2Proof proof) throws InvalidProtocolBufferException { + ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); - return verifyFiatShamirOrProof(statement, proof.getFirst(), proof.getSecond()); + Mix2Verifier verifier = mixProtocols.new Mix2Verifier(statement); - } - - - /** - * Verify a Schnorr proof of discrete log equality, given the entire transcript of the ZKP. - * @param statement - * @param firstMessage - * @param challenge - * @param finalMessage - * @return - */ - boolean verifyInteractiveDlogProof(ECElGamalMixParams.DlogStatement statement, - Mixing.ZeroKnowledgeProof.DlogProof.FirstMessage firstMessage, - BigInteger challenge, - Mixing.ZeroKnowledgeProof.DlogProof.FinalMessage finalMessage) { - GroupElement grEncoded = firstMessage.getGr(); - ECPoint gr = group.decode(grEncoded.toByteArray()); - - GroupElement hrEncoded = firstMessage.getHr(); - ECPoint hr = group.decode(hrEncoded.toByteArray()); - - BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); - - boolean gGood = group.add(gr, group.multiply(statement.a,challenge)).equals(group.multiply(statement.g,xcr)); - boolean hGood = group.add(hr, group.multiply(statement.b,challenge)).equals(group.multiply(statement.h,xcr)); - return gGood && hGood; - } - - /** - * Verify a conjuction of two Dlog Proofs, given a complete transcript of the ZKP - * @param statement - * @param firstMessage - * @param challenge - * @param finalMessage - * @return - */ - boolean verifyInteractiveAndProof(ECElGamalMixParams.AndStatement statement, - Mixing.ZeroKnowledgeProof.AndProof.FirstMessage firstMessage, - BigInteger challenge, - Mixing.ZeroKnowledgeProof.AndProof.FinalMessage finalMessage) { - return verifyInteractiveDlogProof(statement.clauses[0], firstMessage.getClause0(), challenge, finalMessage.getClause0()) && - verifyInteractiveDlogProof(statement.clauses[1], firstMessage.getClause1(), challenge, finalMessage.getClause1()); - } - - /** - * Verify a disjunction of two Dlog-equality statement conjuctions, given the entire transcript of the ZKP. - * @param statement - * @param firstMessage - * @param challenge - * @param finalMessage - * @return - */ - boolean verifyInteractiveMix2Proof(ECElGamalMixParams.Mix2Statement statement, - Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage, - BigInteger challenge, - Mixing.ZeroKnowledgeProof.OrProof.FinalMessage finalMessage) { - BigInteger c0 = Util.decodeBigInteger(finalMessage.getC0()); - BigInteger c1 = challenge.subtract(c0).mod(group.orderUpperBound()); - - return verifyInteractiveAndProof(statement.clauses[0], firstMessage.getClause0(), c0, finalMessage.getClause0()) && - verifyInteractiveAndProof(statement.clauses[1], firstMessage.getClause1(), c1, finalMessage.getClause1()); - } - - - boolean verifyFiatShamirOrProof(ECElGamalMixParams.Mix2Statement statement, Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage, - Mixing.ZeroKnowledgeProof.OrProof.FinalMessage finalMessage) { - BigInteger challenge = Prover.hash(firstMessage, randomOracle).mod(group.orderUpperBound()); - return verifyInteractiveMix2Proof(statement, firstMessage, challenge, finalMessage); + return mix2NIZK.verifyNizk(proof, verifier); } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java index ac3f6a5..36d39ac 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java @@ -37,13 +37,13 @@ public final class VerifyTable { Arrays.fill(locationChecksumLayer,false); } - Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.getProofs(); + Mixing.Mix2Proof[][] Mix2Proofs = mixerOutput.getProofs(); Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.getEncryptedMessages(); - for (int i = 0; i < zeroKnowledgeProofs.length ; i++){ - for (int j = 0; j < zeroKnowledgeProofs[i].length ; j ++){ - Mixing.ZeroKnowledgeProof zkp = zeroKnowledgeProofs[i][j]; - Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation(); + for (int i = 0; i < Mix2Proofs.length ; i++){ + for (int j = 0; j < Mix2Proofs[i].length ; j ++){ + Mixing.Mix2Proof zkp = Mix2Proofs[i][j]; + Mixing.Mix2Proof.Location location = zkp.getLocation(); index1 = location.getI(); index2 = location.getJ(); layer = location.getLayer(); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java index a2ab318..5c3d6c8 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java @@ -13,75 +13,75 @@ import java.math.BigInteger; * zero knowledge proof parser */ public class ZeroKnowledgeOrProofParser { - - private final ECGroup group; - - /** - * parse or proof message and return the result in zero knowledge or proof container - * @param orProof - * @return zero knowledge or proof container - */ - public ZeroKnowledgeOrProofContainer parseOrProof(Mixing.ZeroKnowledgeProof.OrProof orProof){ - return new ZeroKnowledgeOrProofContainer(orProof); - } - - /** - * getter - * @param group - */ - public ZeroKnowledgeOrProofParser(ECGroup group) { - this.group = group; - } - - - /** - * inner class - * container for parsed zero knowledge or proof - * constructor is private, can be construct using ZeroKnowledgeOrProofParser.parseOrProof - */ - public class ZeroKnowledgeOrProofContainer{ - public final ECPoint g1,g2,h1,h2; - public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag; - public final ECPoint u,v,uTag,vTag; - public final BigInteger c1,c2,z,zTag; - public final Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; - - /** - * constructor - * @param orProof - */ - private ZeroKnowledgeOrProofContainer(Mixing.ZeroKnowledgeProof.OrProof orProof){ - this.firstMessage = - Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() - .setG1(orProof.getG1()) - .setH1(orProof.getH1()) - .setG2(orProof.getG2()) - .setH2(orProof.getH2()) - .setG1Tag(orProof.getG1Tag()) - .setH1Tag(orProof.getH1Tag()) - .setG2Tag(orProof.getG2Tag()) - .setH2Tag(orProof.getH2Tag()) - .setU(orProof.getU()) - .setV(orProof.getV()) - .setUTag(orProof.getUTag()) - .setVTag(orProof.getVTag()) - .build(); - this.g1 = ECElGamalEncryption.decodeElement(group, orProof.getG1()); - this.g2 = ECElGamalEncryption.decodeElement(group, orProof.getG2()); - this.h1 = ECElGamalEncryption.decodeElement(group, orProof.getH1()); - this.h2 = ECElGamalEncryption.decodeElement(group, orProof.getH2()); - this.g1Tag = ECElGamalEncryption.decodeElement(group, orProof.getG1Tag()); - this.g2Tag = ECElGamalEncryption.decodeElement(group, orProof.getG2Tag()); - this.h1Tag = ECElGamalEncryption.decodeElement(group, orProof.getH1Tag()); - this.h2Tag = ECElGamalEncryption.decodeElement(group, orProof.getH2Tag()); - this.u = ECElGamalEncryption.decodeElement(group, orProof.getU()); - this.v = ECElGamalEncryption.decodeElement(group, orProof.getV()); - this.uTag = ECElGamalEncryption.decodeElement(group, orProof.getUTag()); - this.vTag = ECElGamalEncryption.decodeElement(group, orProof.getVTag()); - this.c1 = Util.decodeBigInteger(orProof.getC1()); - this.c2 = Util.decodeBigInteger(orProof.getC2()); - this.z = Util.decodeBigInteger(orProof.getZ()); - this.zTag = Util.decodeBigInteger(orProof.getZTag()); - } - } +// +// private final ECGroup group; +// +// /** +// * parse or proof message and return the result in zero knowledge or proof container +// * @param orProof +// * @return zero knowledge or proof container +// */ +// public ZeroKnowledgeOrProofContainer parseOrProof(Mixing.Mix2Proof.OrProof orProof){ +// return new ZeroKnowledgeOrProofContainer(orProof); +// } +// +// /** +// * getter +// * @param group +// */ +// public ZeroKnowledgeOrProofParser(ECGroup group) { +// this.group = group; +// } +// +// +// /** +// * inner class +// * container for parsed zero knowledge or proof +// * constructor is private, can be construct using ZeroKnowledgeOrProofParser.parseOrProof +// */ +// public class ZeroKnowledgeOrProofContainer{ +// public final ECPoint g1,g2,h1,h2; +// public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag; +// public final ECPoint u,v,uTag,vTag; +// public final BigInteger c1,c2,z,zTag; +// public final Mixing.Mix2Proof.OrProof.FirstMessage firstMessage; +// +// /** +// * constructor +// * @param orProof +// */ +// private ZeroKnowledgeOrProofContainer(Mixing.Mix2Proof.OrProof orProof){ +// this.firstMessage = +// Mixing.Mix2Proof.OrProof.FirstMessage.newBuilder() +// .setG1(orProof.getG1()) +// .setH1(orProof.getH1()) +// .setG2(orProof.getG2()) +// .setH2(orProof.getH2()) +// .setG1Tag(orProof.getG1Tag()) +// .setH1Tag(orProof.getH1Tag()) +// .setG2Tag(orProof.getG2Tag()) +// .setH2Tag(orProof.getH2Tag()) +// .setU(orProof.getU()) +// .setV(orProof.getV()) +// .setUTag(orProof.getUTag()) +// .setVTag(orProof.getVTag()) +// .build(); +// this.g1 = ECElGamalEncryption.decodeElement(group, orProof.getG1()); +// this.g2 = ECElGamalEncryption.decodeElement(group, orProof.getG2()); +// this.h1 = ECElGamalEncryption.decodeElement(group, orProof.getH1()); +// this.h2 = ECElGamalEncryption.decodeElement(group, orProof.getH2()); +// this.g1Tag = ECElGamalEncryption.decodeElement(group, orProof.getG1Tag()); +// this.g2Tag = ECElGamalEncryption.decodeElement(group, orProof.getG2Tag()); +// this.h1Tag = ECElGamalEncryption.decodeElement(group, orProof.getH1Tag()); +// this.h2Tag = ECElGamalEncryption.decodeElement(group, orProof.getH2Tag()); +// this.u = ECElGamalEncryption.decodeElement(group, orProof.getU()); +// this.v = ECElGamalEncryption.decodeElement(group, orProof.getV()); +// this.uTag = ECElGamalEncryption.decodeElement(group, orProof.getUTag()); +// this.vTag = ECElGamalEncryption.decodeElement(group, orProof.getVTag()); +// this.c1 = Util.decodeBigInteger(orProof.getC1()); +// this.c2 = Util.decodeBigInteger(orProof.getC2()); +// this.z = Util.decodeBigInteger(orProof.getZ()); +// this.zTag = Util.decodeBigInteger(orProof.getZTag()); +// } +// } } diff --git a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java index af6a865..1690aa5 100644 --- a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java +++ b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java @@ -84,9 +84,9 @@ public class CreateTestVector { //@SimpleRerandomizeTest public void createInvalidTest() throws IOException { - //Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(encryptor,randomOracle,true); - //Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,encryptor,randomOracle,true); - //mixer = new Mixer(randomMixer,corruptedProver,encryptor,corruptedVerifier); + //Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(enc,randomOracle,true); + //Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,enc,randomOracle,true); + //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); List mixerInput = generateMixerInput(); System.out.println("start mixing"); diff --git a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java new file mode 100644 index 0000000..98c11aa --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java @@ -0,0 +1,44 @@ +package meerkat.mixer; + +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.mixer.proofs.Prover; +import meerkat.mixer.proofs.Verifier; +import meerkat.protobuf.ConcreteCrypto; +import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.primitives.concrete.DigestOracle; +import org.factcenter.qilin.primitives.concrete.ECElGamal; +import org.factcenter.qilin.primitives.concrete.ECGroup; + +import java.math.BigInteger; +import java.security.spec.InvalidKeySpecException; +import java.util.Random; + +/** + * Base class with common parameters. + */ +public class ECParamTestBase { + + public Random rand; + public ECElGamal.SK key; + public ECGroup group; + public ECElGamalEncryption enc; + public RandomOracle randomOracle = new DigestOracle(); + public ConcreteCrypto.ElGamalPublicKey serializedPk; + + public ECParamTestBase() { + rand = new Random(1); + group = new ECGroup("secp256k1"); + BigInteger sk = ECElGamal.generateSecretKey(group, rand); + key = new ECElGamal.SK(group, sk); + serializedPk = Utils.serializePk(group, key); + enc = new ECElGamalEncryption(); + try { + enc.init(serializedPk); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + assert(false); + } + } +} diff --git a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java b/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java similarity index 85% rename from mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java rename to mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java index 0f7e729..aec3619 100644 --- a/mixer/src/test/java/meerkat/mixer/ZeroKnowledgeProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java @@ -28,26 +28,12 @@ import java.util.Random; /** * Created by Tzlil on 12/31/2015. */ -public class ZeroKnowledgeProofTest { - - Random rand; - ECElGamal.SK key; - ECGroup group; - ECElGamalEncryption enc; - ConcreteCrypto.ElGamalPublicKey serializedPk; +public class Mix2ProofTest extends ECParamTestBase { Mix2ZeroKnowledgeVerifier verifier ; Mix2ZeroKnowledgeProver prover ; @Before public void setup() throws Exception { - rand = new Random(); - group = new ECGroup("secp256k1"); - BigInteger sk = ECElGamal.generateSecretKey(group, rand); - key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); - enc = new ECElGamalEncryption(); - enc.init(serializedPk); - RandomOracle randomOracle = new DigestOracle(); verifier = new Verifier(enc,randomOracle); prover = new Prover(new Random(),enc,randomOracle); } @@ -91,13 +77,13 @@ public class ZeroKnowledgeProofTest { group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2())))); - Mixing.ZeroKnowledgeProof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2); + Mixing.Mix2Proof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2); assertTrue (verifier.verify(e1,e2,e1New,e2New, proof)); } @Test - public void zeroKnowledgeProofTest() throws InvalidProtocolBufferException { + public void Mix2ProofTest() throws InvalidProtocolBufferException { int tests = 1000; diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index 229196c..87eb4e8 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -25,12 +25,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Random; -public class MixingTest { - - ECElGamalEncryption encryptor; - ECGroup group; +public class MixingTest extends ECParamTestBase { Random random,randomMixer,randomProver; - RandomOracle randomOracle; Mix2ZeroKnowledgeVerifier verifier; Prover prover; meerkat.crypto.mixnet.Mixer mixer; @@ -41,16 +37,12 @@ public class MixingTest { @Before public void setup() throws InvalidKeySpecException { // initialization - random = new Random(); - group = new ECGroup("secp256k1"); - encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); - randomMixer = new Random(); - randomProver = new Random(); - randomOracle = new DigestOracle(); - verifier = new Verifier(encryptor,randomOracle); - prover = new Prover(randomProver,encryptor,randomOracle); - mixer = new Mixer(prover,encryptor); + random = new Random(1); + randomMixer = new Random(2); + randomProver = new Random(3); + verifier = new Verifier(enc,randomOracle); + prover = new Prover(randomProver, enc,randomOracle); + mixer = new Mixer(prover, enc); // generate n int logN = 8; // + random.nextInt(8) @@ -63,7 +55,7 @@ public class MixingTest { Voting.PlaintextBallot msg; for (int i = 0; i < n ; i++){ msg = Utils.genRandomBallot(2,3,16); - result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random))); + result.add(enc.encrypt(msg, enc.generateRandomness(random))); } return result; } diff --git a/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java new file mode 100644 index 0000000..bcc5100 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java @@ -0,0 +1,52 @@ +package meerkat.mixer.proofs; + +import meerkat.protobuf.Mixing; +import org.factcenter.qilin.primitives.RandomOracle; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Created by talm on 12/01/17. + */ +public class AndStatementSigmaTest extends SigmaProtocolTest { + @Override + void generateRandomTrueStatement() { + + } + + @Override + void generateRandomFalseStatement() { + + } + + @Override + protected SigmaProtocol.Prover getNewProver() { + return null; + } + + @Override + protected SigmaProtocol.Verifier getNewVerifier() { + return null; + } + + @Override + protected SigmaProtocol.Simulator getNewSimulator() { + return null; + } + + @Override + protected RandomOracle getRandomOracle() { + return null; + } + + @Override + protected Random getRandom() { + return null; + } + + @Override + protected BigInteger getChallengeModulus() { + return null; + } +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java new file mode 100644 index 0000000..bec9c23 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java @@ -0,0 +1,86 @@ +package meerkat.mixer.proofs; + +import meerkat.mixer.ECParamTestBase; +import meerkat.protobuf.Mixing; +import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.util.Pair; +import org.junit.Before; + +import java.math.BigInteger; +import java.util.Random; + +import static org.junit.Assert.*; + +/** + * Created by talm on 12/01/17. + */ +public class DlogStatementSchnorrSigmaTest extends + SigmaProtocolTest { + + ECParamTestBase ecParams = new ECParamTestBase(); + ECElGamalMixParams params; + ECElGamalMixProtocols prots; + + ECElGamalMixParams.DlogStatement statement; + ECElGamalMixParams.DlogStatementWitness witness; + ECElGamalMixProtocols.DlogStatementSchnorrProver prover; + ECElGamalMixProtocols.DlogStatementSchnorrVerifier verifier; + ECElGamalMixProtocols.DlogStatementSchnorrSimulator simulator; + + public DlogStatementSchnorrSigmaTest() { + + this.params = new ECElGamalMixParams(ecParams.enc); + this.prots = new ECElGamalMixProtocols(params, ecParams.rand); // We don't need randomness for the verifier +// this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); + } + + + void generateRandomTrueStatement() { + BigInteger x = prots.encryptor.generateRandomExponent(rand); + ECPoint a = prots.group.multiply(prots.g, x); + ECPoint b = prots.group.multiply(prots.h, x); + statement = params.new DlogStatement(a, b); + witness = params.new DlogStatementWitness(x); + } + + void generateRandomFalseStatement() { + ECPoint a = prots.group.sample(rand); + ECPoint b = prots.group.sample(rand); + witness = null; + statement = params.new DlogStatement(a, b); + } + + @Override + protected SigmaProtocol.Prover getNewProver() { + prover = prots.new DlogStatementSchnorrProver(statement, witness); + return prover; + } + + @Override + protected SigmaProtocol.Verifier getNewVerifier() { + verifier = prots.new DlogStatementSchnorrVerifier(statement); + return verifier; + } + + @Override + protected SigmaProtocol.Simulator getNewSimulator() { + simulator = prots.new DlogStatementSchnorrSimulator(statement); + return simulator; + } + + @Override + protected RandomOracle getRandomOracle() { + return ecParams.randomOracle; + } + + @Override + protected Random getRandom() { + return ecParams.rand; + } + + @Override + protected BigInteger getChallengeModulus() { + return prots.group.orderUpperBound(); + } +} \ No newline at end of file diff --git a/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java b/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java new file mode 100644 index 0000000..dbbea17 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java @@ -0,0 +1,13 @@ +package meerkat.mixer.proofs; + +import meerkat.protobuf.Mixing; + +/** + * Created by talm on 12/01/17. + */ +public class NIZKContainers { + public static class DlogNIZK { + public Mixing.Mix2Proof.DlogProof.FirstMessage m1; + + } +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java new file mode 100644 index 0000000..3b826b5 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java @@ -0,0 +1,116 @@ +package meerkat.mixer.proofs; + +import com.google.protobuf.Message; +import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.util.Pair; +import org.junit.Before; +import org.junit.Test; + +import java.math.BigInteger; +import java.util.Random; + +import static org.junit.Assert.*; + +/** + * Generic test for Sigma Protocol + */ +abstract public class SigmaProtocolTest { + public final int NUM_REPEAT = 10; + + + abstract void generateRandomTrueStatement(); + + abstract void generateRandomFalseStatement(); + + abstract protected SigmaProtocol.Prover getNewProver(); + abstract protected SigmaProtocol.Verifier getNewVerifier(); + abstract protected SigmaProtocol.Simulator getNewSimulator(); + + class NIZKConcat implements Concatenator.Pair, M1, M2> { + @Override + public Pair concatenate(M1 msg1, M2 msg2) { return new Pair(msg1, msg2); } + + @Override + public M1 getMsg1(Pair msg) { return msg.a; } + + @Override + public M2 getMsg2(Pair msg) { return msg.b; } + } + + final NIZKConcat nizkConcat = new NIZKConcat(); + + abstract protected RandomOracle getRandomOracle(); + + + abstract protected Random getRandom(); + abstract protected BigInteger getChallengeModulus(); + + SigmaProtocol.Prover prover; + SigmaProtocol.Verifier verifier; + SigmaProtocol.Simulator simulator; + BigInteger challengeModulus; + int challengeBits; + + Random rand; + + @Before + public void setup() { + simulator = getNewSimulator(); + rand = getRandom(); + challengeModulus = getChallengeModulus(); + challengeBits = challengeModulus.bitLength() + 1; + } + + @Test + public void testProverCompleteness() { + for (int i = 0; i < NUM_REPEAT; ++i) { + generateRandomTrueStatement(); + + prover = getNewProver(); + verifier = getNewVerifier(); + + M1 msg1 = prover.getFirstMessage(); + BigInteger c = new BigInteger(challengeBits, rand).mod(challengeModulus); + M2 msg2 = prover.getFinalMessage(c); + + assertTrue(String.format("Verification error in iteration %d", i), verifier.verify(msg1, c, msg2)); + } + } + + + @Test + public void testSimulatorCompleteness() { + for (int i = 0; i < NUM_REPEAT; ++i) { + generateRandomFalseStatement(); + + simulator = getNewSimulator(); + verifier = getNewVerifier(); + + BigInteger c = new BigInteger(challengeBits, rand).mod(challengeModulus); + + M1 msg1 = simulator.getFirstMessage(c); + M2 msg2 = simulator.getFinalMessage(); + + assertTrue(String.format("Simulator Verification error in iteration %d", i), verifier.verify(msg1, c, msg2)); + } + } + + @Test + public void testNIZKCompleteness() { + for (int i = 0; i < NUM_REPEAT; ++i) { + generateRandomTrueStatement(); + + SigmaFiatShamir, M1, M2> fiatShamir = new SigmaFiatShamir, M1, M2>(nizkConcat, getRandomOracle()); + + prover = getNewProver(); + Pair nizk = fiatShamir.generateNizk(prover); + + verifier = getNewVerifier(); + boolean nizkOk = fiatShamir.verifyNizk(nizk, verifier); + + assertTrue(String.format("NIZK Verification error in iteration %d", i), nizkOk); + } + } + + +} \ No newline at end of file From c2da5aa464ac49fdf9761794b362f8b55a5e46bb Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Sat, 14 Jan 2017 02:42:02 +0200 Subject: [PATCH 09/25] All tests pass --- .../mixer/proofs/ECElGamalMixProtocols.java | 5 +- .../java/meerkat/mixer/proofs/Prover.java | 6 +- .../mixer/proofs/SigmaProtocolOr2.java | 41 +++++++++ .../java/meerkat/mixer/MixNetworkTest.java | 2 +- .../mixer/proofs/AndStatementSigmaTest.java | 52 ----------- .../proofs/DlogAndStatementSigmaTest.java | 58 ++++++++++++ .../proofs/DlogOrStatementSigmaTest.java | 79 ++++++++++++++++ .../proofs/DlogStatementSchnorrSigmaTest.java | 43 ++++----- .../meerkat/mixer/proofs/DummySigmaProof.java | 91 +++++++++++++++++++ .../meerkat/mixer/proofs/DummySigmaTest.java | 48 ++++++++++ .../meerkat/mixer/proofs/NIZKContainers.java | 13 --- .../mixer/proofs/SigmaProtocolTest.java | 12 +-- 12 files changed, 350 insertions(+), 100 deletions(-) delete mode 100644 mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java create mode 100644 mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java delete mode 100644 mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java index bfebbc8..f14ae3d 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java @@ -3,6 +3,7 @@ package meerkat.mixer.proofs; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto.GroupElement; +import meerkat.protobuf.Mixing; import meerkat.protobuf.Mixing.Mix2Proof.AndProof; import meerkat.protobuf.Mixing.Mix2Proof.DlogProof; import org.bouncycastle.math.ec.ECPoint; @@ -165,7 +166,7 @@ public class ECElGamalMixProtocols { } } - public class Mix2Prover extends SigmaProtocolOr2.Prover { + public class Mix2Prover extends SigmaProtocolOr2.Prover { public Mix2Prover(ECElGamalMixParams.Mix2Statement statement, ECElGamalMixParams.Mix2StatementWitness witness) { super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, new AndStatementProver(statement.clauses[witness.trueClauseIndex], witness.witness), @@ -174,7 +175,7 @@ public class ECElGamalMixProtocols { } } - public class Mix2Verifier extends SigmaProtocolOr2.Verifier { + public class Mix2Verifier extends SigmaProtocolOr2.Verifier { public Mix2Verifier(ECElGamalMixParams.Mix2Statement statement) { super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, new AndStatementVerifier(statement.clauses[0]), new AndStatementVerifier(statement.clauses[1])); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index 9a8a2f3..9fd2662 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -77,7 +77,11 @@ public class Prover implements Mix2ZeroKnowledgeProver { ECElGamalMixProtocols.Mix2Prover prover = mixProtocols.new Mix2Prover(statement, witness); - return mix2NIZK.generateNizk(prover); + Mixing.Mix2Proof.Location location = Mixing.Mix2Proof.Location.newBuilder() + .setI(i) + .setJ(j) + .setLayer(layer).build(); + return mix2NIZK.generateNizk(prover).toBuilder().setLocation(location).build(); // Mixing.Mix2Proof first,second,third,fourth; // diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java index cf2c4ff..178c89e 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java @@ -106,4 +106,45 @@ public class SigmaProtocolOr2 { } } + static public class Simulator + implements SigmaProtocol.Simulator { + final Concatenator.Pair firstMessageConcatenator; + final Concatenator.Triplet finalMessageConcatenator; + + final ChallengeGenerator challengeGenerator; + + final SigmaProtocol.Simulator[] simulators; + + + BigInteger simChallenge0; + + + public Simulator(Concatenator.Pair firstMessageConcatenator, + Concatenator.Triplet finalMessageConcatenator, + ChallengeGenerator challengeGenerator, SigmaProtocol.Simulator... simulators) { + this.firstMessageConcatenator = firstMessageConcatenator; + this.finalMessageConcatenator = finalMessageConcatenator; + this.challengeGenerator = challengeGenerator; + this.simulators = simulators; + } + + + @Override + public FirstMessageOut getFirstMessage(BigInteger challenge) { + + simChallenge0 = challengeGenerator.generateChallenge(); + BigInteger simChallenge1 = challengeGenerator.subtractChallenge(challenge, simChallenge0); + + return firstMessageConcatenator.concatenate(simulators[0].getFirstMessage(simChallenge0), simulators[1].getFirstMessage(simChallenge1)); + } + + @Override + public FinalMessageOut getFinalMessage() { + return finalMessageConcatenator.concatenate(simChallenge0, simulators[0].getFinalMessage(), simulators[1].getFinalMessage()); + } + + @Override + public void reset() { simulators[0].reset(); simulators[1].reset(); } + } + } diff --git a/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java b/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java index 23eaea4..0245726 100644 --- a/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java @@ -16,7 +16,7 @@ public class MixNetworkTest { @Test public void testMixNetwork() throws Exception{ - Random random = new Random(); + Random random = new Random(1); int logn = 10; int n = 1 << logn; int layers = 2*logn - 1; diff --git a/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java deleted file mode 100644 index bcc5100..0000000 --- a/mixer/src/test/java/meerkat/mixer/proofs/AndStatementSigmaTest.java +++ /dev/null @@ -1,52 +0,0 @@ -package meerkat.mixer.proofs; - -import meerkat.protobuf.Mixing; -import org.factcenter.qilin.primitives.RandomOracle; - -import java.math.BigInteger; -import java.util.Random; - -/** - * Created by talm on 12/01/17. - */ -public class AndStatementSigmaTest extends SigmaProtocolTest { - @Override - void generateRandomTrueStatement() { - - } - - @Override - void generateRandomFalseStatement() { - - } - - @Override - protected SigmaProtocol.Prover getNewProver() { - return null; - } - - @Override - protected SigmaProtocol.Verifier getNewVerifier() { - return null; - } - - @Override - protected SigmaProtocol.Simulator getNewSimulator() { - return null; - } - - @Override - protected RandomOracle getRandomOracle() { - return null; - } - - @Override - protected Random getRandom() { - return null; - } - - @Override - protected BigInteger getChallengeModulus() { - return null; - } -} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java new file mode 100644 index 0000000..50c232a --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java @@ -0,0 +1,58 @@ +package meerkat.mixer.proofs; + +import meerkat.protobuf.Mixing; +import org.factcenter.qilin.util.Pair; + +import java.math.BigInteger; + +/** + * Created by talm on 12/01/17. + */ +public class DlogAndStatementSigmaTest extends SigmaProtocolTest { + final DlogStatementSchnorrSigmaTest dlogtest; + + ECElGamalMixParams.DlogStatement s1, s2; + ECElGamalMixParams.DlogStatementWitness w1, w2; + + public DlogAndStatementSigmaTest() { + this.dlogtest = new DlogStatementSchnorrSigmaTest(); + } + + @Override + void generateRandomTrueStatement() { + Pair s1w1 = dlogtest.returnRandomTrueStatement(); + s1 = s1w1.a; w1 = s1w1.b; + + Pair s2w2 = dlogtest.returnRandomTrueStatement(); + s2 = s2w2.a; w2 = s2w2.b; + } + + @Override + void generateRandomFalseStatement() { + s1 = dlogtest.returnRandomFalseStatement(); + s2 = dlogtest.returnRandomFalseStatement(); + } + + @Override + protected SigmaProtocol.Prover getNewProver() { + return new SigmaProtocolAnd2.Prover<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + dlogtest.prots.new DlogStatementSchnorrProver(s1, w1), dlogtest.prots.new DlogStatementSchnorrProver(s2, w2)); + } + + @Override + protected SigmaProtocol.Verifier getNewVerifier() { + return new SigmaProtocolAnd2.Verifier<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + dlogtest.prots.new DlogStatementSchnorrVerifier(s1), dlogtest.prots.new DlogStatementSchnorrVerifier(s2)); + } + + @Override + protected SigmaProtocol.Simulator getNewSimulator() { + return new SigmaProtocolAnd2.Simulator<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + dlogtest.prots.new DlogStatementSchnorrSimulator(s1), dlogtest.prots.new DlogStatementSchnorrSimulator(s2)); + } + + @Override + protected BigInteger getChallengeModulus() { + return dlogtest.getChallengeModulus(); + } +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java new file mode 100644 index 0000000..a352d42 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java @@ -0,0 +1,79 @@ +package meerkat.mixer.proofs; + +import meerkat.protobuf.Mixing; +import org.factcenter.qilin.util.Pair; + +import java.math.BigInteger; + +/** + * Created by talm on 14/01/17. + */ +public class DlogOrStatementSigmaTest extends SigmaProtocolTest { + final DlogStatementSchnorrSigmaTest dlogtest; + + final ECElGamalMixParams.AndStatement[] statements = new ECElGamalMixParams.AndStatement[2]; + ECElGamalMixParams.AndStatementWitness w; + int trueStatementIndex; + + + public DlogOrStatementSigmaTest() { + this.dlogtest = new DlogStatementSchnorrSigmaTest(); + } + + @Override + void generateRandomTrueStatement() { + trueStatementIndex = rand.nextInt(2); + Pair s1w1 = dlogtest.returnRandomTrueStatement(); + Pair s2w2 = dlogtest.returnRandomTrueStatement(); + ECElGamalMixParams.AndStatement trueStatement = dlogtest.params.new AndStatement(s1w1.a, s2w2.a); + w = dlogtest.params.new AndStatementWitness(s1w1.b, s2w2.b); + statements[trueStatementIndex] = trueStatement; + + ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + + ECElGamalMixParams.AndStatement falseStatement = dlogtest.params.new AndStatement(f1, f2); + + statements[1 - trueStatementIndex] = falseStatement; + } + + @Override + void generateRandomFalseStatement() { + ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + + statements[0] = dlogtest.params.new AndStatement(f1, f2); + + f1 = dlogtest.returnRandomFalseStatement(); + f2 = dlogtest.returnRandomFalseStatement(); + statements[1] = dlogtest.params.new AndStatement(f1, f2); + } + + @Override + protected SigmaProtocol.Prover getNewProver() { + SigmaProtocol.Prover andProver = dlogtest.prots.new AndStatementProver(statements[trueStatementIndex], w); + SigmaProtocol.Simulator andSimulator = dlogtest.prots.new AndStatementSimulator(statements[1 - trueStatementIndex]); + + return new SigmaProtocolOr2.Prover<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, + dlogtest.prots.challengeGenerator, andProver, andSimulator, trueStatementIndex); + } + + @Override + protected SigmaProtocol.Verifier getNewVerifier() { + return new SigmaProtocolOr2.Verifier(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, + dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementVerifier(statements[0]), dlogtest.prots.new AndStatementVerifier(statements[1])); + } + + @Override + protected SigmaProtocol.Simulator getNewSimulator() { + return new SigmaProtocolOr2.Simulator<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, + dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementSimulator(statements[0]), + dlogtest.prots.new AndStatementSimulator(statements[1])); + } + + @Override + protected BigInteger getChallengeModulus() { + return dlogtest.getChallengeModulus(); + } +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java index bec9c23..868bce0 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java @@ -3,14 +3,9 @@ package meerkat.mixer.proofs; import meerkat.mixer.ECParamTestBase; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.util.Pair; -import org.junit.Before; import java.math.BigInteger; -import java.util.Random; - -import static org.junit.Assert.*; /** * Created by talm on 12/01/17. @@ -31,24 +26,36 @@ public class DlogStatementSchnorrSigmaTest extends public DlogStatementSchnorrSigmaTest() { this.params = new ECElGamalMixParams(ecParams.enc); - this.prots = new ECElGamalMixProtocols(params, ecParams.rand); // We don't need randomness for the verifier -// this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); + this.prots = new ECElGamalMixProtocols(params, rand); // We don't need randomness for the verifier } - void generateRandomTrueStatement() { + Pair returnRandomTrueStatement() { BigInteger x = prots.encryptor.generateRandomExponent(rand); ECPoint a = prots.group.multiply(prots.g, x); ECPoint b = prots.group.multiply(prots.h, x); - statement = params.new DlogStatement(a, b); - witness = params.new DlogStatementWitness(x); + ECElGamalMixParams.DlogStatement statement = params.new DlogStatement(a, b); + ECElGamalMixParams.DlogStatementWitness witness = params.new DlogStatementWitness(x); + + return new Pair<>(statement, witness); + } + + ECElGamalMixParams.DlogStatement returnRandomFalseStatement() { + ECPoint a = prots.group.sample(rand); + ECPoint b = prots.group.sample(rand); + + return params.new DlogStatement(a, b); + } + + void generateRandomTrueStatement() { + Pair sw = returnRandomTrueStatement(); + this.statement = sw.a; + this.witness = sw.b; } void generateRandomFalseStatement() { - ECPoint a = prots.group.sample(rand); - ECPoint b = prots.group.sample(rand); witness = null; - statement = params.new DlogStatement(a, b); + statement = returnRandomFalseStatement(); } @Override @@ -69,16 +76,6 @@ public class DlogStatementSchnorrSigmaTest extends return simulator; } - @Override - protected RandomOracle getRandomOracle() { - return ecParams.randomOracle; - } - - @Override - protected Random getRandom() { - return ecParams.rand; - } - @Override protected BigInteger getChallengeModulus() { return prots.group.orderUpperBound(); diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java new file mode 100644 index 0000000..07c6c80 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java @@ -0,0 +1,91 @@ +package meerkat.mixer.proofs; + +import meerkat.crypto.concrete.Util; +import meerkat.protobuf.Crypto; + +import java.math.BigInteger; + +/** + * A dummy proof that can be used for testing + */ +public class DummySigmaProof { + public static class Prover implements SigmaProtocol.Prover { + + /** + * The "statement" to be proved: x + y = z + */ + + final BigInteger x,y,z; + final BigInteger r; + + public Prover(BigInteger x, BigInteger y, BigInteger z, BigInteger r) { + this.x = x; + this.y = y; + this.z = z; + this.r = r; + } + + @Override + public Crypto.BigInteger getFirstMessage() { + return Util.encodeBigInteger(r); + } + + @Override + public BigInteger getFinalMessage(BigInteger challenge) { + return challenge.add(r.multiply(x.add(y))); + } + + @Override + public void reset() { + + } + } + public static class Verifier implements SigmaProtocol.Verifier { + + final BigInteger x,y,z; + + public Verifier(BigInteger x, BigInteger y, BigInteger z) { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean verify(Crypto.BigInteger firstMessage, BigInteger challenge, BigInteger finalMessage) { + BigInteger r = Util.decodeBigInteger(firstMessage); + return finalMessage.equals(challenge.add(r.multiply(z))); + } + } + + public static class Simulator implements SigmaProtocol.Simulator { + + final BigInteger x,y,z; + + BigInteger resp; + + public Simulator(BigInteger x, BigInteger y, BigInteger z) { + this.x = x; + this.y = y; + this.z = z; + } + + + @Override + public Crypto.BigInteger getFirstMessage(BigInteger challenge) { + BigInteger r = BigInteger.ONE; + resp = challenge.add(z); + return Util.encodeBigInteger(r); + } + + @Override + public BigInteger getFinalMessage() { + return resp; + } + + @Override + public void reset() { + + } + } + +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java new file mode 100644 index 0000000..3c62570 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java @@ -0,0 +1,48 @@ +package meerkat.mixer.proofs; + +import meerkat.protobuf.Crypto; +import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.primitives.concrete.DigestOracle; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Created by talm on 14/01/17. + */ +public class DummySigmaTest extends SigmaProtocolTest { + BigInteger seed; + BigInteger x,y,z; + + @Override + void generateRandomTrueStatement() { + x = new BigInteger(100, rand); y = new BigInteger(100, rand); z = x.add(y); + } + + @Override + void generateRandomFalseStatement() { + x = new BigInteger(100, rand); + y = new BigInteger(100, rand); + z = new BigInteger(100, rand); + } + + @Override + protected SigmaProtocol.Prover getNewProver() { + return new DummySigmaProof.Prover(x, y, z, new BigInteger(100, rand)); + } + + @Override + protected SigmaProtocol.Verifier getNewVerifier() { + return new DummySigmaProof.Verifier(x, y, z); + } + + @Override + protected SigmaProtocol.Simulator getNewSimulator() { + return new DummySigmaProof.Simulator(x, y, z); + } + + @Override + protected BigInteger getChallengeModulus() { + return new BigInteger(100, rand); + } +} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java b/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java deleted file mode 100644 index dbbea17..0000000 --- a/mixer/src/test/java/meerkat/mixer/proofs/NIZKContainers.java +++ /dev/null @@ -1,13 +0,0 @@ -package meerkat.mixer.proofs; - -import meerkat.protobuf.Mixing; - -/** - * Created by talm on 12/01/17. - */ -public class NIZKContainers { - public static class DlogNIZK { - public Mixing.Mix2Proof.DlogProof.FirstMessage m1; - - } -} diff --git a/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java index 3b826b5..4ad3437 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java @@ -2,6 +2,7 @@ package meerkat.mixer.proofs; import com.google.protobuf.Message; import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.primitives.concrete.DigestOracle; import org.factcenter.qilin.util.Pair; import org.junit.Before; import org.junit.Test; @@ -17,6 +18,7 @@ import static org.junit.Assert.*; abstract public class SigmaProtocolTest { public final int NUM_REPEAT = 10; + final RandomOracle randomOracle = new DigestOracle(); abstract void generateRandomTrueStatement(); @@ -39,10 +41,6 @@ abstract public class SigmaProtocolTest { final NIZKConcat nizkConcat = new NIZKConcat(); - abstract protected RandomOracle getRandomOracle(); - - - abstract protected Random getRandom(); abstract protected BigInteger getChallengeModulus(); SigmaProtocol.Prover prover; @@ -51,12 +49,10 @@ abstract public class SigmaProtocolTest { BigInteger challengeModulus; int challengeBits; - Random rand; + Random rand = new Random(1);; @Before public void setup() { - simulator = getNewSimulator(); - rand = getRandom(); challengeModulus = getChallengeModulus(); challengeBits = challengeModulus.bitLength() + 1; } @@ -100,7 +96,7 @@ abstract public class SigmaProtocolTest { for (int i = 0; i < NUM_REPEAT; ++i) { generateRandomTrueStatement(); - SigmaFiatShamir, M1, M2> fiatShamir = new SigmaFiatShamir, M1, M2>(nizkConcat, getRandomOracle()); + SigmaFiatShamir, M1, M2> fiatShamir = new SigmaFiatShamir, M1, M2>(nizkConcat, randomOracle); prover = getNewProver(); Pair nizk = fiatShamir.generateNizk(prover); From 0d416f0018f8a1f5414f65422635fa15023d321e Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 18 Jan 2017 11:47:52 +0200 Subject: [PATCH 10/25] Rewriting Benes network code (in progress) --- .../meerkat/mixer/mixing/BenesNetwork.java | 214 ++++++++++++++++++ .../java/meerkat/mixer/mixing/MixNetwork.java | 2 +- .../mixer/mixing/PermutationNetwork.java | 39 ++++ .../mixer/mixing/RandomPermutation.java | 25 +- .../mixer/mixing/BenesNetworkTest.java | 15 ++ 5 files changed, 282 insertions(+), 13 deletions(-) create mode 100644 mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java create mode 100644 mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java create mode 100644 mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java diff --git a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java new file mode 100644 index 0000000..c4bfd28 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java @@ -0,0 +1,214 @@ +package meerkat.mixer.mixing; + +import java.util.*; + +/** + * Generate the Benes Network + */ +public class BenesNetwork implements PermutationNetwork +{ + /** + * log (base 2) of number of inputs to Benes network (N = 2^{logN}) + */ + final int logN; + + /** + * Values of switches set for a specific permutation. + * switchValues[layer][switchNum] is true if the corresponding switch applies the identity permutation on its inputs. + * layer can be in the range [0, 2*logN-1), switchNum in the range (0, 2^{logN-1}-1) + */ + final boolean[][] switchValues; + + public BenesNetwork(int logN) { + this.logN = logN; + + switchValues = new boolean[2*logN - 1][]; + for (int i = 0; i < switchValues.length; ++i) + switchValues[i] = new boolean[1 << (logN - 1)]; + } + + /** + * Return the index of the switch output in the previous layer that connects to a specified input in the current layer. + * Each consecutive pair of outputs is from the same switch, and each consecutive pair of inputs goes to the same switch. + * (that is, switch j has inputs/outputs 2j and 2j+1) + * + * @param logN log (base 2) of number of inputs to Benes network (N = 2^{logN}) + * @param layer current layer index. Must be between 1 and 2*logN-2 (layer 0 doesn't have a previous layer) + * @param inputIdx the input Idx for the current layer (must be between 0 and (1 << logN) - 1 + * + * @return the requested index + */ + public static int getOutputIdxInPreviousLayer(int logN, int layer, int inputIdx) { + assert (layer > 0) && (layer < 2*logN - 1); + assert (inputIdx >= 0) && (inputIdx < 1 << inputIdx); + + if ((inputIdx & 1) == 0) { + // Even inputs are connected straight "across" everywhere + return inputIdx; + } + + // --- Odd inputs are connected depending on layer --- + + // In middle layer everything goes across + if (layer == logN) + return inputIdx; + + int crossBit; + if (layer < logN) + crossBit = logN - layer; + else + crossBit = layer - logN; + + return inputIdx ^ (1 << crossBit); + } + + /** + * Inverse of {@link #getOutputIdxInPreviousLayer(int, int, int)} + * @param logN + * @param layer + * @param outputIdx + * @return + */ + public static int getInputIdxInNextLayer(int logN, int layer, int outputIdx) { + return getOutputIdxInPreviousLayer(logN, layer + 1, outputIdx); + } + + @Override + public int getNumInputs() { + return 1 << logN; + } + + @Override + public int getNumLayers() { + return 2*logN - 1; + } + + @Override + public int getOutputIdxInPreviousLayer(int layer, int inputIdx) { + return getOutputIdxInPreviousLayer(logN, layer, inputIdx); + } + + + /** + * Find in array + * TODO: replace with more efficient data structure if this becomes a performance bottleneck + * @param val + * @param arr + * @return + */ + static private int find(int val, int[] arr) { + for (int i = 0; i < arr.length; ++i) { + if (arr[i] == val) + return i; + } + return -1; + } + + /** + * The recursive algorithm attributed to H. Stone by A. Waksman + * (see pg. 161 in paper) + * @param permOut + * @param level + */ + private void setInternalPermutation(int[] permIn, int[] permOut, int idx, int level) { + // Make sure idx is in the the range [0, 2^{logN-level-1}) + assert (idx == (idx & ((1 << (logN - level - 1)) - 1))); + assert (permOut.length == (1 << (logN - level))); + assert (permIn.length == permOut.length); + + // Base case + if (level == logN - 1) { + if (permOut[0] == permIn[0]) + switchValues[level][idx] = false; + else + switchValues[level][idx] = true; + return; + } + + int nextLen = permOut.length >>> 1; + int[] upperPermIn = new int[nextLen]; + int[] lowerPermIn = new int[nextLen]; + + int[] upperPermOut = new int[nextLen]; + int[] lowerPermOut = new int[nextLen]; + + + SortedSet unmatchedIndices = new TreeSet<>(); + for (int i = 0; i < permIn.length; ++i) { + unmatchedIndices.add(i); + } + + /** + * Where the set of switches for this level and index actually starts in switchValues + */ + int blockStart = idx << level; + int numSwitches = 1 << (logN - level - 1); + + while (!unmatchedIndices.isEmpty()) { + int i = unmatchedIndices.first(); + + do { + //assert ((i & 1) == 0); // Algorithm guarantees only even indices are unmatched at start of loop + unmatchedIndices.remove(i); + + int switchNum = i >>> 1; + + if (((i & 1) == 0) && (switchNum < numSwitches / 2) || ((i & 1) == 1) && (switchNum >= numSwitches / 2)) { + // i is in the upper half and even, or in the lower half and odd, so + // switch must be "straight" to get i to upper half. + switchValues[2 * logN - level - 1][blockStart + switchNum] = false; + + } else { + switchValues[2 * logN - level - 1][blockStart + switchNum] = true; + } + + int iConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level), i); + int iPairConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level), i ^ 1); + + upperPermOut[iConnectedTo] = permOut[i]; + lowerPermOut[iPairConnectedTo] = permOut[i ^ 1]; + + int j = find(permOut[i], permIn); + int jSwitchNum = j >>> 1; + int j + + if ((((j & 1) == 0) && (jSwitchNum < numSwitches / 2)) || ((j & 1) == 1) && (jSwitchNum >= numSwitches / 2)) { + // Even output in the upper half, or odd output in the lower half + // so switch needs to be "straight" to get j to the upper half + switchValues[level][blockStart + switchNum] = false; + } else { + // Otherwise switch needs to be "crossed" to get j to upper half + switchValues[level][blockStart + switchNum] = true; + j ^= 1; + } + + int jConnectedTo = getInputIdxInNextLayer(logN - level, 0, j); + upperPermIn[jConnectedTo] = j; + + lowerPermIn[i] = permIn[i + 1]; + + } while (unmatchedIndices.contains(i)); + } + + setInternalPermutation(upperPermIn, upperPermOut, idx, level + 1); + setInternalPermutation(lowerPermIn, lowerPermOut, idx, level + 1); + } + + @Override + public void setPermutation(int[] permutation) { + + // We use the recursive algorithm attributed to ? in ?'s paper + int level = 0; + + } + + @Override + public void permuteLayer(T[] values, int layer) { + + } + + @Override + public void permuteLayer(ArrayList values, int layer) { + + } +} diff --git a/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java index e820ebd..99f041e 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java @@ -23,7 +23,7 @@ public class MixNetwork { } /** - * implements benes mix network algorithm + * implements Benes mix network algorithm * @param permutation - random permutation * @return switches */ diff --git a/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java new file mode 100644 index 0000000..7a224ab --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java @@ -0,0 +1,39 @@ +package meerkat.mixer.mixing; + +import java.util.ArrayList; + +/** + * A generic permutation network composed of 2-input switches. + */ +public interface PermutationNetwork { + /** + * Return the number of inputs supported by the network. + * @return + */ + int getNumInputs(); + + /** + * Return the number of layers supported by the network. + * @return + */ + int getNumLayers(); + + int getOutputIdxInPreviousLayer(int layer, int inputIdx); + + /** + * Initialize switches to generate a specific permutation. + * @param permutation + */ + void setPermutation(int[] permutation); + + + /** + * Apply a single layer's permutation (as implied by {@link #setPermutation(int[])}) + * @param values values output by previous layer + * @param layer layer to apply (layer is between 1 and numLayers; layer 0 is the input layer) + * @param type of values. + */ + void permuteLayer(T[] values, int layer); + + void permuteLayer(ArrayList values, int layer); +} diff --git a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java b/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java index 7f18530..85482ce 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java @@ -17,7 +17,7 @@ public class RandomPermutation { * @param n permutation size * @param random */ - public RandomPermutation(int n,Random random) { + public RandomPermutation(int n, Random random) { this.permutation = generatePermutation(n,random); } @@ -27,19 +27,20 @@ public class RandomPermutation { * @param random * @return permutation */ - private int[] generatePermutation(int n,Random random){ - List numbers= new ArrayList(n); - for (int i = 0; i < n; i++) { - numbers.add(i); + public static int[] generatePermutation(int n, Random random){ + int[] result = new int[n]; + + // initialize and permute in one pass using "inside-out" Fisher-Yates + for (int i = 0; i < n; ++i) { + int j = random.nextInt(i+1); + + if (j != i) { + result[i] = result[j]; + } + + result[j] = 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; } } diff --git a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java new file mode 100644 index 0000000..1f6be55 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java @@ -0,0 +1,15 @@ +package meerkat.mixer.mixing; + +import static org.junit.Assert.*; + +/** + * Tests for Benes Network topology + */ +public class BenesNetworkTest { + public static class Permutation { + + } + + public static isAPerm + +} \ No newline at end of file From abf4cc5e54eaf057f0c7bc2d9d17e0bbb815460f Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 18 Jan 2017 21:54:22 +0200 Subject: [PATCH 11/25] Add task to download protoc (protobuf compiler) to root-level build/ directory --- build.gradle | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/build.gradle b/build.gradle index 9f070e3..8c01ae9 100644 --- a/build.gradle +++ b/build.gradle @@ -1,3 +1,6 @@ +plugins { + id "com.google.osdetector" version "1.4.0" +} subprojects { proj -> proj.afterEvaluate { @@ -8,3 +11,44 @@ subprojects { proj -> } } } + +// Script to create a copy of the protobuf compiler jar in the top-level build directory +// (will make it easier to configure the intellij protobuf plugin) +repositories { + mavenLocal(); + mavenCentral(); +} + + +project.ext.protocLocation = 'com.google.protobuf:protoc:3.+' + +// Copied from Google's protobuf plugin code +File getProtocDep(protocLocation) { + // create a project configuration dependency for the artifact + Configuration config = project.configurations.create("protobufToolsLocator") { + visible = false + transitive = false + extendsFrom = [] + } + + def groupId, artifact, version + (groupId, artifact, version) = protocLocation.split(":") + def notation = [group: groupId, + name: artifact, + version: version, + classifier: project.osdetector.classifier, + ext: 'exe'] + Dependency dep = project.dependencies.add(config.name, notation) + + File file = config.fileCollection(dep).singleFile + + return file +} + + +task getprotoc(type: Copy) { + from getProtocDep(project.ext.protocLocation) + rename { file -> return "protoc" } + into "${buildDir}/" +} + From 37d1857f9c74e10c6d9fc02295f5b59a640dbbb9 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 18 Jan 2017 21:54:42 +0200 Subject: [PATCH 12/25] Working on Benes network/testing --- .../meerkat/mixer/mixing/BenesNetwork.java | 79 ++++++++----- .../mixer/mixing/PermutationNetwork.java | 28 ++++- .../mixer/mixing/RandomPermutation.java | 17 ++- .../main/java/meerkat/mixer/mixing/Util.java | 45 ++++++++ .../test/java/meerkat/mixer/MixingTest.java | 2 +- .../mixer/mixing/BenesNetworkTest.java | 15 ++- .../mixer/mixing/PermutationNetworkTest.java | 109 ++++++++++++++++++ 7 files changed, 252 insertions(+), 43 deletions(-) create mode 100644 mixer/src/main/java/meerkat/mixer/mixing/Util.java create mode 100644 mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java diff --git a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java index c4bfd28..10cc45e 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java @@ -39,25 +39,22 @@ public class BenesNetwork implements PermutationNetwork * @return the requested index */ public static int getOutputIdxInPreviousLayer(int logN, int layer, int inputIdx) { - assert (layer > 0) && (layer < 2*logN - 1); + assert (layer >= 0) && (layer < 2*logN - 1); assert (inputIdx >= 0) && (inputIdx < 1 << inputIdx); - if ((inputIdx & 1) == 0) { - // Even inputs are connected straight "across" everywhere + if ((layer == 0) || (inputIdx & 1) == 0) { + // layer 0 inputs and all even inputs + // are connected straight "across" everywhere return inputIdx; } // --- Odd inputs are connected depending on layer --- - // In middle layer everything goes across - if (layer == logN) - return inputIdx; - int crossBit; if (layer < logN) crossBit = logN - layer; else - crossBit = layer - logN; + crossBit = layer - logN + 1; return inputIdx ^ (1 << crossBit); } @@ -73,6 +70,11 @@ public class BenesNetwork implements PermutationNetwork return getOutputIdxInPreviousLayer(logN, layer + 1, outputIdx); } + @Override + public int getInputIdxInNextLayer(int layer, int outputIdx) { + return getInputIdxInNextLayer(logN, layer, outputIdx); + } + @Override public int getNumInputs() { return 1 << logN; @@ -111,11 +113,13 @@ public class BenesNetwork implements PermutationNetwork * @param level */ private void setInternalPermutation(int[] permIn, int[] permOut, int idx, int level) { - // Make sure idx is in the the range [0, 2^{logN-level-1}) - assert (idx == (idx & ((1 << (logN - level - 1)) - 1))); + // Make sure idx is in the the range [0, 2^{level}) + assert (idx < (1 << level)); assert (permOut.length == (1 << (logN - level))); assert (permIn.length == permOut.length); + final int Nover2 = 1 << (logN - level - 1); + // Base case if (level == logN - 1) { if (permOut[0] == permIn[0]) @@ -150,65 +154,80 @@ public class BenesNetwork implements PermutationNetwork do { //assert ((i & 1) == 0); // Algorithm guarantees only even indices are unmatched at start of loop unmatchedIndices.remove(i); + unmatchedIndices.remove(i ^ 1); int switchNum = i >>> 1; + // index of outPerm[i] after the last switch layer. + int iSwitched; + if (((i & 1) == 0) && (switchNum < numSwitches / 2) || ((i & 1) == 1) && (switchNum >= numSwitches / 2)) { // i is in the upper half and even, or in the lower half and odd, so // switch must be "straight" to get i to upper half. - switchValues[2 * logN - level - 1][blockStart + switchNum] = false; + switchValues[2 * logN - level - 2][blockStart + switchNum] = false; + iSwitched = i; } else { - switchValues[2 * logN - level - 1][blockStart + switchNum] = true; + switchValues[2 * logN - level - 2][blockStart + switchNum] = true; + iSwitched = i ^ 1; } - int iConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level), i); - int iPairConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level), i ^ 1); + // Index of outPerm[i] in the output of the previous layer. + int iConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level) - 2, iSwitched); + int iPairConnectedTo = getOutputIdxInPreviousLayer(logN - level, 2 * (logN - level) - 2, iSwitched ^ 1); upperPermOut[iConnectedTo] = permOut[i]; - lowerPermOut[iPairConnectedTo] = permOut[i ^ 1]; + lowerPermOut[iPairConnectedTo - Nover2] = permOut[i ^ 1]; + // Index of permOut[i] before the first switch layer. int j = find(permOut[i], permIn); int jSwitchNum = j >>> 1; - int j + + // Index of permOut[i] after the first switch layer + int jSwitched; if ((((j & 1) == 0) && (jSwitchNum < numSwitches / 2)) || ((j & 1) == 1) && (jSwitchNum >= numSwitches / 2)) { // Even output in the upper half, or odd output in the lower half // so switch needs to be "straight" to get j to the upper half switchValues[level][blockStart + switchNum] = false; + jSwitched = j; } else { // Otherwise switch needs to be "crossed" to get j to upper half switchValues[level][blockStart + switchNum] = true; - j ^= 1; + jSwitched = j ^ 1; } - int jConnectedTo = getInputIdxInNextLayer(logN - level, 0, j); - upperPermIn[jConnectedTo] = j; + int jConnectedTo = getInputIdxInNextLayer(logN - level, 0, jSwitched); + // must be in upper half + assert(jConnectedTo < (1 << (logN - 1))); + upperPermIn[jConnectedTo] = permOut[i]; - lowerPermIn[i] = permIn[i + 1]; + // Connect from j's pair to through the lower half + int jPairConnectedTo = getInputIdxInNextLayer(logN - level, 0, jSwitched ^ 1); + lowerPermIn[jPairConnectedTo - Nover2] = permIn[j ^ 1]; + int iPairNext = find(permIn[j ^ 1], permOut); + i = iPairNext ^ 1; } while (unmatchedIndices.contains(i)); } - setInternalPermutation(upperPermIn, upperPermOut, idx, level + 1); - setInternalPermutation(lowerPermIn, lowerPermOut, idx, level + 1); + setInternalPermutation(upperPermIn, upperPermOut, 2*idx, level + 1); + setInternalPermutation(lowerPermIn, lowerPermOut, 2*idx + 1, level + 1); } @Override public void setPermutation(int[] permutation) { - - // We use the recursive algorithm attributed to ? in ?'s paper int level = 0; + int[] identity = new int[getNumInputs()]; + for (int i = 0; i < identity.length; ++i) + identity[i] = i; + setInternalPermutation(identity, permutation, 0, 0); } @Override - public void permuteLayer(T[] values, int layer) { - + public boolean isCrossed(int layer, int switchIdx) { + return switchValues[layer][switchIdx]; } - @Override - public void permuteLayer(ArrayList values, int layer) { - - } } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java index 7a224ab..4dc1e0e 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java @@ -18,8 +18,26 @@ public interface PermutationNetwork { */ int getNumLayers(); + /** + * Return the index of the switch output in the previous layer that connects to a specified input in the current layer. + * Each consecutive pair of outputs is from the same switch, and each consecutive pair of inputs goes to the same switch. + * (that is, switch j has inputs/outputs 2j and 2j+1) + * + * @param layer current layer index. Must be in the range [0, numLayers) (layer 0's previous layer consists of the inputs themselves) + * @param inputIdx the input Idx for the current layer. Must be in the range [0, numInputs) + * + * @return the requested index + */ int getOutputIdxInPreviousLayer(int layer, int inputIdx); + /** + * The inverse of {@link }#getOutputIdxInPreviousLayer(int,int)}. + * @param layer + * @param inputIdx + * @return + */ + int getInputIdxInNextLayer(int layer, int inputIdx); + /** * Initialize switches to generate a specific permutation. * @param permutation @@ -28,12 +46,10 @@ public interface PermutationNetwork { /** - * Apply a single layer's permutation (as implied by {@link #setPermutation(int[])}) - * @param values values output by previous layer - * @param layer layer to apply (layer is between 1 and numLayers; layer 0 is the input layer) - * @param type of values. + * Returns true iff the switch is crossed + * @param layer + * @return */ - void permuteLayer(T[] values, int layer); + boolean isCrossed(int layer, int switchIdx); - void permuteLayer(ArrayList values, int layer); } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java b/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java index 85482ce..537fae2 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java @@ -7,7 +7,7 @@ import java.util.Random; /** * Created by Tzlil on 12/17/2015. * container for random permutation - * the permutation is sated in constructor and can't be change + * the permutation is set in the constructor and can't be changed */ public class RandomPermutation { public final int[] permutation; @@ -43,4 +43,19 @@ public class RandomPermutation { return result; } + + + /** + * randomly shuffle an array of elements in-place (using Fisher-Yates) + * @param perm array of elements to shuffle. + * @param random + */ + public static void permute(T[] perm, Random random){ + for (int i = perm.length - 1; i > 0; --i) { + int j = random.nextInt(i+1); + T tmp = perm[i]; + perm[i] = perm[j]; + perm[j] = tmp; + } + } } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Util.java b/mixer/src/main/java/meerkat/mixer/mixing/Util.java new file mode 100644 index 0000000..26437ae --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/mixing/Util.java @@ -0,0 +1,45 @@ +package meerkat.mixer.mixing; + +import java.util.ArrayList; + +/** + * Generic utilities + */ +public class Util { + /* + * Apply a single layer's switch permutations in place (as implied by {@link PermutationNetwork#setPermutation(int[])}) + * @param values values output by previous layxer + * @param layer layer to apply (layer is between 1 and numLayers; layer 0 is the input layer) + * @param type of values. + */ + public static void applyLayerSwitches(PermutationNetwork net, T[] values, int layer) { + int numSwitches = net.getNumInputs() >>> 1; + for (int i = 0; i < numSwitches; ++i) { + if (net.isCrossed(layer, i)) { + T tmp = values[i * 2]; + values[i * 2] = values[i * 2 + 1]; + values[i * 2 + 1] = tmp; + } + } + } + + + public static void convertOutputPermToInputPerm(PermutationNetwork net, T[] oldValues, T[] newValues, int layer) { + int numInputs = net.getNumInputs(); + assert(numInputs == oldValues.length); + assert(numInputs == newValues.length); + + for (int i = 0; i < numInputs; ++i) { + newValues[i] = oldValues[net.getOutputIdxInPreviousLayer(layer, i)]; + } + } + + + public static void permute(PermutationNetwork net, T[] oldValues, T[] newValues) { + for (int layer = 0; layer < net.getNumLayers(); ++layer) { + convertOutputPermToInputPerm(net, oldValues, newValues, layer); + applyLayerSwitches(net, newValues, layer); + System.arraycopy(newValues, 0, oldValues, 0, oldValues.length); + } + } +} diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index 87eb4e8..df5b8aa 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -45,7 +45,7 @@ public class MixingTest extends ECParamTestBase { mixer = new Mixer(prover, enc); // generate n - int logN = 8; // + random.nextInt(8) + int logN = 9; // + random.nextInt(8) layers = 2*logN - 1; n = 1 << logN; } diff --git a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java index 1f6be55..7a64f58 100644 --- a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java +++ b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java @@ -1,15 +1,20 @@ package meerkat.mixer.mixing; +import org.junit.Test; + +import java.util.Set; +import java.util.TreeSet; + import static org.junit.Assert.*; /** * Tests for Benes Network topology */ -public class BenesNetworkTest { - public static class Permutation { +public class BenesNetworkTest extends PermutationNetworkTest { + final static int logN = 3; + @Override + protected PermutationNetwork getNewNetwork() { + return new BenesNetwork(logN); } - - public static isAPerm - } \ No newline at end of file diff --git a/mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java b/mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java new file mode 100644 index 0000000..2c3aa25 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java @@ -0,0 +1,109 @@ +package meerkat.mixer.mixing; + +import org.junit.Before; +import org.junit.Test; + +import java.util.Random; +import java.util.Set; +import java.util.TreeSet; + +import static org.junit.Assert.assertArrayEquals; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +/** + * Generically Test a permutation network + */ +abstract public class PermutationNetworkTest { + + public static final int NUM_REPS = 10; + Random rand; + + abstract protected PermutationNetwork getNewNetwork(); + + PermutationNetwork network; + + @Before + public void setup() { + network = getNewNetwork(); + rand = new Random(1); + } + + public static Set getSequenceSet(int N) { + Set set = new TreeSet<>(); + + for (int i = 0; i < N; ++i) { + set.add(i); + } + return set; + } + + public static Integer[] getSequenceArray(int N) { + Integer[] arr = new Integer[N]; + + for (int i = 0; i < N; ++i) { + arr[i] = i; + } + return arr; + } + + + /** + * Check if a given network is actually a permutation network (i.e., always + * implies a permutation regardless of 2x2 switch settings). + */ + @Test + public void isAlwaysAPermutation() { + int numLayers = network.getNumLayers(); + int N = network.getNumInputs(); + + for (int layer = 1; layer < numLayers; ++layer) { + Set unusedInputs = getSequenceSet(N); + for (int i = 0; i < N; ++i) { + unusedInputs.remove(network.getOutputIdxInPreviousLayer(layer, i)); + } + assertTrue("Not a permutation! Didn't use: " + unusedInputs, unusedInputs.isEmpty()); + } + } + + @Test + public void forwardEqualsBackwards() { + int numLayers = network.getNumLayers(); + int N = network.getNumInputs(); + + for (int layer = 1; layer < numLayers; ++layer) { + for (int i = 0; i < N; ++i) { + int j = network.getOutputIdxInPreviousLayer(layer, i); + assertEquals(String.format("Input %d in layer %d has problems", i, layer), i, + network.getInputIdxInNextLayer(layer - 1, j)); + } + } + } + + public static int[] convert(Integer[] in) { + int[] out = new int[in.length]; + for (int i = 0; i < in.length; ++i) + out[i] = in[i]; + + return out; + } + + @Test + public void testRandomPermutations() throws Exception { + for (int rep = 0; rep < NUM_REPS; ++rep) { + Integer[] target = getSequenceArray(network.getNumInputs()); + RandomPermutation.permute(target, rand); + + network.setPermutation(convert(target)); + + Integer[] id = getSequenceArray(network.getNumInputs()); + + Integer[] out = new Integer[target.length]; + + Util.permute(network, id, out); + + assertArrayEquals("Permutation mismatch: " + target + " != " + out, target, out); + + } + } +} From 78f823f31e74323f10d5fc6a0618e42d1d2d04d7 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Thu, 19 Jan 2017 01:18:21 +0200 Subject: [PATCH 13/25] new benes code passes tests --- .../src/main/java/meerkat/mixer/mixing/BenesNetwork.java | 8 ++++---- .../test/java/meerkat/mixer/mixing/BenesNetworkTest.java | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java index 10cc45e..fc0e37a 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java @@ -40,7 +40,7 @@ public class BenesNetwork implements PermutationNetwork */ public static int getOutputIdxInPreviousLayer(int logN, int layer, int inputIdx) { assert (layer >= 0) && (layer < 2*logN - 1); - assert (inputIdx >= 0) && (inputIdx < 1 << inputIdx); + assert (inputIdx >= 0) && (inputIdx < 1 << logN); if ((layer == 0) || (inputIdx & 1) == 0) { // layer 0 inputs and all even inputs @@ -145,7 +145,7 @@ public class BenesNetwork implements PermutationNetwork /** * Where the set of switches for this level and index actually starts in switchValues */ - int blockStart = idx << level; + int blockStart = idx << (logN - level - 1); int numSwitches = 1 << (logN - level - 1); while (!unmatchedIndices.isEmpty()) { @@ -189,11 +189,11 @@ public class BenesNetwork implements PermutationNetwork if ((((j & 1) == 0) && (jSwitchNum < numSwitches / 2)) || ((j & 1) == 1) && (jSwitchNum >= numSwitches / 2)) { // Even output in the upper half, or odd output in the lower half // so switch needs to be "straight" to get j to the upper half - switchValues[level][blockStart + switchNum] = false; + switchValues[level][blockStart + jSwitchNum] = false; jSwitched = j; } else { // Otherwise switch needs to be "crossed" to get j to upper half - switchValues[level][blockStart + switchNum] = true; + switchValues[level][blockStart + jSwitchNum] = true; jSwitched = j ^ 1; } diff --git a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java index 7a64f58..3114e9e 100644 --- a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java +++ b/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java @@ -11,7 +11,7 @@ import static org.junit.Assert.*; * Tests for Benes Network topology */ public class BenesNetworkTest extends PermutationNetworkTest { - final static int logN = 3; + final static int logN = 8; @Override protected PermutationNetwork getNewNetwork() { From fc2c26d7e9af4e617cce659976f6de0dd3740001 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Thu, 19 Jan 2017 11:08:07 +0200 Subject: [PATCH 14/25] Refactoring (tests currently fail) --- .../mixnet/Mix2ZeroKnowledgeProver.java | 20 -- .../mixnet/Mix2ZeroKnowledgeProver.java | 20 ++ .../mixnet/Mix2ZeroKnowledgeVerifier.java | 0 .../java/meerkat/crypto/mixnet/Mixer.java | 0 .../meerkat/crypto/mixnet/MixerOutput.java | 3 +- .../java/meerkat/crypto/mixnet/Trustee.java | 0 .../java/meerkat/crypto/mixnet/Verifier.java | 0 .../meerkat/mixer/main/BatchConverter.java | 47 +--- .../java/meerkat/mixer/main/BatchHandler.java | 13 +- .../java/meerkat/mixer/main/MainMixing.java | 13 +- .../java/meerkat/mixer/mixing/MixNetwork.java | 214 ------------------ .../main/java/meerkat/mixer/mixing/Mixer.java | 107 +++++---- .../meerkat/mixer/mixing/MixerOutput.java | 102 +++++---- .../meerkat/mixer/proofs/DlogConjunction.java | 39 ++++ .../mixer/proofs/ECElGamalMixProtocols.java | 184 --------------- ...va => ECElGamalMixStatementGenerator.java} | 15 +- .../main/java/meerkat/mixer/proofs/Mix2.java | 46 ++++ .../java/meerkat/mixer/proofs/Prover.java | 190 +--------------- .../mixer/proofs/SchnorrDlogEquivalence.java | 123 ++++++++++ .../meerkat/mixer/proofs/SigmaProtocol.java | 12 - .../mixer/proofs/SigmaProtocolAnd2.java | 6 - .../mixer/proofs/SigmaProtocolOr2.java | 6 - .../java/meerkat/mixer/proofs/Verifier.java | 13 +- .../meerkat/mixer/proofs/VerifyTable.java | 51 ++--- .../src/main/proto/meerkat/mixing.proto | 19 +- .../java/meerkat/mixer/CreateTestVector.java | 200 ++++++++-------- .../java/meerkat/mixer/Mix2ProofTest.java | 2 +- .../java/meerkat/mixer/MixNetworkTest.java | 46 ---- .../test/java/meerkat/mixer/MixingTest.java | 4 +- .../proofs/DlogAndStatementSigmaTest.java | 14 +- .../proofs/DlogOrStatementSigmaTest.java | 42 ++-- .../proofs/DlogStatementSchnorrSigmaTest.java | 56 ++--- .../meerkat/mixer/proofs/DummySigmaProof.java | 10 - .../java/profiling/ZeroKnowledgeProof.java | 2 +- 34 files changed, 584 insertions(+), 1035 deletions(-) delete mode 100644 meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java create mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java rename {meerkat-common => mixer}/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java (100%) rename {meerkat-common => mixer}/src/main/java/meerkat/crypto/mixnet/Mixer.java (100%) rename {meerkat-common => mixer}/src/main/java/meerkat/crypto/mixnet/MixerOutput.java (83%) rename {meerkat-common => mixer}/src/main/java/meerkat/crypto/mixnet/Trustee.java (100%) rename {meerkat-common => mixer}/src/main/java/meerkat/crypto/mixnet/Verifier.java (100%) delete mode 100644 mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java delete mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java rename mixer/src/main/java/meerkat/mixer/proofs/{ECElGamalMixParams.java => ECElGamalMixStatementGenerator.java} (96%) create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/Mix2.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java rename {meerkat-common => mixer}/src/main/proto/meerkat/mixing.proto (70%) delete mode 100644 mixer/src/test/java/meerkat/mixer/MixNetworkTest.java diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java b/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java deleted file mode 100644 index 70f611f..0000000 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java +++ /dev/null @@ -1,20 +0,0 @@ -package meerkat.crypto.mixnet; - -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; - -/** - * Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts. - */ -public interface Mix2ZeroKnowledgeProver { - public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1, - Crypto.RerandomizableEncryptedMessage in2, - Crypto.RerandomizableEncryptedMessage out1, - Crypto.RerandomizableEncryptedMessage out2, - boolean switched,int i,int j, int layer, // switch info - Crypto.EncryptionRandomness r1, - Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException; - - -} diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java new file mode 100644 index 0000000..3a11c0e --- /dev/null +++ b/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java @@ -0,0 +1,20 @@ +package meerkat.crypto.mixnet; + +import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; + +/** + * Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts. + */ +public interface Mix2ZeroKnowledgeProver { + public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1, + Crypto.RerandomizableEncryptedMessage in2, + Crypto.RerandomizableEncryptedMessage out1, + Crypto.RerandomizableEncryptedMessage out2, + boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx, // switch info + Crypto.EncryptionRandomness r1, + Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException; + + +} diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java similarity index 100% rename from meerkat-common/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java rename to mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java similarity index 100% rename from meerkat-common/src/main/java/meerkat/crypto/mixnet/Mixer.java rename to mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java b/mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java similarity index 83% rename from meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java rename to mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java index 1de10f5..770dc92 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/mixnet/MixerOutput.java +++ b/mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java @@ -9,5 +9,6 @@ import meerkat.protobuf.Mixing; public interface MixerOutput { public Mixing.Mix2Proof[][] getProofs(); public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages(); - public int getN(); + public int getLogN(); + public int getNumLayers(); } diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Trustee.java b/mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java similarity index 100% rename from meerkat-common/src/main/java/meerkat/crypto/mixnet/Trustee.java rename to mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java diff --git a/meerkat-common/src/main/java/meerkat/crypto/mixnet/Verifier.java b/mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java similarity index 100% rename from meerkat-common/src/main/java/meerkat/crypto/mixnet/Verifier.java rename to mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java index ea3580d..b61c4c5 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java @@ -15,37 +15,6 @@ import java.util.List; * provide convert operation from batch data to meerkat.mixer.mixing output and backwards */ public class BatchConverter { - - private final int n,layers; - - /** - * constructor - * @param n - * @param layers - */ - public BatchConverter(int n,int layers){ - this.n = n; - this.layers = layers; - } - - /** - * convert integer to byte string - * @param a - * @return a as byte string - */ - private ByteString Integer2ByteString(int a){ - return ByteString.copyFrom(BigInteger.valueOf(a).toByteArray()); - } - - /** - * convert byte string to integer - * @param bs - * @return bs as int - */ - private int ByteString2Integer(ByteString bs) { - return Integer.valueOf(bs.toString()); - } - /** * convert meerkat.mixer.mixing output to batch data * @param mixerOutput @@ -55,8 +24,13 @@ public class BatchConverter { List result = new ArrayList(); + Mixing.MixBatchHeader header = Mixing.MixBatchHeader.newBuilder() + .setLogN(mixerOutput.getLogN()) + .setLayers(mixerOutput.getNumLayers()) + .build(); + result.add(BulletinBoardAPI.BatchChunk.newBuilder() - .setData(Integer2ByteString(n)) + .setData(header.toByteString()) .build()); for (Mixing.Mix2Proof[] zkpLayer : mixerOutput.getProofs()) { @@ -85,10 +59,11 @@ public class BatchConverter { public MixerOutput BatchChunkList2MixerOutput (List batchChunkList) throws Exception { - if (n != ByteString2Integer(batchChunkList.remove(0).getData())){ - throw new Exception(); - } + Mixing.MixBatchHeader header = Mixing.MixBatchHeader.parseFrom(batchChunkList.remove(0).getData()); + int logN = header.getLogN(); + int n = 1 << logN; + int layers = header.getLayers(); int nDiv2 = n >>1; Mixing.Mix2Proof[][] proofs = new Mixing.Mix2Proof[layers][nDiv2]; for (int layer = 0; layer < layers; layer++) @@ -110,7 +85,7 @@ public class BatchConverter { } } - return new meerkat.mixer.mixing.MixerOutput(n,layers,proofs,encryptions); + return new meerkat.mixer.mixing.MixerOutput(logN, proofs,encryptions); } diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java index 28892fa..c9d72d9 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java @@ -21,19 +21,14 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback batchHandlers = new ArrayList(prevBatchIds.size()); BatchHandler currentBatchHandler; for (Integer prevBatchId : prevBatchIds) { - currentBatchHandler = new BatchHandler(n, layers,verifier); + currentBatchHandler = new BatchHandler(verifier); asyncBulletinBoardClient.readBatch(id, prevBatchId,currentBatchHandler); batchHandlers.add(currentBatchHandler); } @@ -99,7 +94,7 @@ public class MainMixing { private void updateBB(MixerOutput mixerOutput , int batchId, AsyncBulletinBoardClient.ClientCallback callback) { - BatchConverter batchConverter = new BatchConverter(n,layers); + BatchConverter batchConverter = new BatchConverter(); List batchChunkList = batchConverter.MixerOutput2BatchChunk(mixerOutput); asyncBulletinBoardClient.postBatch(id, batchId, batchChunkList, callback); } diff --git a/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java deleted file mode 100644 index 99f041e..0000000 --- a/mixer/src/main/java/meerkat/mixer/mixing/MixNetwork.java +++ /dev/null @@ -1,214 +0,0 @@ -package meerkat.mixer.mixing; - -import java.util.ArrayList; -import java.util.List; -import java.util.Queue; -import java.util.concurrent.ArrayBlockingQueue; - -/** - * Created by Tzlil on 12/15/2015. - * contains benes mix network. - * the network is generated in the constructor and can't be change - */ -public class MixNetwork { - - private final Switch[][] switches; - - /** - * constructor - * @param randomPermutation - */ - public MixNetwork(RandomPermutation randomPermutation) { - this.switches = generateSwitchesValue(randomPermutation.permutation); - } - - /** - * implements Benes mix network algorithm - * @param permutation - random permutation - * @return switches - */ - private Switch[][] generateSwitchesValue(int[] permutation){ - int n = permutation.length; - assert ((n & n-1) == 0); //n == 2^k - int layers = numberOfLayers(n); - - int[] pi, piL, piR; - Queue permutationsQueue = new ArrayBlockingQueue(n); - Graph graph; - int iDiv2; - int nDiv2 = n >> 1; - Switch[][] switches = new Switch[layers][nDiv2]; - int index1,index2; - - permutationsQueue.add(permutation); - for (int i = n, layer = 0; i > 1; i >>= 1, layer++) // i == permutation size - { - iDiv2 = i >> 1; - for (int j = 0; j < nDiv2; j += iDiv2) // j == permutation start index - { - pi = permutationsQueue.remove(); - graph = new Graph(pi); - piL = new int[iDiv2]; - piR = new int[iDiv2]; - for (int k = 0; k < iDiv2; k++){ // k == switch index in permutation j - - index1 = k + (j << 1); - index2 = index1 + iDiv2; - switches[layers - layer - 1][k + j] = new Switch(index1,index2,layers - layer - 1,graph.getSwitchValue(k, true)); - switches[layer][k + j] = new Switch(index1,index2,layer,graph.getSwitchValue(k, false)); - - if (!switches[layers - layer - 1][k + j].value) { - piL[k] = pi[k] % iDiv2; - piR[k] = pi[k + iDiv2] % iDiv2; - } else { - piL[k] = pi[k + iDiv2] % iDiv2; - piR[k] = pi[k] % iDiv2; - } - } - permutationsQueue.add(piL); - permutationsQueue.add(piR); - } - } - return switches; - } - - /** - * getter for switches value at layer - * @param layer - * @return switches[layer] - */ - public Switch[] getSwitchesByLayer(int layer) - { - return switches[layer]; - } - - /** - * calc number of layers for n values - * @param n number of votes - * @return layers - */ - public static int numberOfLayers(int n){ - return (int) (2 * Math.log(n) / Math.log(2)) - 1; - } - - /** - * inner class - * graph object, part of benes mix network algorithm - */ - private class Graph { - private int n; - private int nDiv2; - private Node[][] nodes; - protected Graph(int[] permutation){ - n = permutation.length; // n = 2^k - nDiv2 = n >> 1; - createNodes(); - createEdges(permutation); - setSwitches(); - } - - /** - * provide an access to algorithm result - * index must be less then n/2 - */ - protected boolean getSwitchValue(int index,boolean up) { - return up ? nodes[0][index].value : nodes[1][index].value; - } - - - - - - - /** - * create two lines of nodes size n/2 each - * the value of the i th node is (i,i+n/2) if i < n /2 (first line) - * otherwise its value is (i - n/2 , i) (second line) - */ - private void createNodes() { - nodes = new Node[2][nDiv2]; - for (int i = 0; i < nDiv2; i++) { - nodes[0][i] = new Node(); - nodes[1][i] = new Node(); - } - } - - /** create an edge between each pair of nodes i,j from different lines (i index of the first line) - * if exists k in i th node's value and t in j th node's value - * s.t permutation[k] == t - * the edge is broken if (k < n/2 and t >= n/2) or (k >= n/2 and t < n/2) - * Note: in purpose to avoid edge cases, each node has exactly two edges - */ - private void createEdges(int[] permutation) { - int j; - for (int i = 0; i < nDiv2; i++) { - j = permutation[i] % nDiv2; - nodes[0][i].edges.add(new Edge(nodes[1][j], (permutation[i] >= nDiv2))); - nodes[1][j].edges.add(new Edge(nodes[0][i], (permutation[i] >= nDiv2))); - - j = permutation[i + nDiv2] % nDiv2; - nodes[0][i].edges.add(new Edge(nodes[1][j], (permutation[i + nDiv2] < nDiv2))); - nodes[1][j].edges.add(new Edge(nodes[0][i], (permutation[i + nDiv2] < nDiv2))); - } - } - - /** - * set switch's value (on/off) for each switch (node) - * s.t if nodes i,j connected by edge e, i th switch's value - * must be equal to j's if e is broken or not equal if e is not broken - */ - private void setSwitches() { - Node node; - boolean v; - Edge e0,e1; - // iterate over first line of nodes - for (int i = 0; i < nDiv2; i++) { - node = nodes[0][i]; - if (node.set) - continue; - //select default value for first node in connected component - v = false; - // set value to all reachable nodes from node - while (true) { - node.set = true; - node.value = v; - e0 = node.edges.get(0); e1 = node.edges.get(1); - if (e0.neighbor.set && e1.neighbor.set) - break; - v ^= (!e0.neighbor.set) ? e0.broken : e1.broken; - node = (!e0.neighbor.set) ? e0.neighbor : e1.neighbor; - } - } - } - - /** - * inner class - * node object in graph - * there are exactly twp edges for each node - */ - private class Node { - public List edges; - private boolean value; - private boolean set; - public Node() { - edges = new ArrayList(2); - set = false; - } - } - - /** - * inner class - * edge object in graph - */ - private class Edge { - public Node neighbor; - public boolean broken; - public Edge(Node neighbor, boolean broken) { - this.neighbor = neighbor; - this.broken = broken; - } - } - } - - -} diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java index a304e2f..0b6e184 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java @@ -80,89 +80,96 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { /** * generate new random mix network - * @param n number of votes + * @param logN log number of votes * @param random * @return new random mix network */ - private MixNetwork generateMixNetwork(int n,Random random){ - return new MixNetwork(new RandomPermutation(n,random)); + private PermutationNetwork generateMixNetwork(int logN, Random random){ + BenesNetwork net = new BenesNetwork(logN); + RandomPermutation perm = new RandomPermutation(1 << logN, random); + net.setPermutation(perm.permutation); + return net; } + /** - * fills the encryption table with rerandomize encrypted votes. - * @param layers + * fills the encryption table with rerandomized encrypted votes. * @param mixNetwork switches table (boolean values) * @param encryptionTable an initialized encryption table s.t first layer == given encrypted votes * @param randomnesses an initialized randomness table of size layers * n, use for rerandomize operations * @throws InvalidProtocolBufferException */ - private void rerandomize(int layers,MixNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable + private void rerandomize(PermutationNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable ,EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { Switch[] switchesLayer; int index1,index2; - RerandomizableEncryptedMessage e1,e2; + RerandomizableEncryptedMessage a,b; EncryptionRandomness r1,r2; - for (int layer = 0; layer < layers; layer++) - { - switchesLayer = mixNetwork.getSwitchesByLayer(layer); - for (Switch sw : switchesLayer) { - index1 = sw.i; - index2 = sw.j; - e1 = encryptionTable[layer][index1]; - e2 = encryptionTable[layer][index2]; + int layers = mixNetwork.getNumLayers(); - r1 = randomnesses[layer][index1]; - r2 = randomnesses[layer][index2]; - if (!sw.value) { - encryptionTable[layer + 1][index1] = encryptor.rerandomize(e1, r1); - encryptionTable[layer + 1][index2] = encryptor.rerandomize(e2, r2); + int numSwitches = mixNetwork.getNumInputs() >>> 1; + for (int layer = 0; layer < layers; layer++) { + for (int switchIdx = 0; switchIdx < numSwitches; ++switchIdx) { + boolean isCrossed = mixNetwork.isCrossed(layer, switchIdx); + + int out0 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx); + int out1 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx + 1); + + r1 = randomnesses[layer][2 * switchIdx]; + r2 = randomnesses[layer][2 * switchIdx + 1]; + + a = encryptionTable[layer][2 * switchIdx]; + b = encryptionTable[layer][2 * switchIdx + 1]; + + if (isCrossed) { + encryptionTable[layer + 1][out0] = encryptor.rerandomize(b, r2); + encryptionTable[layer + 1][out1] = encryptor.rerandomize(a, r1); } else { - encryptionTable[layer + 1][index1] = encryptor.rerandomize(e2, r2); - encryptionTable[layer + 1][index2] = encryptor.rerandomize(e1, r1); + encryptionTable[layer + 1][out0] = encryptor.rerandomize(a, r1); + encryptionTable[layer + 1][out1] = encryptor.rerandomize(b, r2); } + } } } /** * generate zero knowledge proof for each rerandomize encrypted votes couple in encryptionTable - * @param n number of votes - * @param layers * @param mixNetwork switches table (boolean values) used for set encryption table * @param encryptionTable full encryption table * @param randomnesses randomness table of size layers * n, used for set encryption table * @return zero knowledge proofs table * @throws InvalidProtocolBufferException */ - private Mix2Proof[][] generateMix2ProofTable(int n, int layers, MixNetwork mixNetwork + private Mix2Proof[][] generateMix2ProofTable(PermutationNetwork mixNetwork , RerandomizableEncryptedMessage[][] encryptionTable , EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { + int layers = mixNetwork.getNumLayers(); + int n = mixNetwork.getNumInputs(); Switch[] switchesLayer; int index1,index2; int switchIndex = 0; - int nDiv2 = n >> 1; - Mix2Proof[][] proofsTable = new Mix2Proof[layers][nDiv2]; + int numSwitches = n >> 1; + Mix2Proof[][] proofsTable = new Mix2Proof[layers][numSwitches]; - RerandomizableEncryptedMessage e1,e2; + RerandomizableEncryptedMessage a,b,c,d; EncryptionRandomness r1,r2; - for (int layer = 0; layer < layers; layer++) - { - switchesLayer = mixNetwork.getSwitchesByLayer(layer); - for (Switch sw : switchesLayer) { - index1 = sw.i; - index2 = sw.j; - e1 = encryptionTable[layer][index1]; - e2 = encryptionTable[layer][index2]; - r1 = randomnesses[layer][index1]; - r2 = randomnesses[layer][index2]; + for (int layer = 0; layer < layers; layer++) { + for (int switchIdx = 0; switchIdx < numSwitches; ++switchIdx) { + boolean isCrossed = mixNetwork.isCrossed(layer, switchIdx); + int out0 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx); + int out1 = mixNetwork.getInputIdxInNextLayer(layer, 2 * switchIdx + 1); + + a = encryptionTable[layer][2 * switchIdx]; + b = encryptionTable[layer][2 * switchIdx + 1]; + c = encryptionTable[layer + 1][out0]; + d = encryptionTable[layer + 1][out1]; + r1 = randomnesses[layer][2 * switchIdx]; + r2 = randomnesses[layer][2 * switchIdx + 1]; proofsTable[layer][switchIndex] = - 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; + prover.prove(a, b, c, d, isCrossed, layer, switchIdx, out0, out1, r1, r2); } } return proofsTable; @@ -180,14 +187,18 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { int n = ciphertexts.size(); assert (n > 1 && isPowerOfTwo(n)); - int layers = MixNetwork.numberOfLayers(n); // layers = 2logn -1 + int logN = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 1; + + PermutationNetwork net = generateMixNetwork(logN,random); + + int layers = net.getNumLayers(); RerandomizableEncryptedMessage[][] encryptionTable = initializeEncryptionTable(n,layers,ciphertexts); EncryptionRandomness[][] randomnesses = generateRandomnessesForRerandomize(n,layers,random); - MixNetwork mixNetwork = generateMixNetwork(n,random); - rerandomize(layers,mixNetwork,encryptionTable,randomnesses); - Mix2Proof[][] proofsTable = generateMix2ProofTable(n,layers,mixNetwork,encryptionTable,randomnesses); - return new meerkat.mixer.mixing.MixerOutput(n,layers,proofsTable, encryptionTable); + rerandomize(net,encryptionTable,randomnesses); + Mix2Proof[][] proofsTable = generateMix2ProofTable(net,encryptionTable,randomnesses); + + return new meerkat.mixer.mixing.MixerOutput(logN, proofsTable, encryptionTable); } } \ No newline at end of file diff --git a/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java b/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java index eef60a4..146a13d 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java @@ -13,26 +13,23 @@ import java.io.IOException; * implements meerkat.crypto.mixnet.MixerOutput interface * container for meerkat.mixer.mixing.mix result. */ -public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ +public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput { private final Mixing.Mix2Proof[][] proofs; private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages; - private final int n; - private final int layers; + private final int logN; /** * constructor - * @param n number of votes - * @param layers + * @param logN log (base 2) of the number of votes * @param encryptedMessages at level 0 , contains the original encrypted votes * at each other level contains the re encrypted votes * @param proofs in each cell (level,switch) contains the match zero knowledge proof */ - public MixerOutput(int n,int layers,Mixing.Mix2Proof[][] proofs + public MixerOutput(int logN, Mixing.Mix2Proof[][] proofs , Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) { this.proofs = proofs; this.encryptedMessages = encryptedMessages; - this.n = n; - this.layers = layers; + this.logN = logN; } @@ -48,8 +45,13 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ } @Override - public int getN() { - return n; + public int getLogN() { + return logN; + } + + @Override + public int getNumLayers() { + return 2 * logN - 1; } /** @@ -57,33 +59,33 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ * @param dir - directory * @throws IOException */ - public void outToFolder(String dir) throws IOException { - - (new File(dir)).mkdirs(); - //create files - String proofsDir = dir + "/Proofs"; - String encDir = dir + "/EncryptedMessages"; - (new File(proofsDir)).mkdir(); - (new File(encDir)).mkdir(); - for (int layer = 0; layer < layers; layer++){ - (new File(proofsDir +"/layer" + layer )).mkdir(); - (new File(encDir +"/layer" + layer )).mkdir(); - } - (new File(encDir +"/input")).mkdir(); - - - for (int layer = 0; layer < layers; layer++){ - for(int i = 0; i < proofs[layer].length; i ++){ - writeProofToFile(proofsDir,proofs[layer][i]); - } - } - - for (int layer = 0; layer <= layers; layer++){ - for(int i = 0; i < encryptedMessages[layer].length; i ++){ - writeEncToFile(encDir,layer - 1, i,encryptedMessages[layer][i]); - } - } - } +// public void outToFolder(String dir) throws IOException { +// +// (new File(dir)).mkdirs(); +// //create files +// String proofsDir = dir + "/Proofs"; +// String encDir = dir + "/EncryptedMessages"; +// (new File(proofsDir)).mkdir(); +// (new File(encDir)).mkdir(); +// for (int layer = 0; layer < layers; layer++){ +// (new File(proofsDir +"/layer" + layer )).mkdir(); +// (new File(encDir +"/layer" + layer )).mkdir(); +// } +// (new File(encDir +"/input")).mkdir(); +// +// +// for (int layer = 0; layer < layers; layer++){ +// for(int i = 0; i < proofs[layer].length; i ++){ +// writeProofToFile(proofsDir,proofs[layer][i]); +// } +// } +// +// for (int layer = 0; layer <= layers; layer++){ +// for(int i = 0; i < encryptedMessages[layer].length; i ++){ +// writeEncToFile(encDir,layer - 1, i,encryptedMessages[layer][i]); +// } +// } +// } /** * create new file contains single proof @@ -91,19 +93,19 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput{ * @param proof * @throws IOException */ - private void writeProofToFile(String proofsDir, Mixing.Mix2Proof proof) throws IOException { - Mixing.Mix2Proof.Location location = proof.getLocation(); - int layer = location.getLayer(); - int i = location.getI(); - int j = location.getJ(); - String fileName = proofsDir+"/layer" + layer +"/" + i +"_" + j; - - File file = new File(fileName); - file.createNewFile(); - FileOutputStream fos = new FileOutputStream(file); - fos.write(proof.toByteArray()); - fos.close(); - } +// private void writeProofToFile(String proofsDir, Mixing.Mix2Proof proof) throws IOException { +// Mixing.Mix2Proof.Location location = proof.getLocation(); +// int layer = location.getLayer(); +// int i = location.getI(); +// int j = location.getJ(); +// String fileName = proofsDir+"/layer" + layer +"/" + i +"_" + j; +// +// File file = new File(fileName); +// file.createNewFile(); +// FileOutputStream fos = new FileOutputStream(file); +// fos.write(proof.toByteArray()); +// fos.close(); +// } /** * create new file contains single encrypted message diff --git a/mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java b/mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java new file mode 100644 index 0000000..57afa34 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java @@ -0,0 +1,39 @@ +package meerkat.mixer.proofs; + +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.protobuf.Mixing; + +import java.util.Random; + +/** + * Sigma protocol for plaintext equivalence of a pair of ciphertexts. + */ +public class DlogConjunction { + + public static class Prover + extends SigmaProtocolAnd2.Prover { + + public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement, + ECElGamalMixStatementGenerator.AndStatementWitness witness) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[0], witness.witnesses[0]), + new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[1], witness.witnesses[1])); + + } + } + + public static class Simulator extends SigmaProtocolAnd2.Simulator { + public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[0]), new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[1])); + } + } + + public static class Verifier + extends SigmaProtocolAnd2.Verifier { + + public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.AndStatement statement) { + super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, + new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[0]), new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[1])); + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java deleted file mode 100644 index f14ae3d..0000000 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixProtocols.java +++ /dev/null @@ -1,184 +0,0 @@ -package meerkat.mixer.proofs; - -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.concrete.Util; -import meerkat.protobuf.ConcreteCrypto.GroupElement; -import meerkat.protobuf.Mixing; -import meerkat.protobuf.Mixing.Mix2Proof.AndProof; -import meerkat.protobuf.Mixing.Mix2Proof.DlogProof; -import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.concrete.ECGroup; - -import java.math.BigInteger; -import java.util.Random; - -import static meerkat.protobuf.Mixing.Mix2Proof.DlogProof.*; - -/** - * Prover, Simulator and Verifier - */ -public class ECElGamalMixProtocols { - final ECElGamalMixParams params; - final ECGroup group; - final ECElGamalEncryption encryptor; - final ECPoint g; - final ECPoint h; - final Random rand; - - - final ChallengeGenerator challengeGenerator = new ChallengeGenerator(); - - public ECElGamalMixProtocols(ECElGamalMixParams params, Random rand) { - this.params = params; - this.rand = rand; - group = params.group; - encryptor = params.encryptor; - g = params.g; - h = params.h; - } - - public class ChallengeGenerator implements SigmaProtocolOr2.ChallengeGenerator { - @Override - public BigInteger generateChallenge() { return encryptor.generateRandomExponent(rand); } - - @Override - public BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { return c1.subtract(c2).mod(group.orderUpperBound()); } - } - - - public class DlogStatementSchnorrProver implements SigmaProtocol.Prover { - ECElGamalMixParams.DlogStatement statement; - ECElGamalMixParams.DlogStatementWitness witness; - - BigInteger r = null; - - public DlogStatementSchnorrProver(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { - this.statement = statement; - this.witness = witness; - } - - @Override - public FirstMessage getFirstMessage() { - r = encryptor.generateRandomExponent(rand); - ECPoint gr = group.multiply(statement.g, r); - ECPoint hr = group.multiply(statement.h, r); - - FirstMessage firstMessage = FirstMessage.newBuilder() - .setGr(encryptor.encodeElement(gr)) - .setHr(encryptor.encodeElement(hr)) - .build(); - - return firstMessage; - } - - @Override - public FinalMessage getFinalMessage(BigInteger challenge) { - return FinalMessage.newBuilder() - .setXcr(Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound()))) - .build(); - } - - @Override - public void reset() { r = null; } - } - - public class DlogStatementSchnorrVerifier implements SigmaProtocol.Verifier { - final ECElGamalMixParams.DlogStatement statement; - - public DlogStatementSchnorrVerifier(ECElGamalMixParams.DlogStatement statement) { - this.statement = statement; - } - - @Override - public boolean verify(FirstMessage firstMessage, BigInteger challenge, - FinalMessage finalMessage) { - GroupElement grEncoded = firstMessage.getGr(); - ECPoint gr = encryptor.decodeElement(grEncoded); - - GroupElement hrEncoded = firstMessage.getHr(); - ECPoint hr = encryptor.decodeElement(hrEncoded); - - BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); - - boolean gGood = group.add(gr, group.multiply(statement.a,challenge)).equals(group.multiply(statement.g,xcr)); - boolean hGood = group.add(hr, group.multiply(statement.b,challenge)).equals(group.multiply(statement.h,xcr)); - return gGood && hGood; - } - - } - - public class DlogStatementSchnorrSimulator implements SigmaProtocol.Simulator { - ECElGamalMixParams.DlogStatement statement; - BigInteger response = null; - - public DlogStatementSchnorrSimulator(ECElGamalMixParams.DlogStatement statement) { - this.statement = statement; - } - - @Override - public FirstMessage getFirstMessage(BigInteger challenge) { - response = encryptor.generateRandomExponent(rand); - - ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a,challenge)); - ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b,challenge)); - return FirstMessage.newBuilder() - .setGr(encryptor.encodeElement(u)) - .setHr(encryptor.encodeElement(v)) - .build(); - } - - @Override - public FinalMessage getFinalMessage() { - - return FinalMessage.newBuilder() - .setXcr(Util.encodeBigInteger(response)) - .build(); - } - - @Override - public void reset() { response = null; } - } - - /** - * Prover for plaintext equivalence of a pair of ciphertexts. - */ - public class AndStatementProver - extends SigmaProtocolAnd2.Prover { - public AndStatementProver(ECElGamalMixParams.AndStatement statement, - ECElGamalMixParams.AndStatementWitness witness) { - super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new DlogStatementSchnorrProver(statement.clauses[0], witness.witnesses[0]), - new DlogStatementSchnorrProver(statement.clauses[1], witness.witnesses[1])); - } - } - - public class AndStatementVerifier - extends SigmaProtocolAnd2.Verifier { - public AndStatementVerifier(ECElGamalMixParams.AndStatement statement) { - super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, - new DlogStatementSchnorrVerifier(statement.clauses[0]), new DlogStatementSchnorrVerifier(statement.clauses[1])); - } - } - - public class AndStatementSimulator extends SigmaProtocolAnd2.Simulator { - public AndStatementSimulator(ECElGamalMixParams.AndStatement statement) { - super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, - new DlogStatementSchnorrSimulator(statement.clauses[0]), new DlogStatementSchnorrSimulator(statement.clauses[1])); - } - } - - public class Mix2Prover extends SigmaProtocolOr2.Prover { - public Mix2Prover(ECElGamalMixParams.Mix2Statement statement, ECElGamalMixParams.Mix2StatementWitness witness) { - super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, - new AndStatementProver(statement.clauses[witness.trueClauseIndex], witness.witness), - new AndStatementSimulator(statement.clauses[1 - witness.trueClauseIndex]), - witness.trueClauseIndex); - } - } - - public class Mix2Verifier extends SigmaProtocolOr2.Verifier { - public Mix2Verifier(ECElGamalMixParams.Mix2Statement statement) { - super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, ECElGamalMixProtocols.this.challengeGenerator, - new AndStatementVerifier(statement.clauses[0]), new AndStatementVerifier(statement.clauses[1])); - } - } -} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java similarity index 96% rename from mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java rename to mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java index 273d435..8f43dff 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixParams.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java @@ -16,7 +16,7 @@ import java.math.BigInteger; * * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it */ -public class ECElGamalMixParams { +public class ECElGamalMixStatementGenerator { final ECElGamalEncryption encryptor; final ECGroup group; @@ -31,7 +31,7 @@ public class ECElGamalMixParams { * @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and * second base (h) are taken from the encryptor (second base is the public key) */ - public ECElGamalMixParams(ECElGamalEncryption encryptor){ + public ECElGamalMixStatementGenerator(ECElGamalEncryption encryptor){ this.encryptor = encryptor; this.group = encryptor.getGroup(); this.g = group.getGenerator(); @@ -40,11 +40,6 @@ public class ECElGamalMixParams { this.hEncoded = encryptor.encodeElement(h); } - public enum TrueCouple { - left, right, unknown - } - - /** * can be used by anyone, e.g meerkat.mixer.verifier * @@ -84,7 +79,7 @@ public class ECElGamalMixParams { * * The actual stored data is a cached representation for use in proofs and verification. This consists of the four substatements that are ORs of the DLOG equality. * - * A Mix2Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixParams (all constructors are private) + * A Mix2Statement can be constructed only by calling the {@link #createStatement} factory method on an instance of ECElGamalMixStatementGenerator (all constructors are private) * */ public class Mix2Statement { @@ -180,9 +175,9 @@ public class ECElGamalMixParams { DlogStatement(ECPoint a, ECPoint b) { - this.g = ECElGamalMixParams.this.g; + this.g = ECElGamalMixStatementGenerator.this.g; this.a = a; - this.h = ECElGamalMixParams.this.h; + this.h = ECElGamalMixStatementGenerator.this.h; this.b = b; } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java b/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java new file mode 100644 index 0000000..616b7fd --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java @@ -0,0 +1,46 @@ +package meerkat.mixer.proofs; + +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.protobuf.Mixing; +import org.factcenter.qilin.primitives.concrete.ECGroup; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Sigma protocol for proving correctness of a 2x2 switch + */ +public class Mix2 { + public static class ChallengeGenerator implements SigmaProtocolOr2.ChallengeGenerator { + ECElGamalEncryption encryptor; + ECGroup group; + Random rand; + + public ChallengeGenerator(ECElGamalEncryption encryptor, Random rand) { + this.encryptor = encryptor; + group = encryptor.getGroup(); + } + + @Override + public BigInteger generateChallenge() { return encryptor.generateRandomExponent(rand); } + + @Override + public BigInteger subtractChallenge(BigInteger c1, BigInteger c2) { return c1.subtract(c2).mod(group.orderUpperBound()); } + } + + public static class Prover extends SigmaProtocolOr2.Prover { + public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.Mix2Statement statement, ECElGamalMixStatementGenerator.Mix2StatementWitness witness) { + super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, rand), + new DlogConjunction.Prover(encryptor, rand, statement.clauses[witness.trueClauseIndex], witness.witness), + new DlogConjunction.Simulator(encryptor, rand, statement.clauses[1 - witness.trueClauseIndex]), + witness.trueClauseIndex); + } + } + + public static class Verifier extends SigmaProtocolOr2.Verifier { + public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.Mix2Statement statement) { + super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, null), + new DlogConjunction.Verifier(encryptor, statement.clauses[0]), new DlogConjunction.Verifier(encryptor, statement.clauses[1])); + } + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java index 9fd2662..2710f0c 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Prover.java @@ -2,7 +2,6 @@ package meerkat.mixer.proofs; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.concrete.Util; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -26,8 +25,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { private final ECElGamalEncryption encryptor; private final ECPoint g,h; private final BigInteger groupOrderUpperBound; - private final ECElGamalMixParams mixParams; - final ECElGamalMixProtocols mixProtocols; + private final ECElGamalMixStatementGenerator mixParams; final SigmaFiatShamir mix2NIZK; /** @@ -43,9 +41,8 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.group = this.encryptor.getGroup(); this.g = group.getGenerator(); this.h = this.encryptor.getElGamalPK().getPK(); - this.mixParams = new ECElGamalMixParams(encryptor); + this.mixParams = new ECElGamalMixStatementGenerator(encryptor); this.groupOrderUpperBound = group.orderUpperBound(); - this.mixProtocols = new ECElGamalMixProtocols(mixParams, rand); // We don't need randomness for the verifier this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); } @@ -55,8 +52,6 @@ public class Prover implements Mix2ZeroKnowledgeProver { * @param c - if switched then c = rerandomize(b,r2) else c = rerandomize(a,r1) * @param d - if switched then d = rerandomize(a,r1) else d = rerandomize(b,r2) * @param switched - trueClauseIndex - * @param i - column of a and c in encryption table - * @param j - column of b and d in encryption table * @param layer - row of a,b in encryption table * @param r1 * @param r2 @@ -67,186 +62,25 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.RerandomizableEncryptedMessage b, Crypto.RerandomizableEncryptedMessage c, Crypto.RerandomizableEncryptedMessage d, - boolean switched,int i,int j, int layer, + boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx, + Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { - ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(a,b,c,d); - ECElGamalMixParams.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); + ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(a, b, c, d); + ECElGamalMixStatementGenerator.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); - ECElGamalMixProtocols.Mix2Prover prover = mixProtocols.new Mix2Prover(statement, witness); + Mix2.Prover prover = new Mix2.Prover(encryptor, rand, statement, witness); Mixing.Mix2Proof.Location location = Mixing.Mix2Proof.Location.newBuilder() - .setI(i) - .setJ(j) - .setLayer(layer).build(); + .setLayer(layer) + .setSwitchIdx(switchIdx) + .setOut0(out0Idx) + .setOut1(out1Idx) + .build(); return mix2NIZK.generateNizk(prover).toBuilder().setLocation(location).build(); - -// Mixing.Mix2Proof first,second,third,fourth; -// -// ECElGamalMixParams.MixStatementWitness statement = mixParams.createProverStatement(a,b,c,d,r1,r2,switched); -// -// first = createOrProof(statement.getDlogStatement(0)); -// second = createOrProof(statement.getDlogStatement(1)); -// third = createOrProof(statement.getDlogStatement(2)); -// fourth = createOrProof(statement.getDlogStatement(3)); -// -// Mixing.ZeroKnowledgeProof.Location location = Mixing.ZeroKnowledgeProof.Location.newBuilder() -// .setI(i) -// .setJ(j) -// .setLayer(layer) -// .build(); -// -// Mixing.ZeroKnowledgeProof result = Mixing.ZeroKnowledgeProof.newBuilder() -// .setFirst(first) -// .setSecond(second) -// .setThird(third) -// .setFourth(fourth) -// .setLocation(location) -// .build(); -// return result; } -// -// -// Mixing.Mix2Proof.DlogProof.FirstMessage createDlogProof(ECElGamalMixParams.DlogStatement statement, ECElGamalMixParams.DlogStatementWitness witness) { -// -// BigInteger r = encryptor.generateRandomExponent(rand); -// ECPoint gr = group.multiply(statement.g, r); -// ECPoint hr = group.multiply(statement.h, r); -// -// Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() -// .setGr(group.encode(gr)) -// .setHr(group.encode(hr)) -// .build(); -// -// BigInteger challenge = Prover.hash() -// } -// -// -// -// -// /** -// * Generate a ZK proof that there exists x s.t (g ^ x == a and h ^ x == b) or (g' ^ x == a and h' ^ x == b). -// * -// * For each clause of the disjunction, we use the following sigma-protocol for DLOG equality (i.e. log_{g}(a)==log_{g}(b)): -// *
    -// *
  1. Prover chooses a random r, and sends g^r, h^r
  2. -// *
  3. Verifier chooses a random c and sends c
  4. -// *
  5. Prover computes
  6. -// *
-// * -// * -// * @param orStatement -// * @return ZKP OrProof: -// * assuming DLog is hard in this.group then that proves x is known for the meerkat.mixer.proofs -// */ -// private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ECElGamalMixParams.OrProverStatement orStatement) { -// -// ECPoint g1 = orStatement.g1; -// ECPoint h1 = orStatement.h1; -// ECPoint g2 = orStatement.g2; -// ECPoint h2 = orStatement.h2; -// -// ECPoint g1Tag = orStatement.g1Tag; -// ECPoint h1Tag = orStatement.h1Tag; -// ECPoint g2Tag = orStatement.g2Tag; -// ECPoint h2Tag = orStatement.h2Tag; -// -// // Randomness for the ZK proof -// BigInteger r = encryptor.generateRandomExponent(rand); -// -// -// BigInteger c1,c2,z,zTag; -// ECPoint u,v,uTag,vTag; -// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage firstMessage; -// -// -// switch (orStatement.trueClauseIndex) { -// case left: -// c2 = encryptor.generateRandomExponent(rand); -// zTag = encryptor.generateRandomExponent(rand); -// //step 1 -// 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 -// firstMessage = -// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() -// .setG1(orStatement.g1Encoded) -// .setH1(orStatement.h1Encoded) -// .setG2(orStatement.g2Encoded) -// .setH2(orStatement.h2Encoded) -// .setG1Tag(orStatement.g1TagEncoded) -// .setH1Tag(orStatement.h1TagEncoded) -// .setG2Tag(orStatement.g2TagEncoded) -// .setH2Tag(orStatement.h2TagEncoded) -// .setU(encryptor.encodeElement(u)) -// .setV(encryptor.encodeElement(v)) -// .setUTag(encryptor.encodeElement(uTag)) -// .setVTag(encryptor.encodeElement(vTag)) -// .build(); -// c1 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c2)).mod(groupOrderUpperBound); -// //step 3 -// //z = (r + c1 * x) % group size; -// z = r.add(c1.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); -// break; -// case right: -// c1 = encryptor.generateRandomExponent(rand); -// z = encryptor.generateRandomExponent(rand); -// //step 1 -// 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 -// firstMessage = -// Mixing.ZeroKnowledgeProof.OrProof.FirstMessage.newBuilder() -// .setG1(orStatement.g1Encoded) -// .setH1(orStatement.h1Encoded) -// .setG2(orStatement.g2Encoded) -// .setH2(orStatement.h2Encoded) -// .setG1Tag(orStatement.g1TagEncoded) -// .setH1Tag(orStatement.h1TagEncoded) -// .setG2Tag(orStatement.g2TagEncoded) -// .setH2Tag(orStatement.h2TagEncoded) -// .setU(encryptor.encodeElement(u)) -// .setV(encryptor.encodeElement(v)) -// .setUTag(encryptor.encodeElement(uTag)) -// .setVTag(encryptor.encodeElement(vTag)) -// .build(); -// c2 = hash(firstMessage,randomOracle).add(group.orderUpperBound().subtract(c1)).mod(groupOrderUpperBound); -// //step 3 -// //zTag = (r + c2 * x) % group size; -// zTag = r.add(c2.multiply(encryptor.extractRandomness(orStatement.x))).mod(groupOrderUpperBound); -// break; -// default: -// return null; -// } -// -// -// return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() -// .setG1(firstMessage.getG1()) -// .setH1(firstMessage.getH1()) -// .setG2(firstMessage.getG2()) -// .setH2(firstMessage.getH2()) -// .setG1Tag(firstMessage.getG1()) -// .setH1Tag(firstMessage.getH1Tag()) -// .setG2Tag(firstMessage.getG2Tag()) -// .setH2Tag(firstMessage.getH2Tag()) -// .setU(firstMessage.getU()) -// .setV(firstMessage.getV()) -// .setUTag(firstMessage.getUTag()) -// .setVTag(firstMessage.getVTag()) -// .setC1(Util.encodeBigInteger(c1)) -// .setC2(Util.encodeBigInteger(c2)) -// .setZ(Util.encodeBigInteger(z)) -// .setZTag(Util.encodeBigInteger(zTag)) -// .build(); -// } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java b/mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java new file mode 100644 index 0000000..49d615f --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java @@ -0,0 +1,123 @@ +package meerkat.mixer.proofs; + +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.Mixing; +import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.concrete.ECGroup; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Schnorr's ZK proof of Dlog equivlance + */ +public class SchnorrDlogEquivalence { + + public static class Verifier implements SigmaProtocol.Verifier { + ECElGamalEncryption encryptor; + ECGroup group; + final ECElGamalMixStatementGenerator.DlogStatement statement; + + public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.DlogStatement statement) { + this.encryptor = encryptor; + group = encryptor.getGroup(); + this.statement = statement; + } + + @Override + public boolean verify(Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage, BigInteger challenge, + Mixing.Mix2Proof.DlogProof.FinalMessage finalMessage) { + ConcreteCrypto.GroupElement grEncoded = firstMessage.getGr(); + ECPoint gr = encryptor.decodeElement(grEncoded); + + ConcreteCrypto.GroupElement hrEncoded = firstMessage.getHr(); + ECPoint hr = encryptor.decodeElement(hrEncoded); + + BigInteger xcr = Util.decodeBigInteger(finalMessage.getXcr()); + + boolean gGood = group.add(gr, group.multiply(statement.a, challenge)).equals(group.multiply(statement.g, xcr)); + boolean hGood = group.add(hr, group.multiply(statement.b, challenge)).equals(group.multiply(statement.h, xcr)); + return gGood && hGood; + } + + } + + public static class Simulator implements SigmaProtocol.Simulator { + ECElGamalEncryption encryptor; + ECGroup group; + Random rand; + + ECElGamalMixStatementGenerator.DlogStatement statement; + BigInteger response = null; + + public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.DlogStatement statement) { + this.encryptor = encryptor; + group = encryptor.getGroup(); + this.rand = rand; + this.statement = statement; + } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage(BigInteger challenge) { + response = encryptor.generateRandomExponent(rand); + + ECPoint u = group.multiply(statement.g, response).subtract(group.multiply(statement.a, challenge)); + ECPoint v = group.multiply(statement.h, response).subtract(group.multiply(statement.b, challenge)); + return Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + .setGr(encryptor.encodeElement(u)) + .setHr(encryptor.encodeElement(v)) + .build(); + } + + @Override + public Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage() { + + return Mixing.Mix2Proof.DlogProof.FinalMessage.newBuilder() + .setXcr(Util.encodeBigInteger(response)) + .build(); + } + } + + public static class Prover implements SigmaProtocol.Prover { + ECElGamalEncryption encryptor; + ECGroup group; + Random rand; + ECElGamalMixStatementGenerator.DlogStatement statement; + ECElGamalMixStatementGenerator.DlogStatementWitness witness; + + BigInteger r = null; + + public Prover(ECElGamalEncryption encryptor, Random rand, + ECElGamalMixStatementGenerator.DlogStatement statement, ECElGamalMixStatementGenerator.DlogStatementWitness witness) { + this.encryptor = encryptor; + group = encryptor.getGroup(); + this.rand = rand; + this.statement = statement; + this.witness = witness; + } + + @Override + public Mixing.Mix2Proof.DlogProof.FirstMessage getFirstMessage() { + r = encryptor.generateRandomExponent(rand); + ECPoint gr = group.multiply(statement.g, r); + ECPoint hr = group.multiply(statement.h, r); + + Mixing.Mix2Proof.DlogProof.FirstMessage firstMessage = Mixing.Mix2Proof.DlogProof.FirstMessage.newBuilder() + .setGr(encryptor.encodeElement(gr)) + .setHr(encryptor.encodeElement(hr)) + .build(); + + return firstMessage; + } + + @Override + public Mixing.Mix2Proof.DlogProof.FinalMessage getFinalMessage(BigInteger challenge) { + return Mixing.Mix2Proof.DlogProof.FinalMessage.newBuilder() + .setXcr(Util.encodeBigInteger(challenge.multiply(witness.x).add(r).mod(group.orderUpperBound()))) + .build(); + } + + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java index 6dbac42..d0640c5 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocol.java @@ -12,23 +12,11 @@ public interface SigmaProtocol { public interface Prover { public FirstMsgType getFirstMessage(); public FinalMessageType getFinalMessage(BigInteger challenge); - - /** - * Reset the prover (so the next calls to {@link #getFirstMessage()} will - * start a new proof. - */ - public void reset(); } public interface Simulator { public FirstMsgType getFirstMessage(BigInteger challenge); public FinalMessageType getFinalMessage(); - - /** - * Reset the prover (so the next calls to {@link #getFirstMessage(BigInteger)} will - * start a new proof. - */ - public void reset(); } public interface Verifier { diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java index d9e473b..31a0151 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java @@ -29,10 +29,6 @@ public class SigmaProtocolAnd2 { public FinalMessageOut getFinalMessage(BigInteger challenge) { return finalMessageConcatenator.concatenate(provers[0].getFinalMessage(challenge), provers[1].getFinalMessage(challenge)); } - - - @Override - public void reset() { provers[0].reset(); provers[1].reset(); } } static public class Verifier @@ -142,9 +139,6 @@ public class SigmaProtocolOr2 { public FinalMessageOut getFinalMessage() { return finalMessageConcatenator.concatenate(simChallenge0, simulators[0].getFinalMessage(), simulators[1].getFinalMessage()); } - - @Override - public void reset() { simulators[0].reset(); simulators[1].reset(); } } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java index 5cf98d9..0331cce 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java @@ -8,7 +8,6 @@ import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; -import meerkat.mixer.proofs.ECElGamalMixProtocols.Mix2Verifier; /** * implements Mix2ZeroKnowledgeVerifier @@ -16,11 +15,11 @@ import meerkat.mixer.proofs.ECElGamalMixProtocols.Mix2Verifier; public class Verifier implements Mix2ZeroKnowledgeVerifier { + private final ECElGamalEncryption encryptor; private final ECGroup group; private final RandomOracle randomOracle; private final ECPoint g,h; - private final ECElGamalMixParams mixParams; - final ECElGamalMixProtocols mixProtocols; + private final ECElGamalMixStatementGenerator mixParams; final SigmaFiatShamir mix2NIZK; @@ -32,12 +31,12 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { * @param randomOracle should be as the random oracle used by meerkat.mixer.proofs */ 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; - this.mixParams = new ECElGamalMixParams(encryptor); - this.mixProtocols = new ECElGamalMixProtocols(mixParams, null); // We don't need randomness for the verifier + this.mixParams = new ECElGamalMixStatementGenerator(encryptor); this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); // this.parser = new ZeroKnowledgeOrProofParser(group); } @@ -60,8 +59,8 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Crypto.RerandomizableEncryptedMessage out2, Mixing.Mix2Proof proof) throws InvalidProtocolBufferException { - ECElGamalMixParams.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); - Mix2Verifier verifier = mixProtocols.new Mix2Verifier(statement); + ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); + Mix2.Verifier verifier = new Mix2.Verifier(encryptor, statement); return mix2NIZK.verifyNizk(proof, verifier); } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java index 36d39ac..4d58fee 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java @@ -16,20 +16,17 @@ public final class VerifyTable { /** * constructor * @param verifier - * @param n * @param mixerOutput * @return true iff the meerkat.mixer.mixing output is valid * @throws InvalidProtocolBufferException */ - public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier,int n,MixerOutput mixerOutput) + public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier, MixerOutput mixerOutput) throws InvalidProtocolBufferException { - int index1,index2,layer; + int out0,out1,layer, switchIdx; - //assert n = 2^k - if ( (n &(n-1)) != 0) - throw new IllegalArgumentException("n"); - int layers = 2*(int)(Math.log(n) / Math.log(2)) - 1; + int layers = mixerOutput.getNumLayers(); + int n = 1 << mixerOutput.getLogN(); //initialize locationChecksum table // use for check BeneshNet validity boolean[][] locationChecksum = new boolean[layers][n]; @@ -44,36 +41,32 @@ public final class VerifyTable { for (int j = 0; j < Mix2Proofs[i].length ; j ++){ Mixing.Mix2Proof zkp = Mix2Proofs[i][j]; Mixing.Mix2Proof.Location location = zkp.getLocation(); - index1 = location.getI(); - index2 = location.getJ(); + out0 = location.getOut0(); + out1 = location.getOut1(); layer = location.getLayer(); + switchIdx = location.getSwitchIdx(); // check location validity - if (layer > layers >> 1) { - if (index2 - index1 != n >> (layers - layer)) - return false; - } - else{ - if (index2 - index1 != n >> (layer + 1)) - return false; - } + // TODO: add check +// if (layer > layers >> 1) { +// if (out1 - out0 != n >> (layers - layer)) +// return false; +// } +// else{ +// if (out1 - out0 != n >> (layer + 1)) +// return false; +// } // mark location in table - locationChecksum[layer][index1] = true; - locationChecksum[layer][index2] = true; + locationChecksum[layer][2 * switchIdx] = true; + locationChecksum[layer][2 * switchIdx + 1] = true; // verify proof - if(!verifier.verify(rerandomizableEncryptedMessages[layer][index1], - rerandomizableEncryptedMessages[layer][index2], - rerandomizableEncryptedMessages[layer + 1][index1], - rerandomizableEncryptedMessages[layer + 1][index2], + if(!verifier.verify(rerandomizableEncryptedMessages[layer][2 * switchIdx], + rerandomizableEncryptedMessages[layer][2 * switchIdx + 1], + rerandomizableEncryptedMessages[layer + 1][out0], + rerandomizableEncryptedMessages[layer + 1][out1], zkp)) { - - verifier.verify(rerandomizableEncryptedMessages[layer][index1], - rerandomizableEncryptedMessages[layer][index2], - rerandomizableEncryptedMessages[layer + 1][index1], - rerandomizableEncryptedMessages[layer + 1][index2], - zkp); return false; } } diff --git a/meerkat-common/src/main/proto/meerkat/mixing.proto b/mixer/src/main/proto/meerkat/mixing.proto similarity index 70% rename from meerkat-common/src/main/proto/meerkat/mixing.proto rename to mixer/src/main/proto/meerkat/mixing.proto index eebce4b..0755948 100644 --- a/meerkat-common/src/main/proto/meerkat/mixing.proto +++ b/mixer/src/main/proto/meerkat/mixing.proto @@ -7,6 +7,11 @@ option java_package = "meerkat.protobuf"; import 'meerkat/crypto.proto'; import 'meerkat/concrete_crypto.proto'; +message MixBatchHeader { + int32 logN = 1; // log (base 2) of number of inputs to mix + int32 layers = 2; // Number of layers in mix +} + message Plaintext { bytes data = 1; } @@ -44,13 +49,19 @@ message Mix2Proof { BigInteger c0 = 3; // Challenge for clause 0; challenge for clause 1 is computed from real challenge and c0 } - message Location{ - int32 i = 1; - int32 j = 2; - int32 layer = 3; + + // Location of the + message Location { + int32 layer = 1; // layer in which the switch is placed + int32 switchIdx = 2; // idx of the switch + int32 out0 = 3; // idx of the first output ciphertext (in layer+1 of the ciphertext matrix) + int32 out1 = 4; // idx of the second output ciphertext (in layer+1 of the ciphertext matrix) } + FirstMessage firstMessage = 1; FinalMessage finalMessage = 2; Location location = 5; } + + diff --git a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java index 1690aa5..0893a71 100644 --- a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java +++ b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java @@ -1,100 +1,100 @@ -package meerkat.mixer; - -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.mixer.mixing.Mixer; -import meerkat.mixer.mixing.MixerOutput; -import meerkat.mixer.proofs.Prover; -import meerkat.mixer.proofs.Verifier; -import meerkat.mixer.proofs.VerifyTable; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Voting; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; -import org.factcenter.qilin.primitives.concrete.ECElGamal; -import org.factcenter.qilin.primitives.concrete.ECGroup; -import org.junit.Before; - -import java.io.IOException; -import java.security.spec.InvalidKeySpecException; -import java.util.ArrayList; -import java.util.List; -import java.util.Random; - -/** - * Created by Tzlil on 1/19/2016. - */ -public class CreateTestVector { - - - ECElGamalEncryption encryptor; - ECGroup group; - Random random,randomMixer,randomProver; - RandomOracle randomOracle; - Mix2ZeroKnowledgeVerifier verifier; - Mix2ZeroKnowledgeProver prover; - meerkat.crypto.mixnet.Mixer mixer; - private int layers; - private int n; - - - @Before - public void setup() throws InvalidKeySpecException { - // initialization - random = new Random(); - group = new ECGroup("secp256k1"); - encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); - randomMixer = new Random(); - randomProver = new Random(); - randomOracle = new DigestOracle(); - verifier = new Verifier(encryptor,randomOracle); - prover = new Prover(randomProver,encryptor,randomOracle); - mixer = new Mixer(prover,encryptor); - - // generate n - int logN = 10; // + random.nextInt(8) - layers = 2*logN - 1; - n = 1 << logN; - } - - public List generateMixerInput(){ - List result = new ArrayList(); - Voting.PlaintextBallot msg; - for (int i = 0; i < n ; i++){ - msg = Utils.genRandomBallot(2,3,16); - result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random))); - } - return result; - } - //@SimpleRerandomizeTest - public void createValidTest() throws IOException { - - List mixerInput = generateMixerInput(); - System.out.println("start mixing"); - MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer); - System.out.println("mixing ended, start verification"); - assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); - System.out.println("verification ended, start printing"); - mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3"); - System.out.println("all done"); - } - - //@SimpleRerandomizeTest - public void createInvalidTest() throws IOException { - - //Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(enc,randomOracle,true); - //Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,enc,randomOracle,true); - //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); - - List mixerInput = generateMixerInput(); - System.out.println("start mixing"); - MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random); - System.out.println("mixing ended, start negative verification"); - assert (!VerifyTable.verifyTable(verifier,n,mixerOutput)); - System.out.println("verification ended, start printing"); - mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5"); - System.out.println("all done"); - } -} +//package meerkat.mixer; +// +//import meerkat.crypto.concrete.ECElGamalEncryption; +//import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +//import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +//import meerkat.mixer.mixing.Mixer; +//import meerkat.mixer.mixing.MixerOutput; +//import meerkat.mixer.proofs.Prover; +//import meerkat.mixer.proofs.Verifier; +//import meerkat.mixer.proofs.VerifyTable; +//import meerkat.protobuf.Crypto; +//import meerkat.protobuf.Voting; +//import org.factcenter.qilin.primitives.RandomOracle; +//import org.factcenter.qilin.primitives.concrete.DigestOracle; +//import org.factcenter.qilin.primitives.concrete.ECElGamal; +//import org.factcenter.qilin.primitives.concrete.ECGroup; +//import org.junit.Before; +// +//import java.io.IOException; +//import java.security.spec.InvalidKeySpecException; +//import java.util.ArrayList; +//import java.util.List; +//import java.util.Random; +// +///** +// * Created by Tzlil on 1/19/2016. +// */ +//public class CreateTestVector { +// +// +// ECElGamalEncryption encryptor; +// ECGroup group; +// Random random,randomMixer,randomProver; +// RandomOracle randomOracle; +// Mix2ZeroKnowledgeVerifier verifier; +// Mix2ZeroKnowledgeProver prover; +// meerkat.crypto.mixnet.Mixer mixer; +// private int layers; +// private int n; +// +// +// @Before +// public void setup() throws InvalidKeySpecException { +// // initialization +// random = new Random(); +// group = new ECGroup("secp256k1"); +// encryptor = new ECElGamalEncryption(); +// encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); +// randomMixer = new Random(); +// randomProver = new Random(); +// randomOracle = new DigestOracle(); +// verifier = new Verifier(encryptor,randomOracle); +// prover = new Prover(randomProver,encryptor,randomOracle); +// mixer = new Mixer(prover,encryptor); +// +// // generate n +// int logN = 10; // + random.nextInt(8) +// layers = 2*logN - 1; +// n = 1 << logN; +// } +// +// public List generateMixerInput(){ +// List result = new ArrayList(); +// Voting.PlaintextBallot msg; +// for (int i = 0; i < n ; i++){ +// msg = Utils.genRandomBallot(2,3,16); +// result.add(encryptor.encrypt(msg, encryptor.generateRandomness(random))); +// } +// return result; +// } +// //@SimpleRerandomizeTest +// public void createValidTest() throws IOException { +// +// List mixerInput = generateMixerInput(); +// System.out.println("start mixing"); +// MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer); +// System.out.println("mixing ended, start verification"); +// assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); +// System.out.println("verification ended, start printing"); +// mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3"); +// System.out.println("all done"); +// } +// +// //@SimpleRerandomizeTest +// public void createInvalidTest() throws IOException { +// +// //Mix2ZeroKnowledgeVerifier corruptedVerifier = new Verifier(enc,randomOracle,true); +// //Mix2ZeroKnowledgeProver corruptedProver = new Prover(randomProver,enc,randomOracle,true); +// //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); +// +// List mixerInput = generateMixerInput(); +// System.out.println("start mixing"); +// MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random); +// System.out.println("mixing ended, start negative verification"); +// assert (!VerifyTable.verifyTable(verifier,n,mixerOutput)); +// System.out.println("verification ended, start printing"); +// mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5"); +// System.out.println("all done"); +// } +//} diff --git a/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java b/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java index aec3619..710b8fc 100644 --- a/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java @@ -77,7 +77,7 @@ public class Mix2ProofTest extends ECParamTestBase { group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2())))); - Mixing.Mix2Proof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2); + Mixing.Mix2Proof proof = prover.prove(e1,e2,e1New,e2New,false,0,0,0, 0, r1,r2); assertTrue (verifier.verify(e1,e2,e1New,e2New, proof)); } diff --git a/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java b/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java deleted file mode 100644 index 0245726..0000000 --- a/mixer/src/test/java/meerkat/mixer/MixNetworkTest.java +++ /dev/null @@ -1,46 +0,0 @@ -package meerkat.mixer; - -/** - * Created by Tzlil on 12/17/2015. - */ - -import meerkat.mixer.mixing.MixNetwork; -import meerkat.mixer.mixing.RandomPermutation; -import meerkat.mixer.mixing.Switch; -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(1); - int logn = 10; - 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)); - - } - -} diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index df5b8aa..693baee 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -45,7 +45,7 @@ public class MixingTest extends ECParamTestBase { mixer = new Mixer(prover, enc); // generate n - int logN = 9; // + random.nextInt(8) + int logN = 5; // + random.nextInt(8) layers = 2*logN - 1; n = 1 << logN; } @@ -76,7 +76,7 @@ public class MixingTest extends ECParamTestBase { System.out.println("start verification"); startTime = System.currentTimeMillis(); - assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); + assert (VerifyTable.verifyTable(verifier,mixerOutput)); finishTime = System.currentTimeMillis(); System.out.println(" that took: "+(finishTime-startTime)+ " ms"); diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java index 50c232a..562cac6 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java @@ -11,8 +11,8 @@ import java.math.BigInteger; public class DlogAndStatementSigmaTest extends SigmaProtocolTest { final DlogStatementSchnorrSigmaTest dlogtest; - ECElGamalMixParams.DlogStatement s1, s2; - ECElGamalMixParams.DlogStatementWitness w1, w2; + ECElGamalMixStatementGenerator.DlogStatement s1, s2; + ECElGamalMixStatementGenerator.DlogStatementWitness w1, w2; public DlogAndStatementSigmaTest() { this.dlogtest = new DlogStatementSchnorrSigmaTest(); @@ -20,10 +20,10 @@ public class DlogAndStatementSigmaTest extends SigmaProtocolTest s1w1 = dlogtest.returnRandomTrueStatement(); + Pair s1w1 = dlogtest.returnRandomTrueStatement(); s1 = s1w1.a; w1 = s1w1.b; - Pair s2w2 = dlogtest.returnRandomTrueStatement(); + Pair s2w2 = dlogtest.returnRandomTrueStatement(); s2 = s2w2.a; w2 = s2w2.b; } @@ -36,19 +36,19 @@ public class DlogAndStatementSigmaTest extends SigmaProtocolTest getNewProver() { return new SigmaProtocolAnd2.Prover<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, - dlogtest.prots.new DlogStatementSchnorrProver(s1, w1), dlogtest.prots.new DlogStatementSchnorrProver(s2, w2)); + new SchnorrDlogEquivalence.Prover(dlogtest.encryptor, rand, s1, w1), new SchnorrDlogEquivalence.Prover(dlogtest.encryptor, rand, s2, w2)); } @Override protected SigmaProtocol.Verifier getNewVerifier() { return new SigmaProtocolAnd2.Verifier<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, - dlogtest.prots.new DlogStatementSchnorrVerifier(s1), dlogtest.prots.new DlogStatementSchnorrVerifier(s2)); + new SchnorrDlogEquivalence.Verifier(dlogtest.encryptor, s1), new SchnorrDlogEquivalence.Verifier(dlogtest.encryptor, s2)); } @Override protected SigmaProtocol.Simulator getNewSimulator() { return new SigmaProtocolAnd2.Simulator<>(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, - dlogtest.prots.new DlogStatementSchnorrSimulator(s1), dlogtest.prots.new DlogStatementSchnorrSimulator(s2)); + new SchnorrDlogEquivalence.Simulator(dlogtest.encryptor, rand, s1), new SchnorrDlogEquivalence.Simulator(dlogtest.encryptor, rand, s2)); } @Override diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java index a352d42..d305b87 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java @@ -11,8 +11,8 @@ import java.math.BigInteger; public class DlogOrStatementSigmaTest extends SigmaProtocolTest { final DlogStatementSchnorrSigmaTest dlogtest; - final ECElGamalMixParams.AndStatement[] statements = new ECElGamalMixParams.AndStatement[2]; - ECElGamalMixParams.AndStatementWitness w; + final ECElGamalMixStatementGenerator.AndStatement[] statements = new ECElGamalMixStatementGenerator.AndStatement[2]; + ECElGamalMixStatementGenerator.AndStatementWitness w; int trueStatementIndex; @@ -23,53 +23,57 @@ public class DlogOrStatementSigmaTest extends SigmaProtocolTest s1w1 = dlogtest.returnRandomTrueStatement(); - Pair s2w2 = dlogtest.returnRandomTrueStatement(); - ECElGamalMixParams.AndStatement trueStatement = dlogtest.params.new AndStatement(s1w1.a, s2w2.a); - w = dlogtest.params.new AndStatementWitness(s1w1.b, s2w2.b); + Pair s1w1 = dlogtest.returnRandomTrueStatement(); + Pair s2w2 = dlogtest.returnRandomTrueStatement(); + ECElGamalMixStatementGenerator.AndStatement trueStatement = dlogtest.statementGenerator.new AndStatement(s1w1.a, s2w2.a); + w = dlogtest.statementGenerator.new AndStatementWitness(s1w1.b, s2w2.b); statements[trueStatementIndex] = trueStatement; - ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixParams.AndStatement falseStatement = dlogtest.params.new AndStatement(f1, f2); + ECElGamalMixStatementGenerator.AndStatement falseStatement = dlogtest.statementGenerator.new AndStatement(f1, f2); statements[1 - trueStatementIndex] = falseStatement; } @Override void generateRandomFalseStatement() { - ECElGamalMixParams.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixParams.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); - statements[0] = dlogtest.params.new AndStatement(f1, f2); + statements[0] = dlogtest.statementGenerator.new AndStatement(f1, f2); f1 = dlogtest.returnRandomFalseStatement(); f2 = dlogtest.returnRandomFalseStatement(); - statements[1] = dlogtest.params.new AndStatement(f1, f2); + statements[1] = dlogtest.statementGenerator.new AndStatement(f1, f2); } @Override protected SigmaProtocol.Prover getNewProver() { - SigmaProtocol.Prover andProver = dlogtest.prots.new AndStatementProver(statements[trueStatementIndex], w); - SigmaProtocol.Simulator andSimulator = dlogtest.prots.new AndStatementSimulator(statements[1 - trueStatementIndex]); + SigmaProtocol.Prover andProver = new DlogConjunction.Prover(dlogtest.encryptor, rand, statements[trueStatementIndex], w); + SigmaProtocol.Simulator andSimulator = new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1 - trueStatementIndex]); + Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand); return new SigmaProtocolOr2.Prover<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, - dlogtest.prots.challengeGenerator, andProver, andSimulator, trueStatementIndex); + gen, andProver, andSimulator, trueStatementIndex); } @Override protected SigmaProtocol.Verifier getNewVerifier() { + Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand); return new SigmaProtocolOr2.Verifier(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, - dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementVerifier(statements[0]), dlogtest.prots.new AndStatementVerifier(statements[1])); + gen, new DlogConjunction.Verifier(dlogtest.encryptor, statements[0]), new DlogConjunction.Verifier(dlogtest.encryptor, statements[1])); } @Override protected SigmaProtocol.Simulator getNewSimulator() { + + Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand); return new SigmaProtocolOr2.Simulator<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, - dlogtest.prots.challengeGenerator, dlogtest.prots.new AndStatementSimulator(statements[0]), - dlogtest.prots.new AndStatementSimulator(statements[1])); + gen, new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[0]), + new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1])); } @Override diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java index 868bce0..1da4e21 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java @@ -1,8 +1,10 @@ package meerkat.mixer.proofs; +import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.mixer.ECParamTestBase; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.concrete.ECGroup; import org.factcenter.qilin.util.Pair; import java.math.BigInteger; @@ -13,42 +15,44 @@ import java.math.BigInteger; public class DlogStatementSchnorrSigmaTest extends SigmaProtocolTest { - ECParamTestBase ecParams = new ECParamTestBase(); - ECElGamalMixParams params; - ECElGamalMixProtocols prots; + ECParamTestBase ecParams; + ECElGamalMixStatementGenerator statementGenerator; + ECElGamalEncryption encryptor; + ECGroup group; - ECElGamalMixParams.DlogStatement statement; - ECElGamalMixParams.DlogStatementWitness witness; - ECElGamalMixProtocols.DlogStatementSchnorrProver prover; - ECElGamalMixProtocols.DlogStatementSchnorrVerifier verifier; - ECElGamalMixProtocols.DlogStatementSchnorrSimulator simulator; + ECElGamalMixStatementGenerator.DlogStatement statement; + ECElGamalMixStatementGenerator.DlogStatementWitness witness; + SchnorrDlogEquivalence.Prover prover; + SchnorrDlogEquivalence.Verifier verifier; + SchnorrDlogEquivalence.Simulator simulator; public DlogStatementSchnorrSigmaTest() { - - this.params = new ECElGamalMixParams(ecParams.enc); - this.prots = new ECElGamalMixProtocols(params, rand); // We don't need randomness for the verifier + ecParams = new ECParamTestBase(); + encryptor = ecParams.enc; + group = encryptor.getGroup(); + this.statementGenerator = new ECElGamalMixStatementGenerator(ecParams.enc); } - Pair returnRandomTrueStatement() { - BigInteger x = prots.encryptor.generateRandomExponent(rand); - ECPoint a = prots.group.multiply(prots.g, x); - ECPoint b = prots.group.multiply(prots.h, x); - ECElGamalMixParams.DlogStatement statement = params.new DlogStatement(a, b); - ECElGamalMixParams.DlogStatementWitness witness = params.new DlogStatementWitness(x); + Pair returnRandomTrueStatement() { + BigInteger x = encryptor.generateRandomExponent(rand); + ECPoint a = group.multiply(statementGenerator.g, x); + ECPoint b = group.multiply(statementGenerator.h, x); + ECElGamalMixStatementGenerator.DlogStatement statement = statementGenerator.new DlogStatement(a, b); + ECElGamalMixStatementGenerator.DlogStatementWitness witness = statementGenerator.new DlogStatementWitness(x); return new Pair<>(statement, witness); } - ECElGamalMixParams.DlogStatement returnRandomFalseStatement() { - ECPoint a = prots.group.sample(rand); - ECPoint b = prots.group.sample(rand); + ECElGamalMixStatementGenerator.DlogStatement returnRandomFalseStatement() { + ECPoint a = group.sample(rand); + ECPoint b = group.sample(rand); - return params.new DlogStatement(a, b); + return statementGenerator.new DlogStatement(a, b); } void generateRandomTrueStatement() { - Pair sw = returnRandomTrueStatement(); + Pair sw = returnRandomTrueStatement(); this.statement = sw.a; this.witness = sw.b; } @@ -60,24 +64,24 @@ public class DlogStatementSchnorrSigmaTest extends @Override protected SigmaProtocol.Prover getNewProver() { - prover = prots.new DlogStatementSchnorrProver(statement, witness); + prover = new SchnorrDlogEquivalence.Prover(encryptor, rand, statement, witness); return prover; } @Override protected SigmaProtocol.Verifier getNewVerifier() { - verifier = prots.new DlogStatementSchnorrVerifier(statement); + verifier = new SchnorrDlogEquivalence.Verifier(encryptor, statement); return verifier; } @Override protected SigmaProtocol.Simulator getNewSimulator() { - simulator = prots.new DlogStatementSchnorrSimulator(statement); + simulator = new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement); return simulator; } @Override protected BigInteger getChallengeModulus() { - return prots.group.orderUpperBound(); + return group.orderUpperBound(); } } \ No newline at end of file diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java index 07c6c80..82d2429 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaProof.java @@ -34,11 +34,6 @@ public class DummySigmaProof { public BigInteger getFinalMessage(BigInteger challenge) { return challenge.add(r.multiply(x.add(y))); } - - @Override - public void reset() { - - } } public static class Verifier implements SigmaProtocol.Verifier { @@ -81,11 +76,6 @@ public class DummySigmaProof { public BigInteger getFinalMessage() { return resp; } - - @Override - public void reset() { - - } } } diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index d676a34..85015f4 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -75,7 +75,7 @@ public class ZeroKnowledgeProof { for (int i = 0; i < n*2 ; i +=2){ prover.prove(encryptedMessage[i],encryptedMessage[i+1],reencryptedMessage[i],reencryptedMessage[i+1], - false,0,0,0,randomnesses[i],randomnesses[i+1]); + false,0,0,0, 0, randomnesses[i],randomnesses[i+1]); } long finishTime = System.currentTimeMillis(); From deeed4f20f259e5a402ecde1b1ee46ad90b208af Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Thu, 19 Jan 2017 15:24:35 +0200 Subject: [PATCH 15/25] tests pass --- mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java | 6 +++--- mixer/src/main/java/meerkat/mixer/mixing/Mixer.java | 7 ++----- mixer/src/main/java/meerkat/mixer/proofs/Mix2.java | 1 + 3 files changed, 6 insertions(+), 8 deletions(-) diff --git a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java index fc0e37a..ded8997 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java @@ -33,16 +33,16 @@ public class BenesNetwork implements PermutationNetwork * (that is, switch j has inputs/outputs 2j and 2j+1) * * @param logN log (base 2) of number of inputs to Benes network (N = 2^{logN}) - * @param layer current layer index. Must be between 1 and 2*logN-2 (layer 0 doesn't have a previous layer) + * @param layer current layer index. Must be between 0 and 2*logN-1 (layer -1 is the inputs and layer 2*logN-1 is the outputs) * @param inputIdx the input Idx for the current layer (must be between 0 and (1 << logN) - 1 * * @return the requested index */ public static int getOutputIdxInPreviousLayer(int logN, int layer, int inputIdx) { - assert (layer >= 0) && (layer < 2*logN - 1); + assert (layer >= 0) && (layer <= 2*logN - 1); assert (inputIdx >= 0) && (inputIdx < 1 << logN); - if ((layer == 0) || (inputIdx & 1) == 0) { + if ((layer == 0) || (layer == 2*logN - 1) || (inputIdx & 1) == 0) { // layer 0 inputs and all even inputs // are connected straight "across" everywhere return inputIdx; diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java index 0b6e184..5f013e3 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java +++ b/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java @@ -147,9 +147,6 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { , EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { int layers = mixNetwork.getNumLayers(); int n = mixNetwork.getNumInputs(); - Switch[] switchesLayer; - int index1,index2; - int switchIndex = 0; int numSwitches = n >> 1; Mix2Proof[][] proofsTable = new Mix2Proof[layers][numSwitches]; @@ -168,7 +165,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { r1 = randomnesses[layer][2 * switchIdx]; r2 = randomnesses[layer][2 * switchIdx + 1]; - proofsTable[layer][switchIndex] = + proofsTable[layer][switchIdx] = prover.prove(a, b, c, d, isCrossed, layer, switchIdx, out0, out1, r1, r2); } } @@ -187,7 +184,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { int n = ciphertexts.size(); assert (n > 1 && isPowerOfTwo(n)); - int logN = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)) + 1; + int logN = Integer.numberOfTrailingZeros(Integer.highestOneBit(n)); PermutationNetwork net = generateMixNetwork(logN,random); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java b/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java index 616b7fd..9884e36 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java @@ -18,6 +18,7 @@ public class Mix2 { public ChallengeGenerator(ECElGamalEncryption encryptor, Random rand) { this.encryptor = encryptor; + this.rand = rand; group = encryptor.getGroup(); } From b9abd847c7efb9b681630c828f2a38800ce93b00 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Thu, 19 Jan 2017 16:00:01 +0200 Subject: [PATCH 16/25] Refactoring --- .../src/main/proto/meerkat/voting.proto | 2 +- .../java/meerkat/crypto/mixnet/Trustee.java | 7 - .../java/meerkat/crypto/mixnet/Verifier.java | 7 - .../{mixing/Mixer.java => MixGenerator.java} | 22 +-- .../VerifyTable.java => MixVerifier.java} | 8 +- .../main/java/meerkat/mixer/MixerOutput.java | 52 +++++++ .../meerkat/mixer/main/BatchConverter.java | 12 +- .../java/meerkat/mixer/main/BatchHandler.java | 10 +- .../java/meerkat/mixer/main/MainMixing.java | 6 +- .../meerkat/mixer/mixing/MixerOutput.java | 132 ------------------ .../java/meerkat/mixer/mixing/Switch.java | 36 ----- .../{mixing => network}/BenesNetwork.java | 2 +- .../PermutationNetwork.java | 4 +- .../RandomPermutation.java | 4 +- .../mixer/{mixing => network}/Util.java | 4 +- .../java/meerkat/mixer/proofs/Verifier.java | 67 --------- .../proofs/ZeroKnowledgeOrProofParser.java | 87 ------------ .../{ => concrete}/DlogConjunction.java | 11 +- .../mixer/proofs/{ => concrete}/Mix2.java | 7 +- .../{Prover.java => concrete/Mix2nizk.java} | 52 ++++--- .../{ => concrete}/ProtobufConcatenators.java | 3 +- .../SchnorrDlogEquivalence.java | 17 +-- .../Statements.java} | 25 ++-- .../proofs/{ => generic}/SigmaFiatShamir.java | 4 +- .../{ => generic}/SigmaProtocolAnd2.java | 5 +- .../{ => generic}/SigmaProtocolOr2.java | 5 +- .../java/meerkat/mixer/CreateTestVector.java | 14 +- .../java/meerkat/mixer/ECParamTestBase.java | 4 - .../test/java/meerkat/mixer/MixingTest.java | 23 +-- .../{mixing => network}/BenesNetworkTest.java | 9 +- .../PermutationNetworkTest.java | 2 +- .../meerkat/mixer/proofs/DummySigmaTest.java | 7 +- .../mixer/proofs/SigmaProtocolTest.java | 13 +- .../DlogAndStatementSigmaTest.java | 17 ++- .../DlogOrStatementSigmaTest.java | 29 ++-- .../DlogStatementSchnorrSigmaTest.java | 30 ++-- .../{ => proofs/concrete}/Mix2ProofTest.java | 21 ++- .../java/profiling/ZeroKnowledgeProof.java | 4 +- 38 files changed, 239 insertions(+), 525 deletions(-) delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java rename mixer/src/main/java/meerkat/mixer/{mixing/Mixer.java => MixGenerator.java} (90%) rename mixer/src/main/java/meerkat/mixer/{proofs/VerifyTable.java => MixVerifier.java} (93%) create mode 100644 mixer/src/main/java/meerkat/mixer/MixerOutput.java delete mode 100644 mixer/src/main/java/meerkat/mixer/mixing/MixerOutput.java delete mode 100644 mixer/src/main/java/meerkat/mixer/mixing/Switch.java rename mixer/src/main/java/meerkat/mixer/{mixing => network}/BenesNetwork.java (99%) rename mixer/src/main/java/meerkat/mixer/{mixing => network}/PermutationNetwork.java (96%) rename mixer/src/main/java/meerkat/mixer/{mixing => network}/RandomPermutation.java (94%) rename mixer/src/main/java/meerkat/mixer/{mixing => network}/Util.java (96%) delete mode 100644 mixer/src/main/java/meerkat/mixer/proofs/Verifier.java delete mode 100644 mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java rename mixer/src/main/java/meerkat/mixer/proofs/{ => concrete}/DlogConjunction.java (83%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => concrete}/Mix2.java (88%) rename mixer/src/main/java/meerkat/mixer/proofs/{Prover.java => concrete/Mix2nizk.java} (59%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => concrete}/ProtobufConcatenators.java (98%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => concrete}/SchnorrDlogEquivalence.java (87%) rename mixer/src/main/java/meerkat/mixer/proofs/{ECElGamalMixStatementGenerator.java => concrete/Statements.java} (91%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => generic}/SigmaFiatShamir.java (93%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => generic}/SigmaProtocolAnd2.java (96%) rename mixer/src/main/java/meerkat/mixer/proofs/{ => generic}/SigmaProtocolOr2.java (98%) rename mixer/src/test/java/meerkat/mixer/{mixing => network}/BenesNetworkTest.java (64%) rename mixer/src/test/java/meerkat/mixer/{mixing => network}/PermutationNetworkTest.java (98%) rename mixer/src/test/java/meerkat/mixer/proofs/{ => concrete}/DlogAndStatementSigmaTest.java (77%) rename mixer/src/test/java/meerkat/mixer/proofs/{ => concrete}/DlogOrStatementSigmaTest.java (71%) rename mixer/src/test/java/meerkat/mixer/proofs/{ => concrete}/DlogStatementSchnorrSigmaTest.java (69%) rename mixer/src/test/java/meerkat/mixer/{ => proofs/concrete}/Mix2ProofTest.java (87%) diff --git a/meerkat-common/src/main/proto/meerkat/voting.proto b/meerkat-common/src/main/proto/meerkat/voting.proto index 6e03a5b..0907adc 100644 --- a/meerkat-common/src/main/proto/meerkat/voting.proto +++ b/meerkat-common/src/main/proto/meerkat/voting.proto @@ -123,7 +123,7 @@ message ElectionParams { // Verification keys for valid mixers. repeated SignatureVerificationKey mixerVerificationKeys = 4; - // How many mixers must participate for the mixing to be considered valid + // How many mixers must participate for the network to be considered valid uint32 mixerThreshold = 5; // questions to first indicate the voter's channel diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java b/mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java deleted file mode 100644 index e8044cd..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/Trustee.java +++ /dev/null @@ -1,7 +0,0 @@ -package meerkat.crypto.mixnet; - -/** - * Created by talm on 25/10/15. - */ -public class Trustee { -} diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java b/mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java deleted file mode 100644 index b733317..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/Verifier.java +++ /dev/null @@ -1,7 +0,0 @@ -package meerkat.crypto.mixnet; - -/** - * Created by talm on 25/10/15. - */ -public class Verifier { -} diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java b/mixer/src/main/java/meerkat/mixer/MixGenerator.java similarity index 90% rename from mixer/src/main/java/meerkat/mixer/mixing/Mixer.java rename to mixer/src/main/java/meerkat/mixer/MixGenerator.java index 5f013e3..e4787d6 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/Mixer.java +++ b/mixer/src/main/java/meerkat/mixer/MixGenerator.java @@ -1,9 +1,12 @@ -package meerkat.mixer.mixing; +package meerkat.mixer; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.Encryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.MixerOutput; +import meerkat.mixer.network.BenesNetwork; +import meerkat.mixer.network.PermutationNetwork; +import meerkat.mixer.network.RandomPermutation; import meerkat.protobuf.Crypto.EncryptionRandomness; import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage; import meerkat.protobuf.Mixing.Mix2Proof; @@ -13,7 +16,7 @@ import java.util.Random; /** * an implementation of meerkat.crypto.mixnet.Mixer - * meerkat.mixer.mixing algorithm on set of n encrypted votes: + * meerkat.mixer.network algorithm on set of n encrypted votes: * 0. asset n is power of two * 1. set switches according to benes network on random permutation * 2. re encrypt and mix with respect to switches values (encryptor.rerandomize) @@ -21,7 +24,7 @@ import java.util.Random; * 4. return proofs table + encryption table * */ -public class Mixer implements meerkat.crypto.mixnet.Mixer { +public class MixGenerator implements meerkat.crypto.mixnet.Mixer { private final Mix2ZeroKnowledgeProver prover; private final Encryption encryptor; @@ -31,7 +34,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { * @param prover * @param encryptor */ - public Mixer(Mix2ZeroKnowledgeProver prover, Encryption encryptor) { + public MixGenerator(Mix2ZeroKnowledgeProver prover, Encryption encryptor) { this.prover = prover; this.encryptor = encryptor; } @@ -99,10 +102,9 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { * @param randomnesses an initialized randomness table of size layers * n, use for rerandomize operations * @throws InvalidProtocolBufferException */ - private void rerandomize(PermutationNetwork mixNetwork, RerandomizableEncryptedMessage[][] encryptionTable - ,EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { - Switch[] switchesLayer; - int index1,index2; + private void rerandomize(PermutationNetwork mixNetwork, + RerandomizableEncryptedMessage[][] encryptionTable, + EncryptionRandomness[][] randomnesses) throws InvalidProtocolBufferException { RerandomizableEncryptedMessage a,b; EncryptionRandomness r1,r2; int layers = mixNetwork.getNumLayers(); @@ -176,7 +178,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { * mix given encrypted votes using random * @param ciphertexts encrypted votes * @param random - * @return meerkat.mixer.mixing result + * @return meerkat.mixer.network result * @throws InvalidProtocolBufferException */ public MixerOutput mix(List ciphertexts,Random random) throws InvalidProtocolBufferException { @@ -195,7 +197,7 @@ public class Mixer implements meerkat.crypto.mixnet.Mixer { rerandomize(net,encryptionTable,randomnesses); Mix2Proof[][] proofsTable = generateMix2ProofTable(net,encryptionTable,randomnesses); - return new meerkat.mixer.mixing.MixerOutput(logN, proofsTable, encryptionTable); + return new meerkat.mixer.MixerOutput(logN, proofsTable, encryptionTable); } } \ No newline at end of file diff --git a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java b/mixer/src/main/java/meerkat/mixer/MixVerifier.java similarity index 93% rename from mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java rename to mixer/src/main/java/meerkat/mixer/MixVerifier.java index 4d58fee..8ddd956 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/VerifyTable.java +++ b/mixer/src/main/java/meerkat/mixer/MixVerifier.java @@ -1,4 +1,4 @@ -package meerkat.mixer.proofs; +package meerkat.mixer; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; @@ -10,14 +10,14 @@ import java.util.Arrays; /** * Created by Tzlil on 12/30/2015. - * provide one operation - verify meerkat.mixer.mixing output + * provide one operation - verify meerkat.mixer.network output */ -public final class VerifyTable { +public final class MixVerifier { /** * constructor * @param verifier * @param mixerOutput - * @return true iff the meerkat.mixer.mixing output is valid + * @return true iff the meerkat.mixer.network output is valid * @throws InvalidProtocolBufferException */ public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier, MixerOutput mixerOutput) diff --git a/mixer/src/main/java/meerkat/mixer/MixerOutput.java b/mixer/src/main/java/meerkat/mixer/MixerOutput.java new file mode 100644 index 0000000..356bc05 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/MixerOutput.java @@ -0,0 +1,52 @@ +package meerkat.mixer; + +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; + +import java.io.OutputStream; + + +/** + * Created by Tzlil on 1/18/2016. + * implements meerkat.crypto.mixnet.MixerOutput interface + * container for meerkat.mixer.network.mix result. + */ +public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput { + private final Mixing.Mix2Proof[][] proofs; + private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages; + private final int logN; + + /** + * constructor + * @param logN log (base 2) of the number of votes + * @param encryptedMessages at level 0 , contains the original encrypted votes + * at each other level contains the re encrypted votes + * @param proofs in each cell (level,switch) contains the match zero knowledge proof + */ + public MixerOutput(int logN, Mixing.Mix2Proof[][] proofs, + Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) { + this.proofs = proofs; + this.encryptedMessages = encryptedMessages; + this.logN = logN; + } + + @Override + public Mixing.Mix2Proof[][] getProofs() { + return proofs; + } + + @Override + public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages() { + return encryptedMessages; + } + + @Override + public int getLogN() { + return logN; + } + + @Override + public int getNumLayers() { + return 2 * logN - 1; + } +} diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java index b61c4c5..a611b22 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java @@ -1,24 +1,22 @@ package meerkat.mixer.main; -import com.google.protobuf.ByteString; import meerkat.crypto.mixnet.MixerOutput; import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; -import java.math.BigInteger; import java.util.ArrayList; import java.util.List; /** * Created by Tzlil on 12/17/2015. - * provide convert operation from batch data to meerkat.mixer.mixing output and backwards + * provide convert operation from batch data to meerkat.mixer.network output and backwards */ public class BatchConverter { /** - * convert meerkat.mixer.mixing output to batch data + * convert meerkat.mixer.network output to batch data * @param mixerOutput - * @return meerkat.mixer.mixing output as list of batch data + * @return meerkat.mixer.network output as list of batch data */ public List MixerOutput2BatchChunk(MixerOutput mixerOutput) { @@ -51,7 +49,7 @@ public class BatchConverter { } /** - * convert batch data list to meerkat.mixer.mixing output + * convert batch data list to meerkat.mixer.network output * @param batchChunkList * @return batch data list as MixerOutput * @throws Exception @@ -85,7 +83,7 @@ public class BatchConverter { } } - return new meerkat.mixer.mixing.MixerOutput(logN, proofs,encryptions); + return new meerkat.mixer.MixerOutput(logN, proofs,encryptions); } diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java index c9d72d9..4aeb582 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java @@ -5,7 +5,7 @@ import meerkat.crypto.mixnet.MixerOutput; import meerkat.protobuf.Crypto; import meerkat.mixer.necessary.AsyncBulletinBoardClient; import meerkat.mixer.necessary.CompleteBatch; -import meerkat.mixer.proofs.VerifyTable; +import meerkat.mixer.MixVerifier; import java.util.Arrays; import java.util.List; @@ -61,7 +61,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback= 0) - fileName = encDir+"/layer" + layer +"/" + i; - else - fileName = encDir+"/input/" + i; - - File file = new File(fileName); - file.createNewFile(); - FileOutputStream fos = new FileOutputStream(file); - fos.write(enc.toByteArray()); - fos.close(); - } -} diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Switch.java b/mixer/src/main/java/meerkat/mixer/mixing/Switch.java deleted file mode 100644 index 5de522e..0000000 --- a/mixer/src/main/java/meerkat/mixer/mixing/Switch.java +++ /dev/null @@ -1,36 +0,0 @@ -package meerkat.mixer.mixing; - -/** - * Created by Tzlil on 12/15/2015. - * container for switch - */ -public class Switch{ - - public final int i, j, layer; - public final boolean value; - - /** - * constructor - * @param i - * @param j - * @param layer - * @param value the switch is on or off - */ - public Switch(int i, int j, int layer, boolean value) { - this.i = i; - this.j = j; - 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/meerkat/mixer/mixing/BenesNetwork.java b/mixer/src/main/java/meerkat/mixer/network/BenesNetwork.java similarity index 99% rename from mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java rename to mixer/src/main/java/meerkat/mixer/network/BenesNetwork.java index ded8997..e467fd8 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/BenesNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/network/BenesNetwork.java @@ -1,4 +1,4 @@ -package meerkat.mixer.mixing; +package meerkat.mixer.network; import java.util.*; diff --git a/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java b/mixer/src/main/java/meerkat/mixer/network/PermutationNetwork.java similarity index 96% rename from mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java rename to mixer/src/main/java/meerkat/mixer/network/PermutationNetwork.java index 4dc1e0e..c4cad88 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/PermutationNetwork.java +++ b/mixer/src/main/java/meerkat/mixer/network/PermutationNetwork.java @@ -1,6 +1,4 @@ -package meerkat.mixer.mixing; - -import java.util.ArrayList; +package meerkat.mixer.network; /** * A generic permutation network composed of 2-input switches. diff --git a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java b/mixer/src/main/java/meerkat/mixer/network/RandomPermutation.java similarity index 94% rename from mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java rename to mixer/src/main/java/meerkat/mixer/network/RandomPermutation.java index 537fae2..55a491d 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/RandomPermutation.java +++ b/mixer/src/main/java/meerkat/mixer/network/RandomPermutation.java @@ -1,7 +1,5 @@ -package meerkat.mixer.mixing; +package meerkat.mixer.network; -import java.util.ArrayList; -import java.util.List; import java.util.Random; /** diff --git a/mixer/src/main/java/meerkat/mixer/mixing/Util.java b/mixer/src/main/java/meerkat/mixer/network/Util.java similarity index 96% rename from mixer/src/main/java/meerkat/mixer/mixing/Util.java rename to mixer/src/main/java/meerkat/mixer/network/Util.java index 26437ae..90bae97 100644 --- a/mixer/src/main/java/meerkat/mixer/mixing/Util.java +++ b/mixer/src/main/java/meerkat/mixer/network/Util.java @@ -1,6 +1,4 @@ -package meerkat.mixer.mixing; - -import java.util.ArrayList; +package meerkat.mixer.network; /** * Generic utilities diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java b/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java deleted file mode 100644 index 0331cce..0000000 --- a/mixer/src/main/java/meerkat/mixer/proofs/Verifier.java +++ /dev/null @@ -1,67 +0,0 @@ -package meerkat.mixer.proofs; - -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; -import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.ECGroup; - -/** - * implements Mix2ZeroKnowledgeVerifier - */ -public class Verifier implements Mix2ZeroKnowledgeVerifier { - - - private final ECElGamalEncryption encryptor; - private final ECGroup group; - private final RandomOracle randomOracle; - private final ECPoint g,h; - private final ECElGamalMixStatementGenerator mixParams; - final SigmaFiatShamir mix2NIZK; - - -// private final ZeroKnowledgeOrProofParser parser; - - /** - * constructor - * @param encryptor should be as the encryptor used by meerkat.mixer.proofs - * @param randomOracle should be as the random oracle used by meerkat.mixer.proofs - */ - 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; - this.mixParams = new ECElGamalMixStatementGenerator(encryptor); - this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); -// this.parser = new ZeroKnowledgeOrProofParser(group); - } - - /** - * verify zero knowledge proof - * @param in1 - * @param in2 - * @param out1 - * @param out2 - * @param proof out1 = rerandomize(in1) && out2 = rerandomize(in2) - * || - * out1 = rerandomize(in2) && out2 = rerandomize(in1) - * @return true iff all 4 or proofs are valid - * @throws InvalidProtocolBufferException - */ - public boolean verify(Crypto.RerandomizableEncryptedMessage in1, - Crypto.RerandomizableEncryptedMessage in2, - Crypto.RerandomizableEncryptedMessage out1, - Crypto.RerandomizableEncryptedMessage out2, - Mixing.Mix2Proof proof) throws InvalidProtocolBufferException { - - ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); - Mix2.Verifier verifier = new Mix2.Verifier(encryptor, statement); - - return mix2NIZK.verifyNizk(proof, verifier); - } -} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java b/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java deleted file mode 100644 index 5c3d6c8..0000000 --- a/mixer/src/main/java/meerkat/mixer/proofs/ZeroKnowledgeOrProofParser.java +++ /dev/null @@ -1,87 +0,0 @@ -package meerkat.mixer.proofs; - -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.concrete.Util; -import meerkat.protobuf.Mixing; -import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.concrete.ECGroup; - -import java.math.BigInteger; - -/** - * Created by Tzlil on 1/25/2016. - * zero knowledge proof parser - */ -public class ZeroKnowledgeOrProofParser { -// -// private final ECGroup group; -// -// /** -// * parse or proof message and return the result in zero knowledge or proof container -// * @param orProof -// * @return zero knowledge or proof container -// */ -// public ZeroKnowledgeOrProofContainer parseOrProof(Mixing.Mix2Proof.OrProof orProof){ -// return new ZeroKnowledgeOrProofContainer(orProof); -// } -// -// /** -// * getter -// * @param group -// */ -// public ZeroKnowledgeOrProofParser(ECGroup group) { -// this.group = group; -// } -// -// -// /** -// * inner class -// * container for parsed zero knowledge or proof -// * constructor is private, can be construct using ZeroKnowledgeOrProofParser.parseOrProof -// */ -// public class ZeroKnowledgeOrProofContainer{ -// public final ECPoint g1,g2,h1,h2; -// public final ECPoint g1Tag,g2Tag,h1Tag,h2Tag; -// public final ECPoint u,v,uTag,vTag; -// public final BigInteger c1,c2,z,zTag; -// public final Mixing.Mix2Proof.OrProof.FirstMessage firstMessage; -// -// /** -// * constructor -// * @param orProof -// */ -// private ZeroKnowledgeOrProofContainer(Mixing.Mix2Proof.OrProof orProof){ -// this.firstMessage = -// Mixing.Mix2Proof.OrProof.FirstMessage.newBuilder() -// .setG1(orProof.getG1()) -// .setH1(orProof.getH1()) -// .setG2(orProof.getG2()) -// .setH2(orProof.getH2()) -// .setG1Tag(orProof.getG1Tag()) -// .setH1Tag(orProof.getH1Tag()) -// .setG2Tag(orProof.getG2Tag()) -// .setH2Tag(orProof.getH2Tag()) -// .setU(orProof.getU()) -// .setV(orProof.getV()) -// .setUTag(orProof.getUTag()) -// .setVTag(orProof.getVTag()) -// .build(); -// this.g1 = ECElGamalEncryption.decodeElement(group, orProof.getG1()); -// this.g2 = ECElGamalEncryption.decodeElement(group, orProof.getG2()); -// this.h1 = ECElGamalEncryption.decodeElement(group, orProof.getH1()); -// this.h2 = ECElGamalEncryption.decodeElement(group, orProof.getH2()); -// this.g1Tag = ECElGamalEncryption.decodeElement(group, orProof.getG1Tag()); -// this.g2Tag = ECElGamalEncryption.decodeElement(group, orProof.getG2Tag()); -// this.h1Tag = ECElGamalEncryption.decodeElement(group, orProof.getH1Tag()); -// this.h2Tag = ECElGamalEncryption.decodeElement(group, orProof.getH2Tag()); -// this.u = ECElGamalEncryption.decodeElement(group, orProof.getU()); -// this.v = ECElGamalEncryption.decodeElement(group, orProof.getV()); -// this.uTag = ECElGamalEncryption.decodeElement(group, orProof.getUTag()); -// this.vTag = ECElGamalEncryption.decodeElement(group, orProof.getVTag()); -// this.c1 = Util.decodeBigInteger(orProof.getC1()); -// this.c2 = Util.decodeBigInteger(orProof.getC2()); -// this.z = Util.decodeBigInteger(orProof.getZ()); -// this.zTag = Util.decodeBigInteger(orProof.getZTag()); -// } -// } -} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java similarity index 83% rename from mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java index 57afa34..d2487b5 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/DlogConjunction.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java @@ -1,6 +1,7 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.mixer.proofs.generic.SigmaProtocolAnd2; import meerkat.protobuf.Mixing; import java.util.Random; @@ -13,8 +14,8 @@ public class DlogConjunction { public static class Prover extends SigmaProtocolAnd2.Prover { - public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement, - ECElGamalMixStatementGenerator.AndStatementWitness witness) { + public Prover(ECElGamalEncryption encryptor, Random rand, Statements.AndStatement statement, + Statements.AndStatementWitness witness) { super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[0], witness.witnesses[0]), new SchnorrDlogEquivalence.Prover(encryptor, rand, statement.clauses[1], witness.witnesses[1])); @@ -22,7 +23,7 @@ public class DlogConjunction { } public static class Simulator extends SigmaProtocolAnd2.Simulator { - public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.AndStatement statement) { + public Simulator(ECElGamalEncryption encryptor, Random rand, Statements.AndStatement statement) { super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[0]), new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[1])); } @@ -31,7 +32,7 @@ public class DlogConjunction { public static class Verifier extends SigmaProtocolAnd2.Verifier { - public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.AndStatement statement) { + public Verifier(ECElGamalEncryption encryptor, Statements.AndStatement statement) { super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[0]), new SchnorrDlogEquivalence.Verifier(encryptor, statement.clauses[1])); } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2.java similarity index 88% rename from mixer/src/main/java/meerkat/mixer/proofs/Mix2.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2.java index 9884e36..10ea69a 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Mix2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2.java @@ -1,6 +1,7 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.mixer.proofs.generic.SigmaProtocolOr2; import meerkat.protobuf.Mixing; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -30,7 +31,7 @@ public class Mix2 { } public static class Prover extends SigmaProtocolOr2.Prover { - public Prover(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.Mix2Statement statement, ECElGamalMixStatementGenerator.Mix2StatementWitness witness) { + public Prover(ECElGamalEncryption encryptor, Random rand, Statements.Mix2Statement statement, Statements.Mix2StatementWitness witness) { super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, rand), new DlogConjunction.Prover(encryptor, rand, statement.clauses[witness.trueClauseIndex], witness.witness), new DlogConjunction.Simulator(encryptor, rand, statement.clauses[1 - witness.trueClauseIndex]), @@ -39,7 +40,7 @@ public class Mix2 { } public static class Verifier extends SigmaProtocolOr2.Verifier { - public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.Mix2Statement statement) { + public Verifier(ECElGamalEncryption encryptor, Statements.Mix2Statement statement) { super(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, new ChallengeGenerator(encryptor, null), new DlogConjunction.Verifier(encryptor, statement.clauses[0]), new DlogConjunction.Verifier(encryptor, statement.clauses[1])); } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java similarity index 59% rename from mixer/src/main/java/meerkat/mixer/proofs/Prover.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java index 2710f0c..83b80f8 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/Prover.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java @@ -1,31 +1,28 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.mixer.proofs.generic.SigmaFiatShamir; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; -import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; -import java.math.BigInteger; import java.util.Random; /** - * implements of Mix2ZeroKnowledgeProver interface - * this implementation assumes that each RerandomizableEncryptedMessage is ElGamalCiphertext + * implements of Mix2ZeroKnowledgeProver and Mix2ZeroKnowledgeVerifier interfaces + * this implementation assumes that each RerandomizableEncryptedMessage is an ElGamalCiphertext */ -public class Prover implements Mix2ZeroKnowledgeProver { +public class Mix2nizk implements Mix2ZeroKnowledgeProver, Mix2ZeroKnowledgeVerifier { // private final ECGroup group; - private final RandomOracle randomOracle; private final Random rand; private final ECElGamalEncryption encryptor; - private final ECPoint g,h; - private final BigInteger groupOrderUpperBound; - private final ECElGamalMixStatementGenerator mixParams; + private final Statements mixParams; final SigmaFiatShamir mix2NIZK; /** @@ -33,16 +30,12 @@ public class Prover implements Mix2ZeroKnowledgeProver { * @param encryptor * @param randomOracle - use for Fiat–Shamir heuristic */ - public Prover(Random rand, ECElGamalEncryption encryptor, RandomOracle randomOracle) { + public Mix2nizk(Random rand, ECElGamalEncryption encryptor, RandomOracle randomOracle) { this.rand = rand; this.encryptor = encryptor; - this.randomOracle = randomOracle; this.group = this.encryptor.getGroup(); - this.g = group.getGenerator(); - this.h = this.encryptor.getElGamalPK().getPK(); - this.mixParams = new ECElGamalMixStatementGenerator(encryptor); - this.groupOrderUpperBound = group.orderUpperBound(); + this.mixParams = new Statements(encryptor); this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); } @@ -68,8 +61,8 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { - ECElGamalMixStatementGenerator.Mix2Statement statement = mixParams.createStatement(a, b, c, d); - ECElGamalMixStatementGenerator.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); + Statements.Mix2Statement statement = mixParams.createStatement(a, b, c, d); + Statements.Mix2StatementWitness witness = mixParams.createMix2Witness(r1, r2, switched); Mix2.Prover prover = new Mix2.Prover(encryptor, rand, statement, witness); @@ -82,5 +75,28 @@ public class Prover implements Mix2ZeroKnowledgeProver { return mix2NIZK.generateNizk(prover).toBuilder().setLocation(location).build(); } + /** + * verify zero knowledge proof + * @param in1 + * @param in2 + * @param out1 + * @param out2 + * @param proof out1 = rerandomize(in1) && out2 = rerandomize(in2) + * || + * out1 = rerandomize(in2) && out2 = rerandomize(in1) + * @return true iff all 4 or proofs are valid + * @throws InvalidProtocolBufferException + */ + public boolean verify(Crypto.RerandomizableEncryptedMessage in1, + Crypto.RerandomizableEncryptedMessage in2, + Crypto.RerandomizableEncryptedMessage out1, + Crypto.RerandomizableEncryptedMessage out2, + Mixing.Mix2Proof proof) throws InvalidProtocolBufferException { + + Statements.Mix2Statement statement = mixParams.createStatement(in1,in2,out1,out2); + Mix2.Verifier verifier = new Mix2.Verifier(encryptor, statement); + + return mix2NIZK.verifyNizk(proof, verifier); + } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/ProtobufConcatenators.java similarity index 98% rename from mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/ProtobufConcatenators.java index 98c74ef..5a2d833 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ProtobufConcatenators.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/ProtobufConcatenators.java @@ -1,6 +1,7 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import meerkat.crypto.concrete.Util; +import meerkat.mixer.proofs.Concatenator; import meerkat.protobuf.Mixing; import java.math.BigInteger; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/SchnorrDlogEquivalence.java similarity index 87% rename from mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/SchnorrDlogEquivalence.java index 49d615f..4aec718 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SchnorrDlogEquivalence.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/SchnorrDlogEquivalence.java @@ -1,7 +1,8 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.concrete.Util; +import meerkat.mixer.proofs.SigmaProtocol; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; @@ -18,9 +19,9 @@ public class SchnorrDlogEquivalence { public static class Verifier implements SigmaProtocol.Verifier { ECElGamalEncryption encryptor; ECGroup group; - final ECElGamalMixStatementGenerator.DlogStatement statement; + final Statements.DlogStatement statement; - public Verifier(ECElGamalEncryption encryptor, ECElGamalMixStatementGenerator.DlogStatement statement) { + public Verifier(ECElGamalEncryption encryptor, Statements.DlogStatement statement) { this.encryptor = encryptor; group = encryptor.getGroup(); this.statement = statement; @@ -49,10 +50,10 @@ public class SchnorrDlogEquivalence { ECGroup group; Random rand; - ECElGamalMixStatementGenerator.DlogStatement statement; + Statements.DlogStatement statement; BigInteger response = null; - public Simulator(ECElGamalEncryption encryptor, Random rand, ECElGamalMixStatementGenerator.DlogStatement statement) { + public Simulator(ECElGamalEncryption encryptor, Random rand, Statements.DlogStatement statement) { this.encryptor = encryptor; group = encryptor.getGroup(); this.rand = rand; @@ -84,13 +85,13 @@ public class SchnorrDlogEquivalence { ECElGamalEncryption encryptor; ECGroup group; Random rand; - ECElGamalMixStatementGenerator.DlogStatement statement; - ECElGamalMixStatementGenerator.DlogStatementWitness witness; + Statements.DlogStatement statement; + Statements.DlogStatementWitness witness; BigInteger r = null; public Prover(ECElGamalEncryption encryptor, Random rand, - ECElGamalMixStatementGenerator.DlogStatement statement, ECElGamalMixStatementGenerator.DlogStatementWitness witness) { + Statements.DlogStatement statement, Statements.DlogStatementWitness witness) { this.encryptor = encryptor; group = encryptor.getGroup(); this.rand = rand; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java similarity index 91% rename from mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java rename to mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java index 8f43dff..92c8ba7 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/ECElGamalMixStatementGenerator.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java @@ -1,9 +1,8 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; -import meerkat.protobuf.ConcreteCrypto.GroupElement; import meerkat.protobuf.Crypto; import meerkat.protobuf.Crypto.EncryptionRandomness; import org.bouncycastle.math.ec.ECPoint; @@ -16,28 +15,22 @@ import java.math.BigInteger; * * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it */ -public class ECElGamalMixStatementGenerator { +public class Statements { - final ECElGamalEncryption encryptor; - final ECGroup group; - final ECPoint g; - final ECPoint h; - - // Cache encoded formats to save multiple re-encodings - private final GroupElement gEncoded; - private final GroupElement hEncoded; + final public ECElGamalEncryption encryptor; + final public ECGroup group; + final public ECPoint g; + final public ECPoint h; /** * @param encryptor encryptor used for encoding/decoding serialized ciphertexts. The group, default generator and * second base (h) are taken from the encryptor (second base is the public key) */ - public ECElGamalMixStatementGenerator(ECElGamalEncryption encryptor){ + public Statements(ECElGamalEncryption encryptor){ this.encryptor = encryptor; this.group = encryptor.getGroup(); this.g = group.getGenerator(); this.h = encryptor.getElGamalPK().getPK(); - this.gEncoded = encryptor.encodeElement(g); - this.hEncoded = encryptor.encodeElement(h); } /** @@ -175,9 +168,9 @@ public class ECElGamalMixStatementGenerator { DlogStatement(ECPoint a, ECPoint b) { - this.g = ECElGamalMixStatementGenerator.this.g; + this.g = Statements.this.g; this.a = a; - this.h = ECElGamalMixStatementGenerator.this.h; + this.h = Statements.this.h; this.b = b; } } diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java similarity index 93% rename from mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java rename to mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java index 409ea02..80085c0 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaFiatShamir.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java @@ -1,6 +1,8 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.generic; import com.google.protobuf.Message; +import meerkat.mixer.proofs.Concatenator; +import meerkat.mixer.proofs.SigmaProtocol; import org.factcenter.qilin.primitives.RandomOracle; import java.math.BigInteger; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java similarity index 96% rename from mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java rename to mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java index 31a0151..3e14edd 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolAnd2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java @@ -1,4 +1,7 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.generic; + +import meerkat.mixer.proofs.Concatenator; +import meerkat.mixer.proofs.SigmaProtocol; import java.math.BigInteger; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java similarity index 98% rename from mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java rename to mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java index 9cbc473..097d2a8 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/SigmaProtocolOr2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java @@ -1,4 +1,7 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.generic; + +import meerkat.mixer.proofs.Concatenator; +import meerkat.mixer.proofs.SigmaProtocol; import java.math.BigInteger; diff --git a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java index 0893a71..328a9e4 100644 --- a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java +++ b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java @@ -3,11 +3,11 @@ //import meerkat.crypto.concrete.ECElGamalEncryption; //import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; //import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -//import meerkat.mixer.mixing.Mixer; -//import meerkat.mixer.mixing.MixerOutput; +//import meerkat.mixer.Mixer; +//import meerkat.mixer.MixerOutput; //import meerkat.mixer.proofs.Prover; //import meerkat.mixer.proofs.Verifier; -//import meerkat.mixer.proofs.VerifyTable; +//import meerkat.mixer.VerifyTable; //import meerkat.protobuf.Crypto; //import meerkat.protobuf.Voting; //import org.factcenter.qilin.primitives.RandomOracle; @@ -72,9 +72,9 @@ // public void createValidTest() throws IOException { // // List mixerInput = generateMixerInput(); -// System.out.println("start mixing"); +// System.out.println("start network"); // MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer); -// System.out.println("mixing ended, start verification"); +// System.out.println("network ended, start verification"); // assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); // System.out.println("verification ended, start printing"); // mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test3"); @@ -89,9 +89,9 @@ // //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); // // List mixerInput = generateMixerInput(); -// System.out.println("start mixing"); +// System.out.println("start network"); // MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random); -// System.out.println("mixing ended, start negative verification"); +// System.out.println("network ended, start negative verification"); // assert (!VerifyTable.verifyTable(verifier,n,mixerOutput)); // System.out.println("verification ended, start printing"); // mixerOutput.outToFolder("C:\\Users\\Tzlil\\Desktop\\TestVector\\Test5"); diff --git a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java index 98c11aa..927aff5 100644 --- a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java +++ b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java @@ -1,10 +1,6 @@ package meerkat.mixer; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.mixer.proofs.Prover; -import meerkat.mixer.proofs.Verifier; import meerkat.protobuf.ConcreteCrypto; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.DigestOracle; diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index 693baee..05c8c90 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -5,18 +5,9 @@ package meerkat.mixer; */ import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.mixer.mixing.Mixer; -import meerkat.mixer.proofs.Prover; -import meerkat.mixer.proofs.Verifier; -import meerkat.mixer.proofs.VerifyTable; +import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; -import org.factcenter.qilin.primitives.concrete.ECElGamal; -import org.factcenter.qilin.primitives.concrete.ECGroup; import org.junit.Before; import org.junit.Test; @@ -27,8 +18,7 @@ import java.util.Random; public class MixingTest extends ECParamTestBase { Random random,randomMixer,randomProver; - Mix2ZeroKnowledgeVerifier verifier; - Prover prover; + Mix2nizk mix2nizk; meerkat.crypto.mixnet.Mixer mixer; private int layers; private int n; @@ -40,9 +30,8 @@ public class MixingTest extends ECParamTestBase { random = new Random(1); randomMixer = new Random(2); randomProver = new Random(3); - verifier = new Verifier(enc,randomOracle); - prover = new Prover(randomProver, enc,randomOracle); - mixer = new Mixer(prover, enc); + mix2nizk = new Mix2nizk(randomProver, enc,randomOracle); + mixer = new MixGenerator(mix2nizk, enc); // generate n int logN = 5; // + random.nextInt(8) @@ -65,7 +54,7 @@ public class MixingTest extends ECParamTestBase { System.out.println("n is : " + n); System.out.println(" generating input"); List mixerInput = generateMixerInput(); - System.out.println(" start mixing"); + System.out.println(" start network"); long startTime = System.currentTimeMillis(); meerkat.crypto.mixnet.MixerOutput mixerOutput = mixer.mix(mixerInput,randomMixer); @@ -76,7 +65,7 @@ public class MixingTest extends ECParamTestBase { System.out.println("start verification"); startTime = System.currentTimeMillis(); - assert (VerifyTable.verifyTable(verifier,mixerOutput)); + assert (MixVerifier.verifyTable(mix2nizk, mixerOutput)); finishTime = System.currentTimeMillis(); System.out.println(" that took: "+(finishTime-startTime)+ " ms"); diff --git a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java b/mixer/src/test/java/meerkat/mixer/network/BenesNetworkTest.java similarity index 64% rename from mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java rename to mixer/src/test/java/meerkat/mixer/network/BenesNetworkTest.java index 3114e9e..84178af 100644 --- a/mixer/src/test/java/meerkat/mixer/mixing/BenesNetworkTest.java +++ b/mixer/src/test/java/meerkat/mixer/network/BenesNetworkTest.java @@ -1,11 +1,4 @@ -package meerkat.mixer.mixing; - -import org.junit.Test; - -import java.util.Set; -import java.util.TreeSet; - -import static org.junit.Assert.*; +package meerkat.mixer.network; /** * Tests for Benes Network topology diff --git a/mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java b/mixer/src/test/java/meerkat/mixer/network/PermutationNetworkTest.java similarity index 98% rename from mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java rename to mixer/src/test/java/meerkat/mixer/network/PermutationNetworkTest.java index 2c3aa25..f3e143d 100644 --- a/mixer/src/test/java/meerkat/mixer/mixing/PermutationNetworkTest.java +++ b/mixer/src/test/java/meerkat/mixer/network/PermutationNetworkTest.java @@ -1,4 +1,4 @@ -package meerkat.mixer.mixing; +package meerkat.mixer.network; import org.junit.Before; import org.junit.Test; diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java index 3c62570..ffcd495 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/DummySigmaTest.java @@ -1,11 +1,8 @@ package meerkat.mixer.proofs; import meerkat.protobuf.Crypto; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; import java.math.BigInteger; -import java.util.Random; /** * Created by talm on 14/01/17. @@ -15,12 +12,12 @@ public class DummySigmaTest extends SigmaProtocolTest { public final int NUM_REPEAT = 10; - final RandomOracle randomOracle = new DigestOracle(); + final protected RandomOracle randomOracle = new DigestOracle(); - abstract void generateRandomTrueStatement(); + abstract protected void generateRandomTrueStatement(); - abstract void generateRandomFalseStatement(); + abstract protected void generateRandomFalseStatement(); abstract protected SigmaProtocol.Prover getNewProver(); abstract protected SigmaProtocol.Verifier getNewVerifier(); abstract protected SigmaProtocol.Simulator getNewSimulator(); - class NIZKConcat implements Concatenator.Pair, M1, M2> { + public class NIZKConcat implements Concatenator.Pair, M1, M2> { @Override public Pair concatenate(M1 msg1, M2 msg2) { return new Pair(msg1, msg2); } @@ -39,7 +40,7 @@ abstract public class SigmaProtocolTest { public M2 getMsg2(Pair msg) { return msg.b; } } - final NIZKConcat nizkConcat = new NIZKConcat(); + final protected NIZKConcat nizkConcat = new NIZKConcat(); abstract protected BigInteger getChallengeModulus(); @@ -49,7 +50,7 @@ abstract public class SigmaProtocolTest { BigInteger challengeModulus; int challengeBits; - Random rand = new Random(1);; + protected Random rand = new Random(1);; @Before public void setup() { diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogAndStatementSigmaTest.java similarity index 77% rename from mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java rename to mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogAndStatementSigmaTest.java index 562cac6..3a8dad4 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogAndStatementSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogAndStatementSigmaTest.java @@ -1,5 +1,8 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; +import meerkat.mixer.proofs.SigmaProtocol; +import meerkat.mixer.proofs.SigmaProtocolTest; +import meerkat.mixer.proofs.generic.SigmaProtocolAnd2; import meerkat.protobuf.Mixing; import org.factcenter.qilin.util.Pair; @@ -11,24 +14,24 @@ import java.math.BigInteger; public class DlogAndStatementSigmaTest extends SigmaProtocolTest { final DlogStatementSchnorrSigmaTest dlogtest; - ECElGamalMixStatementGenerator.DlogStatement s1, s2; - ECElGamalMixStatementGenerator.DlogStatementWitness w1, w2; + Statements.DlogStatement s1, s2; + Statements.DlogStatementWitness w1, w2; public DlogAndStatementSigmaTest() { this.dlogtest = new DlogStatementSchnorrSigmaTest(); } @Override - void generateRandomTrueStatement() { - Pair s1w1 = dlogtest.returnRandomTrueStatement(); + protected void generateRandomTrueStatement() { + Pair s1w1 = dlogtest.returnRandomTrueStatement(); s1 = s1w1.a; w1 = s1w1.b; - Pair s2w2 = dlogtest.returnRandomTrueStatement(); + Pair s2w2 = dlogtest.returnRandomTrueStatement(); s2 = s2w2.a; w2 = s2w2.b; } @Override - void generateRandomFalseStatement() { + protected void generateRandomFalseStatement() { s1 = dlogtest.returnRandomFalseStatement(); s2 = dlogtest.returnRandomFalseStatement(); } diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java similarity index 71% rename from mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java rename to mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java index d305b87..91eca64 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogOrStatementSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java @@ -1,5 +1,8 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; +import meerkat.mixer.proofs.SigmaProtocol; +import meerkat.mixer.proofs.SigmaProtocolTest; +import meerkat.mixer.proofs.generic.SigmaProtocolOr2; import meerkat.protobuf.Mixing; import org.factcenter.qilin.util.Pair; @@ -11,8 +14,8 @@ import java.math.BigInteger; public class DlogOrStatementSigmaTest extends SigmaProtocolTest { final DlogStatementSchnorrSigmaTest dlogtest; - final ECElGamalMixStatementGenerator.AndStatement[] statements = new ECElGamalMixStatementGenerator.AndStatement[2]; - ECElGamalMixStatementGenerator.AndStatementWitness w; + final Statements.AndStatement[] statements = new Statements.AndStatement[2]; + Statements.AndStatementWitness w; int trueStatementIndex; @@ -21,26 +24,26 @@ public class DlogOrStatementSigmaTest extends SigmaProtocolTest s1w1 = dlogtest.returnRandomTrueStatement(); - Pair s2w2 = dlogtest.returnRandomTrueStatement(); - ECElGamalMixStatementGenerator.AndStatement trueStatement = dlogtest.statementGenerator.new AndStatement(s1w1.a, s2w2.a); + Pair s1w1 = dlogtest.returnRandomTrueStatement(); + Pair s2w2 = dlogtest.returnRandomTrueStatement(); + Statements.AndStatement trueStatement = dlogtest.statementGenerator.new AndStatement(s1w1.a, s2w2.a); w = dlogtest.statementGenerator.new AndStatementWitness(s1w1.b, s2w2.b); statements[trueStatementIndex] = trueStatement; - ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + Statements.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + Statements.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixStatementGenerator.AndStatement falseStatement = dlogtest.statementGenerator.new AndStatement(f1, f2); + Statements.AndStatement falseStatement = dlogtest.statementGenerator.new AndStatement(f1, f2); statements[1 - trueStatementIndex] = falseStatement; } @Override - void generateRandomFalseStatement() { - ECElGamalMixStatementGenerator.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); - ECElGamalMixStatementGenerator.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); + protected void generateRandomFalseStatement() { + Statements.DlogStatement f1 = dlogtest.returnRandomFalseStatement(); + Statements.DlogStatement f2 = dlogtest.returnRandomFalseStatement(); statements[0] = dlogtest.statementGenerator.new AndStatement(f1, f2); diff --git a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogStatementSchnorrSigmaTest.java similarity index 69% rename from mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java rename to mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogStatementSchnorrSigmaTest.java index 1da4e21..2e5ebe5 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/DlogStatementSchnorrSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogStatementSchnorrSigmaTest.java @@ -1,7 +1,11 @@ -package meerkat.mixer.proofs; +package meerkat.mixer.proofs.concrete; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.mixer.ECParamTestBase; +import meerkat.mixer.proofs.SigmaProtocol; +import meerkat.mixer.proofs.SigmaProtocolTest; +import meerkat.mixer.proofs.concrete.SchnorrDlogEquivalence; +import meerkat.mixer.proofs.concrete.Statements; import meerkat.protobuf.Mixing; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -16,12 +20,12 @@ public class DlogStatementSchnorrSigmaTest extends SigmaProtocolTest { ECParamTestBase ecParams; - ECElGamalMixStatementGenerator statementGenerator; + Statements statementGenerator; ECElGamalEncryption encryptor; ECGroup group; - ECElGamalMixStatementGenerator.DlogStatement statement; - ECElGamalMixStatementGenerator.DlogStatementWitness witness; + Statements.DlogStatement statement; + Statements.DlogStatementWitness witness; SchnorrDlogEquivalence.Prover prover; SchnorrDlogEquivalence.Verifier verifier; SchnorrDlogEquivalence.Simulator simulator; @@ -30,34 +34,36 @@ public class DlogStatementSchnorrSigmaTest extends ecParams = new ECParamTestBase(); encryptor = ecParams.enc; group = encryptor.getGroup(); - this.statementGenerator = new ECElGamalMixStatementGenerator(ecParams.enc); + this.statementGenerator = new Statements(ecParams.enc); } - Pair returnRandomTrueStatement() { + Pair returnRandomTrueStatement() { BigInteger x = encryptor.generateRandomExponent(rand); ECPoint a = group.multiply(statementGenerator.g, x); ECPoint b = group.multiply(statementGenerator.h, x); - ECElGamalMixStatementGenerator.DlogStatement statement = statementGenerator.new DlogStatement(a, b); - ECElGamalMixStatementGenerator.DlogStatementWitness witness = statementGenerator.new DlogStatementWitness(x); + Statements.DlogStatement statement = statementGenerator.new DlogStatement(a, b); + Statements.DlogStatementWitness witness = statementGenerator.new DlogStatementWitness(x); return new Pair<>(statement, witness); } - ECElGamalMixStatementGenerator.DlogStatement returnRandomFalseStatement() { + Statements.DlogStatement returnRandomFalseStatement() { ECPoint a = group.sample(rand); ECPoint b = group.sample(rand); return statementGenerator.new DlogStatement(a, b); } - void generateRandomTrueStatement() { - Pair sw = returnRandomTrueStatement(); + @Override + protected void generateRandomTrueStatement() { + Pair sw = returnRandomTrueStatement(); this.statement = sw.a; this.witness = sw.b; } - void generateRandomFalseStatement() { + @Override + protected void generateRandomFalseStatement() { witness = null; statement = returnRandomFalseStatement(); } diff --git a/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java similarity index 87% rename from mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java rename to mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java index 710b8fc..4a9c28f 100644 --- a/mixer/src/test/java/meerkat/mixer/Mix2ProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java @@ -1,41 +1,36 @@ -package meerkat.mixer; +package meerkat.mixer.proofs.concrete; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.mixer.proofs.Prover; -import meerkat.mixer.proofs.Verifier; +import meerkat.mixer.ECParamTestBase; +import meerkat.mixer.Utils; +import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import meerkat.protobuf.Voting; //import meerkat.protobuf.Voting.PlaintextBallot; import org.bouncycastle.math.ec.ECPoint; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; -import org.factcenter.qilin.primitives.concrete.ECElGamal; -import org.factcenter.qilin.primitives.concrete.ECGroup; import org.junit.Before; import org.junit.Test; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; -import java.math.BigInteger; -import java.util.Random; - /** * Created by Tzlil on 12/31/2015. */ public class Mix2ProofTest extends ECParamTestBase { + Mix2nizk nizk; Mix2ZeroKnowledgeVerifier verifier ; Mix2ZeroKnowledgeProver prover ; @Before public void setup() throws Exception { - verifier = new Verifier(enc,randomOracle); - prover = new Prover(new Random(),enc,randomOracle); + nizk = new Mix2nizk(rand, enc, randomOracle); + verifier = nizk; + prover = nizk; } private ECPoint convert2ECPoint(ConcreteCrypto.GroupElement bs){ diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index 85015f4..e390486 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -4,7 +4,7 @@ import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.mixer.proofs.Prover; +import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; @@ -43,7 +43,7 @@ public class ZeroKnowledgeProof { enc = new ECElGamalEncryption(); enc.init(serializedPk); RandomOracle randomOracle = new DigestOracle(); - prover = new Prover(new Random(),enc,randomOracle); + prover = new Mix2nizk(new Random(),enc,randomOracle); int LogVotes = 12; int layers = 2*LogVotes - 1; n = layers * (1< Date: Fri, 20 Jan 2017 23:46:51 +0200 Subject: [PATCH 17/25] More refactoring --- .../mixnet/Mix2ZeroKnowledgeProver.java | 20 --------- .../mixnet/Mix2ZeroKnowledgeVerifier.java | 24 ---------- .../java/meerkat/crypto/mixnet/Mixer.java | 15 ------- .../meerkat/crypto/mixnet/MixerOutput.java | 14 ------ .../main/java/meerkat/mixer/MixGenerator.java | 16 +++---- .../main/java/meerkat/mixer/MixVerifier.java | 5 +-- .../main/java/meerkat/mixer/MixerOutput.java | 7 +-- .../meerkat/mixer/main/BatchConverter.java | 2 +- .../java/meerkat/mixer/main/BatchHandler.java | 8 ++-- .../java/meerkat/mixer/main/MainMixing.java | 12 ++--- .../java/meerkat/mixer/proofs/Mix2nizk.java | 44 +++++++++++++++++++ .../mixer/proofs/concrete/Mix2nizk.java | 8 ++-- .../java/meerkat/mixer/CreateTestVector.java | 12 ++--- .../test/java/meerkat/mixer/MixingTest.java | 4 +- .../mixer/proofs/concrete/Mix2ProofTest.java | 7 +-- .../java/profiling/ZeroKnowledgeProof.java | 3 +- 16 files changed, 80 insertions(+), 121 deletions(-) delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java delete mode 100644 mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java create mode 100644 mixer/src/main/java/meerkat/mixer/proofs/Mix2nizk.java diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java deleted file mode 100644 index 3a11c0e..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeProver.java +++ /dev/null @@ -1,20 +0,0 @@ -package meerkat.crypto.mixnet; - -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; - -/** - * Prove in zero knowledge that two ciphertexts are a mix of two original ciphertexts. - */ -public interface Mix2ZeroKnowledgeProver { - public Mixing.Mix2Proof prove(Crypto.RerandomizableEncryptedMessage in1, - Crypto.RerandomizableEncryptedMessage in2, - Crypto.RerandomizableEncryptedMessage out1, - Crypto.RerandomizableEncryptedMessage out2, - boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx, // switch info - Crypto.EncryptionRandomness r1, - Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException; - - -} diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java deleted file mode 100644 index 45bf692..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/Mix2ZeroKnowledgeVerifier.java +++ /dev/null @@ -1,24 +0,0 @@ -package meerkat.crypto.mixnet; - -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; - -/** - * Verify the two-ciphertext mix proof - */ -public interface Mix2ZeroKnowledgeVerifier { - /** - * Return true iff the proof is valid. - * @param in1 - * @param in2 - * @param out1 - * @param out2 - * @return - */ - boolean verify(Crypto.RerandomizableEncryptedMessage in1, - Crypto.RerandomizableEncryptedMessage in2, - Crypto.RerandomizableEncryptedMessage out1, - Crypto.RerandomizableEncryptedMessage out2, - Mixing.Mix2Proof proof) throws InvalidProtocolBufferException; -} diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java b/mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java deleted file mode 100644 index a9b61d7..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/Mixer.java +++ /dev/null @@ -1,15 +0,0 @@ -package meerkat.crypto.mixnet; - -import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.protobuf.Crypto; - -import java.util.List; -import java.util.Random; - -/** - * Created by talm on 25/10/15. - */ -public interface Mixer { - public MixerOutput mix(List ciphertexts,Random random) - throws InvalidProtocolBufferException; -} diff --git a/mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java b/mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java deleted file mode 100644 index 770dc92..0000000 --- a/mixer/src/main/java/meerkat/crypto/mixnet/MixerOutput.java +++ /dev/null @@ -1,14 +0,0 @@ -package meerkat.crypto.mixnet; - -import meerkat.protobuf.Crypto; -import meerkat.protobuf.Mixing; - -/** - * Created by Tzlil on 1/18/2016. - */ -public interface MixerOutput { - public Mixing.Mix2Proof[][] getProofs(); - public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages(); - public int getLogN(); - public int getNumLayers(); -} diff --git a/mixer/src/main/java/meerkat/mixer/MixGenerator.java b/mixer/src/main/java/meerkat/mixer/MixGenerator.java index e4787d6..c901fc7 100644 --- a/mixer/src/main/java/meerkat/mixer/MixGenerator.java +++ b/mixer/src/main/java/meerkat/mixer/MixGenerator.java @@ -2,11 +2,10 @@ package meerkat.mixer; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.Encryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.crypto.mixnet.MixerOutput; import meerkat.mixer.network.BenesNetwork; import meerkat.mixer.network.PermutationNetwork; import meerkat.mixer.network.RandomPermutation; +import meerkat.mixer.proofs.Mix2nizk; import meerkat.protobuf.Crypto.EncryptionRandomness; import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage; import meerkat.protobuf.Mixing.Mix2Proof; @@ -15,18 +14,17 @@ import java.util.List; import java.util.Random; /** - * an implementation of meerkat.crypto.mixnet.Mixer - * meerkat.mixer.network algorithm on set of n encrypted votes: - * 0. asset n is power of two - * 1. set switches according to benes network on random permutation + * Run Abe's permutation network mixing algorithm on set of n encrypted votes: + * 0. n is power of two + * 1. set switches according to Benes network on random permutation * 2. re encrypt and mix with respect to switches values (encryptor.rerandomize) * 3. generate zero knowledge proof on each re encrypted couple * 4. return proofs table + encryption table * */ -public class MixGenerator implements meerkat.crypto.mixnet.Mixer { +public class MixGenerator { - private final Mix2ZeroKnowledgeProver prover; + private final Mix2nizk.Prover prover; private final Encryption encryptor; /** @@ -34,7 +32,7 @@ public class MixGenerator implements meerkat.crypto.mixnet.Mixer { * @param prover * @param encryptor */ - public MixGenerator(Mix2ZeroKnowledgeProver prover, Encryption encryptor) { + public MixGenerator(Mix2nizk.Prover prover, Encryption encryptor) { this.prover = prover; this.encryptor = encryptor; } diff --git a/mixer/src/main/java/meerkat/mixer/MixVerifier.java b/mixer/src/main/java/meerkat/mixer/MixVerifier.java index 8ddd956..e94938c 100644 --- a/mixer/src/main/java/meerkat/mixer/MixVerifier.java +++ b/mixer/src/main/java/meerkat/mixer/MixVerifier.java @@ -1,8 +1,7 @@ package meerkat.mixer; import com.google.protobuf.InvalidProtocolBufferException; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.crypto.mixnet.MixerOutput; +import meerkat.mixer.proofs.Mix2nizk; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -20,7 +19,7 @@ public final class MixVerifier { * @return true iff the meerkat.mixer.network output is valid * @throws InvalidProtocolBufferException */ - public static boolean verifyTable(Mix2ZeroKnowledgeVerifier verifier, MixerOutput mixerOutput) + public static boolean verifyTable(Mix2nizk.Verifier verifier, MixerOutput mixerOutput) throws InvalidProtocolBufferException { int out0,out1,layer, switchIdx; diff --git a/mixer/src/main/java/meerkat/mixer/MixerOutput.java b/mixer/src/main/java/meerkat/mixer/MixerOutput.java index 356bc05..c77d54c 100644 --- a/mixer/src/main/java/meerkat/mixer/MixerOutput.java +++ b/mixer/src/main/java/meerkat/mixer/MixerOutput.java @@ -8,10 +8,9 @@ import java.io.OutputStream; /** * Created by Tzlil on 1/18/2016. - * implements meerkat.crypto.mixnet.MixerOutput interface * container for meerkat.mixer.network.mix result. */ -public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput { +public class MixerOutput { private final Mixing.Mix2Proof[][] proofs; private final Crypto.RerandomizableEncryptedMessage[][] encryptedMessages; private final int logN; @@ -30,22 +29,18 @@ public class MixerOutput implements meerkat.crypto.mixnet.MixerOutput { this.logN = logN; } - @Override public Mixing.Mix2Proof[][] getProofs() { return proofs; } - @Override public Crypto.RerandomizableEncryptedMessage[][] getEncryptedMessages() { return encryptedMessages; } - @Override public int getLogN() { return logN; } - @Override public int getNumLayers() { return 2 * logN - 1; } diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java index a611b22..38541a9 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java @@ -1,6 +1,6 @@ package meerkat.mixer.main; -import meerkat.crypto.mixnet.MixerOutput; +import meerkat.mixer.MixerOutput; import meerkat.protobuf.BulletinBoardAPI; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java index 4aeb582..4886066 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java @@ -1,7 +1,7 @@ package meerkat.mixer.main; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; -import meerkat.crypto.mixnet.MixerOutput; +import meerkat.mixer.MixerOutput; +import meerkat.mixer.proofs.Mix2nizk; import meerkat.protobuf.Crypto; import meerkat.mixer.necessary.AsyncBulletinBoardClient; import meerkat.mixer.necessary.CompleteBatch; @@ -21,13 +21,13 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback mixerInput = generateMixerInput(); diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index 05c8c90..b1f08a0 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -19,7 +19,7 @@ import java.util.Random; public class MixingTest extends ECParamTestBase { Random random,randomMixer,randomProver; Mix2nizk mix2nizk; - meerkat.crypto.mixnet.Mixer mixer; + MixGenerator mixer; private int layers; private int n; @@ -57,7 +57,7 @@ public class MixingTest extends ECParamTestBase { System.out.println(" start network"); long startTime = System.currentTimeMillis(); - meerkat.crypto.mixnet.MixerOutput mixerOutput = mixer.mix(mixerInput,randomMixer); + MixerOutput mixerOutput = mixer.mix(mixerInput,randomMixer); long finishTime = System.currentTimeMillis(); System.out.println(" that took: "+(finishTime-startTime)+ " ms"); diff --git a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java index 4a9c28f..1ee2a42 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java @@ -2,11 +2,8 @@ package meerkat.mixer.proofs.concrete; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.mixer.ECParamTestBase; import meerkat.mixer.Utils; -import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -23,8 +20,8 @@ import static org.junit.Assert.assertTrue; */ public class Mix2ProofTest extends ECParamTestBase { Mix2nizk nizk; - Mix2ZeroKnowledgeVerifier verifier ; - Mix2ZeroKnowledgeProver prover ; + meerkat.mixer.proofs.Mix2nizk.Verifier verifier ; + meerkat.mixer.proofs.Mix2nizk.Prover prover ; @Before public void setup() throws Exception { diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index e390486..94e8f24 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -3,7 +3,6 @@ package profiling; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; @@ -28,7 +27,7 @@ public class ZeroKnowledgeProof { ECGroup group; ECElGamalEncryption enc; ConcreteCrypto.ElGamalPublicKey serializedPk; - Mix2ZeroKnowledgeProver prover ; + meerkat.mixer.proofs.Mix2nizk.Prover prover ; int n; Crypto.EncryptionRandomness[] randomnesses; Crypto.RerandomizableEncryptedMessage[] encryptedMessage; From 43d4fb75b2a3a0c4b5e51e1bd66329f9783f0126 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Sat, 21 Jan 2017 21:42:10 +0200 Subject: [PATCH 18/25] More refactoring, wrote command-line mixer application (no BB access as of yet) --- .../java/meerkat/crypto/concrete/Util.java | 91 ++++++ .../src/main/proto/meerkat/comm.proto | 2 +- mixer/build.gradle | 11 +- mixer/gradlew | 1 + .../main/java/meerkat/mixer/MixGenerator.java | 3 +- .../main/java/meerkat/mixer/MixVerifier.java | 96 ++++-- .../main/java/meerkat/mixer/MixerOutput.java | 70 +++- .../meerkat/mixer/main/BatchConverter.java | 8 +- .../java/meerkat/mixer/main/BatchHandler.java | 22 +- .../java/meerkat/mixer/main/MainMixing.java | 12 +- .../src/main/java/meerkat/mixer/main/Mix.java | 299 ++++++++++++++++++ .../mixer/proofs/concrete/Mix2nizk.java | 1 - .../mixer/proofs/concrete/Statements.java | 2 +- .../java/meerkat/mixer/CreateTestVector.java | 26 +- .../java/meerkat/mixer/ECParamTestBase.java | 3 +- .../test/java/meerkat/mixer/MixingTest.java | 8 +- .../java/meerkat/mixer/RerandomizeTest.java | 8 +- mixer/src/test/java/meerkat/mixer/Utils.java | 60 ---- .../test/java/meerkat/mixer/main/MixTest.java | 120 +++++++ .../mixer/proofs/concrete/Mix2ProofTest.java | 9 +- .../java/profiling/BigInteger/AddSub.java | 3 +- .../BigInteger/GenerateRandomness.java | 3 +- .../java/profiling/BigInteger/Modulo.java | 4 +- .../test/java/profiling/BigInteger/Mul.java | 3 +- .../profiling/Convert/ByteString2ECPoint.java | 6 +- ...bleEncryptedMessage2ElGamalCiphertext.java | 3 +- .../src/test/java/profiling/ECGroup/Add.java | 4 +- .../test/java/profiling/ECGroup/Encode.java | 3 +- .../src/test/java/profiling/ECGroup/Mul.java | 4 +- .../test/java/profiling/ECGroup/Negate.java | 4 +- .../src/test/java/profiling/Rerandomize.java | 5 +- .../java/profiling/ZeroKnowledgeProof.java | 3 +- 32 files changed, 733 insertions(+), 164 deletions(-) create mode 120000 mixer/gradlew create mode 100644 mixer/src/main/java/meerkat/mixer/main/Mix.java create mode 100644 mixer/src/test/java/meerkat/mixer/main/MixTest.java diff --git a/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java b/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java index 4508d0c..e3b83d1 100644 --- a/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java +++ b/meerkat-common/src/main/java/meerkat/crypto/concrete/Util.java @@ -1,14 +1,31 @@ package meerkat.crypto.concrete; import com.google.protobuf.ByteString; +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.Message; +import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; +import org.bouncycastle.jce.spec.ECParameterSpec; +import org.bouncycastle.jce.spec.ECPublicKeySpec; +import org.bouncycastle.math.ec.ECPoint; +import org.factcenter.qilin.primitives.concrete.ECElGamal; +import org.factcenter.qilin.primitives.concrete.ECGroup; +import org.factcenter.qilin.primitives.generic.ElGamal; +import org.factcenter.qilin.util.Pair; +import java.io.ByteArrayInputStream; import java.math.BigInteger; +import java.security.KeyFactory; +import java.security.PublicKey; +import java.security.spec.InvalidKeySpecException; /** * Created by talm on 02/11/16. */ public class Util { + + public final static String ENCRYPTION_KEY_ALGORITHM = ECElGamalEncryption.KEY_ALGORITHM; + /** * Decode a BigInteger from a protobuf * @param i @@ -26,4 +43,78 @@ public class Util { public static Crypto.BigInteger encodeBigInteger(BigInteger i) { return Crypto.BigInteger.newBuilder().setData(ByteString.copyFrom(i.toByteArray())).build(); } + + /** + * Serialize an El-Gamal public key into a form acceptable by {@link ECElGamalEncryption} + * @param pk + * @return + */ + public static ConcreteCrypto.ElGamalPublicKey encodePK(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.getInstance().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); + } + } + + /** + * Deserialize an ECElGamal secret key. + * @param serializedPk + * @param serializedSk + * @return + * @throws InvalidKeySpecException + */ + public static ECElGamal.SK decodeSK(ConcreteCrypto.ElGamalPublicKey serializedPk, Crypto.BigInteger serializedSk) + throws InvalidKeySpecException { + ECElGamalEncryption enc = new ECElGamalEncryption(); + enc.init(serializedPk); + ECElGamal.SK sk = new ECElGamal.SK(enc.getGroup(), decodeBigInteger(serializedSk)); + return sk; + } + + /** + * Standard (non-threshold) decryption for testing purposes. + * @param secretKey + * @return + */ + public static T decrypt(Class plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher) + throws InvalidProtocolBufferException { + ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData()); + ConcreteCrypto.GroupElement c1encoded = cipherText.getC1(); + ConcreteCrypto.GroupElement c2encoded = cipherText.getC2(); + + ECPoint c1 = ECElGamalEncryption.decodeElement(group, c1encoded); + ECPoint c2 = ECElGamalEncryption.decodeElement(group, c2encoded); + + assert (group.contains(c1)); + assert (group.contains(c2)); + + ECPoint plaintextEncoded = secretKey.decrypt(new Pair(c1, c2)); + + byte[] plaintext = group.injectiveDecode(plaintextEncoded); + + ByteArrayInputStream in = new ByteArrayInputStream(plaintext); + + try { + java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder"); + Message.Builder builder = (Message.Builder) newBuilder.invoke(plaintextMessageType); + builder.mergeDelimitedFrom(in); + return plaintextMessageType.cast(builder.build()); + } catch (Exception e) { + throw new InvalidProtocolBufferException("Plaintext protobuf error"); + } + } + + } diff --git a/meerkat-common/src/main/proto/meerkat/comm.proto b/meerkat-common/src/main/proto/meerkat/comm.proto index 6808288..c509165 100644 --- a/meerkat-common/src/main/proto/meerkat/comm.proto +++ b/meerkat-common/src/main/proto/meerkat/comm.proto @@ -10,4 +10,4 @@ message BroadcastMessage { bool is_private = 3; bytes payload = 5; -} \ No newline at end of file +} diff --git a/mixer/build.gradle b/mixer/build.gradle index 2dab24c..3973fa0 100644 --- a/mixer/build.gradle +++ b/mixer/build.gradle @@ -13,8 +13,8 @@ apply plugin: 'maven-publish' // Uncomment the lines below to define an application // (this will also allow you to build a "fatCapsule" which includes // the entire application, including all dependencies in a single jar) -//apply plugin: 'application' -//mainClassName='your.main.ApplicationClass' +apply plugin: 'application' +mainClassName='meerkat.mixer.main.Mix' // Is this a snapshot version? ext { isSnapshot = false } @@ -29,10 +29,10 @@ ext { nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } -description = "TODO: Add a description" +description = "Mix network implementation" // Your project version -version = "0.0" +version = "0.1" version += "${isSnapshot ? '-SNAPSHOT' : ''}" @@ -52,6 +52,9 @@ dependencies { // Crypto compile 'org.factcenter.qilin:qilin:1.2.+' + // Command-line parsing. + compile 'net.sf.jopt-simple:jopt-simple:6.+' + testCompile 'junit:junit:4.+' runtime 'org.codehaus.groovy:groovy:2.4.+' diff --git a/mixer/gradlew b/mixer/gradlew new file mode 120000 index 0000000..502f5a2 --- /dev/null +++ b/mixer/gradlew @@ -0,0 +1 @@ +../gradlew \ No newline at end of file diff --git a/mixer/src/main/java/meerkat/mixer/MixGenerator.java b/mixer/src/main/java/meerkat/mixer/MixGenerator.java index c901fc7..9ba10c2 100644 --- a/mixer/src/main/java/meerkat/mixer/MixGenerator.java +++ b/mixer/src/main/java/meerkat/mixer/MixGenerator.java @@ -176,7 +176,7 @@ public class MixGenerator { * mix given encrypted votes using random * @param ciphertexts encrypted votes * @param random - * @return meerkat.mixer.network result + * @return meerkat.mixProverVerifier.network result * @throws InvalidProtocolBufferException */ public MixerOutput mix(List ciphertexts,Random random) throws InvalidProtocolBufferException { @@ -197,5 +197,4 @@ public class MixGenerator { return new meerkat.mixer.MixerOutput(logN, proofsTable, encryptionTable); } - } \ No newline at end of file diff --git a/mixer/src/main/java/meerkat/mixer/MixVerifier.java b/mixer/src/main/java/meerkat/mixer/MixVerifier.java index e94938c..677bd16 100644 --- a/mixer/src/main/java/meerkat/mixer/MixVerifier.java +++ b/mixer/src/main/java/meerkat/mixer/MixVerifier.java @@ -1,36 +1,54 @@ package meerkat.mixer; import com.google.protobuf.InvalidProtocolBufferException; +import meerkat.mixer.network.BenesNetwork; +import meerkat.mixer.network.PermutationNetwork; import meerkat.mixer.proofs.Mix2nizk; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import java.util.Arrays; /** * Created by Tzlil on 12/30/2015. - * provide one operation - verify meerkat.mixer.network output + * provide one operation - verify meerkat.mixProverVerifier.network output */ public final class MixVerifier { + + final static Logger logger = LoggerFactory.getLogger(MixVerifier.class); /** * constructor * @param verifier * @param mixerOutput - * @return true iff the meerkat.mixer.network output is valid + * @param strict if true, check that the network structure matches our implementation of the Benes network exactly. + * if false, only checks that the result is a permutation. + * @return true iff the meerkat.mixProverVerifier.network output is valid * @throws InvalidProtocolBufferException */ - public static boolean verifyTable(Mix2nizk.Verifier verifier, MixerOutput mixerOutput) + public static boolean verifyTable(Mix2nizk.Verifier verifier, MixerOutput mixerOutput, boolean strict) throws InvalidProtocolBufferException { - int out0,out1,layer, switchIdx; + PermutationNetwork net = null; int layers = mixerOutput.getNumLayers(); int n = 1 << mixerOutput.getLogN(); - //initialize locationChecksum table - // use for check BeneshNet validity - boolean[][] locationChecksum = new boolean[layers][n]; - for (boolean[] locationChecksumLayer: locationChecksum) { - Arrays.fill(locationChecksumLayer,false); + + if (strict) { + net = new BenesNetwork(mixerOutput.getLogN()); + } + + //initialize outputUsed table + // used to check BeneshNet validity + boolean[][] outputUsed = new boolean[layers][n]; + for (boolean[] outputUsedLayer: outputUsed) { + Arrays.fill(outputUsedLayer,false); + } + + boolean[][] switchUsed = new boolean[layers][n / 2]; + for (boolean[] switchUsedLayer: switchUsed) { + Arrays.fill(switchUsedLayer,false); } Mixing.Mix2Proof[][] Mix2Proofs = mixerOutput.getProofs(); @@ -38,6 +56,8 @@ public final class MixVerifier { for (int i = 0; i < Mix2Proofs.length ; i++){ for (int j = 0; j < Mix2Proofs[i].length ; j ++){ + int out0,out1,layer, switchIdx; + Mixing.Mix2Proof zkp = Mix2Proofs[i][j]; Mixing.Mix2Proof.Location location = zkp.getLocation(); out0 = location.getOut0(); @@ -45,20 +65,38 @@ public final class MixVerifier { layer = location.getLayer(); switchIdx = location.getSwitchIdx(); - // check location validity - // TODO: add check -// if (layer > layers >> 1) { -// if (out1 - out0 != n >> (layers - layer)) -// return false; -// } -// else{ -// if (out1 - out0 != n >> (layer + 1)) -// return false; -// } + if (strict) { + // Check that location is correct + int expectedOut0 = net.getInputIdxInNextLayer(layer, 2 * switchIdx); + if (out0 != expectedOut0) { + logger.error("Input {} in layer {} goes to {} instead of {}", 2 * switchIdx, layer, out0, expectedOut0); + return false; + } + int expectedOut1 = net.getInputIdxInNextLayer(layer, 2 * switchIdx + 1); + if (out0 != expectedOut0) { + logger.error("Input {} in layer {} goes to {} instead of {}", 2 * switchIdx + 1, layer, out1, expectedOut1); + return false; + } + } // mark location in table - locationChecksum[layer][2 * switchIdx] = true; - locationChecksum[layer][2 * switchIdx + 1] = true; + if (switchUsed[layer][switchIdx]) { + logger.error("Switch {} in layer {} used twice!", switchIdx, layer); + return false; + } + switchUsed[layer][switchIdx] = true; + + if (outputUsed[layer][out0]) { + logger.error("Output {} in layer {} used twice!", out0, layer); + return false; + } + outputUsed[layer][out0] = true; + + if (outputUsed[layer][out1]) { + logger.error("Output {} in layer {} used twice!", out1, layer); + return false; + } + outputUsed[layer][out1] = true; // verify proof if(!verifier.verify(rerandomizableEncryptedMessages[layer][2 * switchIdx], @@ -71,11 +109,19 @@ public final class MixVerifier { } } - // verify all meerkat.mixer.necessary locations for BeneshNet were proved - for (boolean[] checksumLayer: locationChecksum) { - for (boolean locationBoolean: checksumLayer) { - if (!locationBoolean) + // verify all meerkat.mixProverVerifier.necessary locations for BenesNet were proved + for (int layer = 0; layer < layers; ++layer) { + for (int switchIdx = 0; switchIdx < n / 2; ++switchIdx) { + if (!switchUsed[layer][switchIdx]) { + logger.error("Switch {} in layer {} was not used!", switchIdx, layer); return false; + } + } + for (int i = 0; i < n / 2; ++i) { + if (!outputUsed[layer][i]) { + logger.error("Output {} in layer {} was not used!", i, layer); + return false; + } } } return true; diff --git a/mixer/src/main/java/meerkat/mixer/MixerOutput.java b/mixer/src/main/java/meerkat/mixer/MixerOutput.java index c77d54c..370fefe 100644 --- a/mixer/src/main/java/meerkat/mixer/MixerOutput.java +++ b/mixer/src/main/java/meerkat/mixer/MixerOutput.java @@ -3,12 +3,14 @@ package meerkat.mixer; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; +import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; /** * Created by Tzlil on 1/18/2016. - * container for meerkat.mixer.network.mix result. + * container for meerkat.mixProverVerifier.network.mix result. */ public class MixerOutput { private final Mixing.Mix2Proof[][] proofs; @@ -20,7 +22,9 @@ public class MixerOutput { * @param logN log (base 2) of the number of votes * @param encryptedMessages at level 0 , contains the original encrypted votes * at each other level contains the re encrypted votes - * @param proofs in each cell (level,switch) contains the match zero knowledge proof + * @param proofs in each cell (level,switch) contains the match zero knowledge proof. + * We allow null proofs as a special case -- this is used to store the input to the + * first mixProverVerifier (as a 0-layer mix). */ public MixerOutput(int logN, Mixing.Mix2Proof[][] proofs, Crypto.RerandomizableEncryptedMessage[][] encryptedMessages) { @@ -42,6 +46,66 @@ public class MixerOutput { } public int getNumLayers() { - return 2 * logN - 1; + return proofs == null ? 0 : proofs.length; } + + + /** + * Read from an InputStream. The data should have been written by {@link #writeDelimitedTo(OutputStream)} + * @param in + * @return + * @throws IOException + */ + public static MixerOutput parseDelimitedFrom(InputStream in) throws IOException { + Mixing.MixBatchHeader header = Mixing.MixBatchHeader.parseDelimitedFrom(in); + int n = 1 << header.getLogN(); + int layers = header.getLayers(); + + Crypto.RerandomizableEncryptedMessage[][] encryptedMessages = new Crypto.RerandomizableEncryptedMessage[layers + 1][n]; + Mixing.Mix2Proof[][] proofs = null; + if (layers > 0) + proofs = new Mixing.Mix2Proof[header.getLayers()][n / 2]; + + for (int i = 0; i < encryptedMessages.length; ++i) { + for (int j = 0; j < encryptedMessages[i].length; ++j) { + encryptedMessages[i][j] = Crypto.RerandomizableEncryptedMessage.parseDelimitedFrom(in); + } + } + if (layers > 0) { + for (int i = 0; i < proofs.length; ++i) { + for (int j = 0; j < proofs[i].length; ++j) { + proofs[i][j] = Mixing.Mix2Proof.parseDelimitedFrom(in); + } + } + } + return new MixerOutput(header.getLogN(), proofs, encryptedMessages); + } + + /** + * Write to an outputstream. + * This format can be parsed by {@link #parseDelimitedFrom(InputStream)} + * @param out + * @throws IOException + */ + public void writeDelimitedTo(OutputStream out) throws IOException { + Mixing.MixBatchHeader header = Mixing.MixBatchHeader.newBuilder() + .setLogN(getLogN()) + .setLayers(getNumLayers()) + .build(); + header.writeDelimitedTo(out); + + for (int i = 0; i < encryptedMessages.length; ++i) { + for (int j = 0; j < encryptedMessages[i].length; ++j) { + encryptedMessages[i][j].writeDelimitedTo(out); + } + } + if (proofs != null) { + for (int i = 0; i < proofs.length; ++i) { + for (int j = 0; j < proofs[i].length; ++j) { + proofs[i][j].writeDelimitedTo(out); + } + } + } + } + } diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java index 38541a9..ea78f80 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchConverter.java @@ -10,13 +10,13 @@ import java.util.List; /** * Created by Tzlil on 12/17/2015. - * provide convert operation from batch data to meerkat.mixer.network output and backwards + * provide convert operation from batch data to meerkat.mixProverVerifier.network output and backwards */ public class BatchConverter { /** - * convert meerkat.mixer.network output to batch data + * convert meerkat.mixProverVerifier.network output to batch data * @param mixerOutput - * @return meerkat.mixer.network output as list of batch data + * @return meerkat.mixProverVerifier.network output as list of batch data */ public List MixerOutput2BatchChunk(MixerOutput mixerOutput) { @@ -49,7 +49,7 @@ public class BatchConverter { } /** - * convert batch data list to meerkat.mixer.network output + * convert batch data list to meerkat.mixProverVerifier.network output * @param batchChunkList * @return batch data list as MixerOutput * @throws Exception diff --git a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java index 4886066..2fb9ef5 100644 --- a/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java +++ b/mixer/src/main/java/meerkat/mixer/main/BatchHandler.java @@ -12,8 +12,8 @@ import java.util.List; /** * Created by Tzlil on 12/17/2015. - * implements AsyncBulletinBoardClient.ClientCallback - */ + * Handles callback for receiving a complete mix proof table from the bulletin board. + */ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback { private MixerOutput mixerOutput; @@ -61,7 +61,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback getInputForMixer() throws Throwable { + public List getInputForMixer(boolean strictVerification) throws Throwable { if (t != null) { throw t; } - if(!verifyTable()){ - throw new Exception("in valid table"); + if(!verifyTable(strictVerification)){ + throw new Exception("invalid table"); } - return Arrays.asList(mixerOutput.getEncryptedMessages()[mixerOutput.getNumLayers()]);//there are layers + 1 + return Arrays.asList(mixerOutput.getEncryptedMessages()[mixerOutput.getNumLayers()]); //there are layers + 1 } } diff --git a/mixer/src/main/java/meerkat/mixer/main/MainMixing.java b/mixer/src/main/java/meerkat/mixer/main/MainMixing.java index a28ca40..f32cb9f 100644 --- a/mixer/src/main/java/meerkat/mixer/main/MainMixing.java +++ b/mixer/src/main/java/meerkat/mixer/main/MainMixing.java @@ -15,11 +15,11 @@ import java.util.Random; /** * Created by Tzlil on 12/17/2015. - * this class define all the operation meerkat.mixer.network party should do: + * this class define all the operation meerkat.mixProverVerifier.network party should do: * 1. receive previous mixers output (re encrypted votes + proofs) * 2. verify its input * 3. mix - * 4. send the meerkat.mixer.network output + * 4. send the meerkat.mixProverVerifier.network output */ public class MainMixing { @@ -52,7 +52,7 @@ public class MainMixing { * @param callback * @throws Throwable */ - public void main(List prevBatchIds, int batchId, Random random, AsyncBulletinBoardClient.ClientCallback callback) throws Throwable { + public void main(List prevBatchIds, int batchId, boolean strictVerification, Random random, AsyncBulletinBoardClient.ClientCallback callback) throws Throwable { List mixerInput; @@ -72,13 +72,13 @@ public class MainMixing { } // assert all handlers succeeded for (BatchHandler batchHandler : batchHandlers) { - if(!batchHandler.verifyTable()){ + if(!batchHandler.verifyTable(strictVerification)){ throw new Exception("invalid input"); } } BatchHandler lastBatchHandler = batchHandlers.get(batchHandlers.size() - 1); - mixerInput = lastBatchHandler.getInputForMixer(); + mixerInput = lastBatchHandler.getInputForMixer(strictVerification); MixerOutput mixerOutput = mixer.mix(mixerInput,random); updateBB(mixerOutput, batchId, callback); @@ -86,7 +86,7 @@ public class MainMixing { } /** - * send meerkat.mixer.network output to BB + * send meerkat.mixProverVerifier.network output to BB * @param mixerOutput * @param batchId * @param callback diff --git a/mixer/src/main/java/meerkat/mixer/main/Mix.java b/mixer/src/main/java/meerkat/mixer/main/Mix.java new file mode 100644 index 0000000..03cc467 --- /dev/null +++ b/mixer/src/main/java/meerkat/mixer/main/Mix.java @@ -0,0 +1,299 @@ +package meerkat.mixer.main; + +import com.google.protobuf.InvalidProtocolBufferException; +import com.google.protobuf.StringValue; +import joptsimple.OptionParser; +import joptsimple.OptionSet; +import joptsimple.OptionSpec; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.mixer.MixGenerator; +import meerkat.mixer.MixVerifier; +import meerkat.mixer.MixerOutput; +import meerkat.mixer.proofs.concrete.Mix2nizk; +import meerkat.protobuf.ConcreteCrypto; +import meerkat.protobuf.Crypto; +import org.factcenter.qilin.primitives.RandomOracle; +import org.factcenter.qilin.primitives.concrete.DigestOracle; +import org.factcenter.qilin.primitives.concrete.ECElGamal; +import org.factcenter.qilin.primitives.concrete.ECGroup; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import java.io.*; +import java.math.BigInteger; +import java.security.SecureRandom; +import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.Random; + +import static java.lang.System.exit; +import static java.lang.System.in; + +/** + * Command-line mixProverVerifier and verifier. + */ +public class Mix { + final static Logger logger = LoggerFactory.getLogger(Mix.class); + public Random rand; + public ECGroup group; + public ECElGamalEncryption enc; + public RandomOracle randomOracle; + public ConcreteCrypto.ElGamalPublicKey serializedPk; + public ECElGamal.SK secretKey; + public Mix2nizk mixProverVerifier; + + public MixerOutput inMix; + + public Mix() { + rand = new SecureRandom(); + randomOracle = new DigestOracle(); + enc = new ECElGamalEncryption(); + serializedPk = null; + secretKey = null; + } + + public void loadMix(File inFile) throws IOException { + + assert(serializedPk != null); + InputStream in = new FileInputStream(inFile); + inMix = MixerOutput.parseDelimitedFrom(in); + in.close(); + logger.info("Loaded mixnet with {} layers and logN={}", inMix.getNumLayers(), inMix.getLogN()); + } + + public boolean verify(boolean strict) { + try { + logger.info("Starting verification of {} ciphertexts", 1 << inMix.getLogN()); + long startTime = System.currentTimeMillis(); + boolean ok = MixVerifier.verifyTable(mixProverVerifier, inMix, strict); + long endTime = System.currentTimeMillis(); + logger.info("Verification took {} seconds", (endTime - startTime) / 1000f); + return ok; + } catch (InvalidProtocolBufferException e) { + logger.error("Badly formatted encryptions", e); + return false; + } + } + + public void mix(File outFile) throws IOException { + MixGenerator mixer = new MixGenerator(mixProverVerifier, enc); + + List encryptedMessages = Arrays.asList(inMix.getEncryptedMessages()[inMix.getNumLayers()]); + + logger.info("Starting mix of {} ciphertexts", encryptedMessages.size()); + long startTime = System.currentTimeMillis(); + MixerOutput outMix = mixer.mix(encryptedMessages, rand); + long endTime = System.currentTimeMillis(); + logger.info("Mix done (took {} seconds)", (endTime - startTime) / 1000f); + + OutputStream out = new FileOutputStream(outFile); + outMix.writeDelimitedTo(out); + out.close(); + } + + + // For testing purposes + + public void setPK(ConcreteCrypto.ElGamalPublicKey serializedPk) { + this.serializedPk = serializedPk; + + try { + enc.init(serializedPk); + group = enc.getGroup(); + } catch (InvalidKeySpecException e) { + logger.error("Invalid EC-ElGamal public key", e); + exit(-2); + } + + mixProverVerifier = new Mix2nizk(rand, enc, randomOracle); + } + + /** + * Create a new ECElGamal key pair and write it serialized to file. + * + * @param outFile + */ + public void createKeypair(File outFile) throws IOException { + group = new ECGroup("secp256k1"); + BigInteger sk = ECElGamal.generateSecretKey(group, rand); + secretKey = new ECElGamal.SK(group, sk); + + serializedPk = Util.encodePK(group, secretKey); + setPK(serializedPk); + Crypto.BigInteger serializedSk = Util.encodeBigInteger(sk); + + OutputStream out = new FileOutputStream(outFile); + + serializedPk.writeDelimitedTo(out); + serializedSk.writeDelimitedTo(out); + + out.close(); + } + + /** + * Loads a public key and optionally a secret key from a file. + * @param inFile + * @throws IOException + * @throws InvalidKeySpecException + */ + public void loadKeypair(File inFile) throws IOException, InvalidKeySpecException { + InputStream in = new FileInputStream(inFile); + serializedPk = ConcreteCrypto.ElGamalPublicKey.parseDelimitedFrom(in); + + setPK(serializedPk); + + try { + Crypto.BigInteger serializedSk = Crypto.BigInteger.parseDelimitedFrom(in); + secretKey = Util.decodeSK(serializedPk, serializedSk); + } catch (EOFException e) { + logger.debug("File {} does not have a secret key", inFile); + } finally { + in.close(); + } + } + + + /** + * Decrypt the output of a mixnet + * Outputs to a file, one line per decoded element. + * + * @throws IOException + */ + public void decrypt(File outFile) throws IOException { + PrintStream out = new PrintStream(outFile); + + assert(inMix != null); + assert(inMix.getEncryptedMessages() != null); + + logger.info("Decrypting {} ciphertexts", inMix.getEncryptedMessages()[inMix.getNumLayers()].length); + for (Crypto.RerandomizableEncryptedMessage ciphertext : inMix.getEncryptedMessages()[inMix.getNumLayers()]) { + StringValue plaintext = Util.decrypt(StringValue.class, secretKey, group, ciphertext); + out.println(plaintext.getValue()); + } + + out.close(); + } + + public void encrypt(File inFile, File outFile) throws IOException { + BufferedReader in = new BufferedReader(new InputStreamReader(new FileInputStream(inFile))); + + ArrayList lines = new ArrayList<>(); + String line; + while ((line = in.readLine()) != null) { + lines.add(line); + } + in.close(); + + int n = lines.size(); + int logN = 32 - Integer.numberOfLeadingZeros(n - 1); + n = 1 << logN; // We need the smallest power of 2 greater than the size + + + Crypto.RerandomizableEncryptedMessage ciphers[][] = new Crypto.RerandomizableEncryptedMessage[1][n]; + + logger.info("Encrypting {} plaintexts (padded to {})", lines.size(), n); + for (int i = 0; i < lines.size(); ++i) { + ciphers[0][i] = enc.encrypt(StringValue.newBuilder().setValue(lines.get(i)).build(), enc.generateRandomness(rand)); + } + + // Pad with empty values + StringValue empty = StringValue.newBuilder().setValue("").build(); + for (int i = lines.size(); i < n; ++i) { + ciphers[0][i] = enc.encrypt(empty, enc.generateRandomness(rand)); + } + + inMix = new MixerOutput(logN, null, ciphers); + + OutputStream out = new FileOutputStream(outFile); + inMix.writeDelimitedTo(out); + out.close(); + logger.info("Wrote mixnet with {} layers and logN={}", inMix.getNumLayers(), inMix.getLogN()); + } + + + static void printHelp(OptionParser parser) { + printHelp(null, parser); + } + + static void printHelp(String msg, OptionParser parser) { + if (msg != null) + System.out.println(msg); + try { + parser.printHelpOn(System.out); + } catch (IOException e) { + // should never happen + } + } + + public static void main(String[] args) { + OptionParser parser = new OptionParser(); + final OptionSpec OPT_HELP = parser.accepts("help", "Print help"); + final OptionSpec OPT_GENKEY = parser.accepts("genkey", "Generate a key-pair (write into key file)"); + final OptionSpec OPT_DECRYPT = parser.accepts("decrypt", "Decrypt using given keypair"); + final OptionSpec OPT_KEYFILE = parser.accepts("keys", "File containing public key (or keypair for decryption)").withRequiredArg().ofType(File.class); + final OptionSpec OPT_ENCRYPT = parser.accepts("encrypt", "Decrypt using given keypair"); + final OptionSpec OPT_STRICT = parser.accepts("strict", "Use strict verification (verify that network matches our Benes implementation)"); + final OptionSpec OPT_INPUTFILE = parser.accepts("infile", "Input file (if mixing, should contain ciphertext or mixProverVerifier output; if verifying, mixProverVerifier output)").withRequiredArg().ofType(File.class); + final OptionSpec OPT_OUTPUTFILE = parser.accepts("outfile", "Output file. If given, operate in Mix mode; otherwise in verify mode.").withRequiredArg().ofType(File.class); + + OptionSet options = parser.parse(args); + if (options.has(OPT_HELP)) { + printHelp(parser); + return; + } + + File keyFile = options.valueOf(OPT_KEYFILE); + if (keyFile == null) { + printHelp("Must specify key file", parser); + return; + } + + File inFile = options.valueOf(OPT_INPUTFILE); + if ((inFile == null || !inFile.canRead()) && !options.has(OPT_GENKEY)) { + printHelp("Must specify input file except for key generation" + (inFile.canRead() ? "" : " (can't read inFile)"), parser); + return; + } + + + File outFile = options.valueOf(OPT_OUTPUTFILE); + + Mix mix = new Mix(); + + try { + if (options.has(OPT_GENKEY)) { + mix.createKeypair(keyFile); + } else { + mix.loadKeypair(keyFile); + if (options.has(OPT_ENCRYPT)) { + mix.encrypt(inFile, outFile); + } else if (options.has(OPT_DECRYPT)) { + mix.loadMix(inFile); + mix.decrypt(outFile); + } else if (options.has(OPT_OUTPUTFILE)) { + // Mix mode + mix.loadMix(inFile); + mix.mix(outFile); + } else { + mix.loadMix(inFile); + boolean ok = mix.verify(options.has(OPT_STRICT)); + if (ok) { + logger.info("Verification successful"); + } else { + logger.error("Verification failed!"); + exit(-1); + } + } + } + } catch (FileNotFoundException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (InvalidKeySpecException e) { + e.printStackTrace(); + } + + } +} diff --git a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java index 1bc1be4..5e43851 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java @@ -56,7 +56,6 @@ public class Mix2nizk implements Prover, Verifier { Crypto.RerandomizableEncryptedMessage c, Crypto.RerandomizableEncryptedMessage d, boolean switched, int layer, int switchIdx, int out0Idx, int out1Idx, - Crypto.EncryptionRandomness r1, Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { diff --git a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java index 92c8ba7..6c41b43 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Statements.java @@ -13,7 +13,7 @@ import java.math.BigInteger; /** * used for organizing the input for each ZKP * - * both meerkat.mixer.proofs and meerkat.mixer.verifier implementation use it + * both meerkat.mixProverVerifier.proofs and meerkat.mixProverVerifier.verifier implementation use it */ public class Statements { diff --git a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java index feb300e..17df70a 100644 --- a/mixer/src/test/java/meerkat/mixer/CreateTestVector.java +++ b/mixer/src/test/java/meerkat/mixer/CreateTestVector.java @@ -1,13 +1,13 @@ //package meerkat.mixer; // //import meerkat.crypto.concrete.ECElGamalEncryption; -//import meerkat.mixer.proofs.Mix2nizk.Prover; -//import meerkat.mixer.proofs.Mix2nizk.Verifier; -//import meerkat.mixer.Mixer; -//import meerkat.mixer.MixerOutput; -//import meerkat.mixer.proofs.Prover; -//import meerkat.mixer.proofs.Verifier; -//import meerkat.mixer.VerifyTable; +//import meerkat.mixProverVerifier.proofs.Mix2nizk.Prover; +//import meerkat.mixProverVerifier.proofs.Mix2nizk.Verifier; +//import meerkat.mixProverVerifier.Mixer; +//import meerkat.mixProverVerifier.MixerOutput; +//import meerkat.mixProverVerifier.proofs.Prover; +//import meerkat.mixProverVerifier.proofs.Verifier; +//import meerkat.mixProverVerifier.VerifyTable; //import meerkat.protobuf.Crypto; //import meerkat.protobuf.Voting; //import org.factcenter.qilin.primitives.RandomOracle; @@ -34,7 +34,7 @@ // RandomOracle randomOracle; // Verifier verifier; // Prover prover; -// meerkat.crypto.mixnet.Mixer mixer; +// meerkat.crypto.mixnet.Mixer mixProverVerifier; // private int layers; // private int n; // @@ -45,13 +45,13 @@ // random = new Random(); // group = new ECGroup("secp256k1"); // encryptor = new ECElGamalEncryption(); -// encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); +// encryptor.init(Utils.encodePK(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // randomMixer = new Random(); // randomProver = new Random(); // randomOracle = new DigestOracle(); // verifier = new Verifier(encryptor,randomOracle); // prover = new Prover(randomProver,encryptor,randomOracle); -// mixer = new Mixer(prover,encryptor); +// mixProverVerifier = new Mixer(prover,encryptor); // // // generate n // int logN = 10; // + random.nextInt(8) @@ -73,7 +73,7 @@ // // List mixerInput = generateMixerInput(); // System.out.println("start network"); -// MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,randomMixer); +// MixerOutput mixerOutput = (MixerOutput)mixProverVerifier.mix(mixerInput,randomMixer); // System.out.println("network ended, start verification"); // assert (VerifyTable.verifyTable(verifier,n,mixerOutput)); // System.out.println("verification ended, start printing"); @@ -86,11 +86,11 @@ // // //Verifier corruptedVerifier = new Verifier(enc,randomOracle,true); // //Prover corruptedProver = new Prover(randomProver,enc,randomOracle,true); -// //mixer = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); +// //mixProverVerifier = new Mixer(randomMixer,corruptedProver,enc,corruptedVerifier); // // List mixerInput = generateMixerInput(); // System.out.println("start network"); -// MixerOutput mixerOutput = (MixerOutput)mixer.mix(mixerInput,random); +// MixerOutput mixerOutput = (MixerOutput)mixProverVerifier.mix(mixerInput,random); // System.out.println("network ended, start negative verification"); // assert (!VerifyTable.verifyTable(verifier,n,mixerOutput)); // System.out.println("verification ended, start printing"); diff --git a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java index 927aff5..0c187cf 100644 --- a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java +++ b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java @@ -1,6 +1,7 @@ package meerkat.mixer; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.DigestOracle; @@ -28,7 +29,7 @@ public class ECParamTestBase { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); try { enc.init(serializedPk); diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index b1f08a0..344e42f 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -20,7 +20,6 @@ public class MixingTest extends ECParamTestBase { Random random,randomMixer,randomProver; Mix2nizk mix2nizk; MixGenerator mixer; - private int layers; private int n; @@ -35,11 +34,10 @@ public class MixingTest extends ECParamTestBase { // generate n int logN = 5; // + random.nextInt(8) - layers = 2*logN - 1; n = 1 << logN; } - public List generateMixerInput(){ + public List generateMixerInput(int n){ List result = new ArrayList(); Voting.PlaintextBallot msg; for (int i = 0; i < n ; i++){ @@ -53,7 +51,7 @@ public class MixingTest extends ECParamTestBase { public void mixingTest() throws InvalidProtocolBufferException { System.out.println("n is : " + n); System.out.println(" generating input"); - List mixerInput = generateMixerInput(); + List mixerInput = generateMixerInput(n); System.out.println(" start network"); long startTime = System.currentTimeMillis(); @@ -65,7 +63,7 @@ public class MixingTest extends ECParamTestBase { System.out.println("start verification"); startTime = System.currentTimeMillis(); - assert (MixVerifier.verifyTable(mix2nizk, mixerOutput)); + assert (MixVerifier.verifyTable(mix2nizk, mixerOutput, true)); finishTime = System.currentTimeMillis(); System.out.println(" that took: "+(finishTime-startTime)+ " ms"); diff --git a/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java b/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java index 860dafd..52a7482 100644 --- a/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java +++ b/mixer/src/test/java/meerkat/mixer/RerandomizeTest.java @@ -1,8 +1,8 @@ package meerkat.mixer; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; @@ -35,7 +35,7 @@ public class RerandomizeTest { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); RandomOracle randomOracle = new DigestOracle(); @@ -56,8 +56,8 @@ public class RerandomizeTest { Crypto.RerandomizableEncryptedMessage e = enc.encrypt(msg, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage eNew = enc.rerandomize(e, r); - assert (Utils.decrypt(Voting.PlaintextBallot.class, key, group, e).equals(msg)); - assert (Utils.decrypt(Voting.PlaintextBallot.class, key, group, eNew).equals(msg)); + assert (Util.decrypt(Voting.PlaintextBallot.class, key, group, e).equals(msg)); + assert (Util.decrypt(Voting.PlaintextBallot.class, key, group, eNew).equals(msg)); ConcreteCrypto.ElGamalCiphertext eElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(e); ConcreteCrypto.ElGamalCiphertext eNewElGamal = ECElGamalEncryption.RerandomizableEncryptedMessage2ElGamalCiphertext(eNew); diff --git a/mixer/src/test/java/meerkat/mixer/Utils.java b/mixer/src/test/java/meerkat/mixer/Utils.java index c402876..3852c8d 100644 --- a/mixer/src/test/java/meerkat/mixer/Utils.java +++ b/mixer/src/test/java/meerkat/mixer/Utils.java @@ -27,66 +27,6 @@ import java.util.Random; * Created by Tzlil on 1/1/2016. */ public class Utils { - - - 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.getInstance().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); - } - } - - /** - * Standard (non-threshold) decryption for testing purposes. - * @param secretKey - * @return - */ - public static T decrypt(Class plaintextMessageType, ECElGamal.SK secretKey, ECGroup group, Crypto.RerandomizableEncryptedMessage opaqueCipher) - throws InvalidProtocolBufferException { - ConcreteCrypto.ElGamalCiphertext cipherText = ConcreteCrypto.ElGamalCiphertext.parseFrom(opaqueCipher.getData()); - ConcreteCrypto.GroupElement c1encoded = cipherText.getC1(); - ConcreteCrypto.GroupElement c2encoded = cipherText.getC2(); - - ECPoint c1 = ECElGamalEncryption.decodeElement(group, c1encoded); - ECPoint c2 = ECElGamalEncryption.decodeElement(group, c2encoded); - - assert (group.contains(c1)); - assert (group.contains(c2)); - - ECPoint plaintextEncoded = secretKey.decrypt(new Pair(c1, c2)); - - byte[] plaintext = group.injectiveDecode(plaintextEncoded); - - ByteArrayInputStream in = new ByteArrayInputStream(plaintext); - - try { - java.lang.reflect.Method newBuilder = plaintextMessageType.getMethod("newBuilder"); - Message.Builder builder = (Message.Builder) newBuilder.invoke(plaintextMessageType); - builder.mergeDelimitedFrom(in); - return plaintextMessageType.cast(builder.build()); - } catch (Exception e) { - throw new InvalidProtocolBufferException("Plaintext protobuf error"); - } - } - static Random random = new Random(0); public static Voting.PlaintextBallot genRandomBallot(int numQuestions, int numAnswers, int maxAnswer) { diff --git a/mixer/src/test/java/meerkat/mixer/main/MixTest.java b/mixer/src/test/java/meerkat/mixer/main/MixTest.java new file mode 100644 index 0000000..83e4c56 --- /dev/null +++ b/mixer/src/test/java/meerkat/mixer/main/MixTest.java @@ -0,0 +1,120 @@ +package meerkat.mixer.main; + +import com.google.protobuf.StringValue; +import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.protobuf.Crypto; +import org.factcenter.qilin.primitives.concrete.ECElGamal; +import org.junit.Before; +import org.junit.Test; + +import java.io.*; +import java.util.Random; + +import static org.junit.Assert.*; + +/** + * Created by talm on 21/01/17. + */ +public class MixTest { + public Mix mix; + Random rand = new Random(1); + + @Before + public void setUp() throws Exception { + mix = new Mix(); + } + + @Test + public void testKeygen() throws Exception { + File tmpKeys = File.createTempFile("elgamal", "key"); + mix.createKeypair(tmpKeys); + + ECElGamal.SK secretKey = mix.secretKey; + assertNotNull(secretKey); + assertNotNull(mix.serializedPk); + + Mix newMix = new Mix(); + + newMix.loadKeypair(tmpKeys); + assertEquals(mix.serializedPk, newMix.serializedPk); + + StringValue tst = StringValue.newBuilder().setValue("test").build(); + + Crypto.RerandomizableEncryptedMessage cipher = mix.enc.encrypt(tst, mix.enc.generateRandomness(rand)); + StringValue newTst = Util.decrypt(StringValue.class, newMix.secretKey, newMix.enc.getGroup(), cipher); + + assertEquals(tst, newTst); + + } + + File createPlaintexts(int n) throws Exception { + File tmpData = File.createTempFile("plaintext", "txt"); + PrintStream out = new PrintStream(tmpData); + + for (int i = 0; i < n; ++i) { + out.println("Line " + i); + } + + out.close(); + + return tmpData; + } + + @Test + public void testEncryptDecrypt() throws Exception { + File tmpKeys = File.createTempFile("elgamal", "key"); + mix.createKeypair(tmpKeys); + + int n = 35; + File plaintexts = createPlaintexts(n); + File ciphertexts = File.createTempFile("ciphertexts", "bin"); + mix.encrypt(plaintexts, ciphertexts); + + Mix newMix = new Mix(); + newMix.loadKeypair(tmpKeys); + newMix.loadMix(ciphertexts); + File newPlaintexts = File.createTempFile("plaintexts2", "txt"); + newMix.decrypt(newPlaintexts); + + BufferedReader in1 = new BufferedReader(new FileReader(plaintexts)); + BufferedReader in2 = new BufferedReader(new FileReader(newPlaintexts)); + + int n2 = 1 << newMix.inMix.getLogN(); + assert(n2 >= n); + + for (int i = 0; i < n; ++i) { + String line1 = in1.readLine(); + String line2 = in2.readLine(); + assertEquals(line1, line2); + } + + for (int i = n; i < n2; ++i) { + String line2 = in2.readLine(); + assertEquals("", line2); + } + } + + @Test + public void testMixVerify() throws Exception { + File tmpKeys = File.createTempFile("elgamal", "key"); + mix.createKeypair(tmpKeys); + + int n = 35; + File plaintexts = createPlaintexts(n); + File ciphertexts = File.createTempFile("ciphertexts", "enc"); + mix.encrypt(plaintexts, ciphertexts); + + File mixedFile = File.createTempFile("mixed", "enc"); + Mix newMix1 = new Mix(); + newMix1.loadKeypair(tmpKeys); + newMix1.loadMix(ciphertexts); + newMix1.mix(mixedFile); + + Mix newMix2 = new Mix(); + newMix2.loadKeypair(tmpKeys); + newMix2.loadMix(mixedFile); + boolean ok = newMix2.verify(true); + assertTrue(ok); + } +} \ No newline at end of file diff --git a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java index 1ee2a42..d4c4b77 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java @@ -2,6 +2,7 @@ package meerkat.mixer.proofs.concrete; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.mixer.ECParamTestBase; import meerkat.mixer.Utils; import meerkat.protobuf.ConcreteCrypto; @@ -45,10 +46,10 @@ public class Mix2ProofTest extends ECParamTestBase { Crypto.RerandomizableEncryptedMessage e1New = enc.rerandomize(e1, r1); Crypto.RerandomizableEncryptedMessage e2New = enc.rerandomize(e2, r2); - assertEquals (Utils.decrypt(Voting.PlaintextBallot.class, key, group, e1), msg1); - assertEquals (Utils.decrypt(Voting.PlaintextBallot.class, key, group, e1New), msg1); - assertEquals (Utils.decrypt(Voting.PlaintextBallot.class, key, group, e2), msg2); - assertEquals (Utils.decrypt(Voting.PlaintextBallot.class, key, group, e2New), msg2); + assertEquals (Util.decrypt(Voting.PlaintextBallot.class, key, group, e1), msg1); + assertEquals (Util.decrypt(Voting.PlaintextBallot.class, key, group, e1New), msg1); + assertEquals (Util.decrypt(Voting.PlaintextBallot.class, key, group, e2), msg2); + assertEquals (Util.decrypt(Voting.PlaintextBallot.class, key, group, e2New), msg2); ECPoint g = group.getGenerator(); ECPoint h = enc.getElGamalPK().getPK(); diff --git a/mixer/src/test/java/profiling/BigInteger/AddSub.java b/mixer/src/test/java/profiling/BigInteger/AddSub.java index 8e3b5c1..6a64b0b 100644 --- a/mixer/src/test/java/profiling/BigInteger/AddSub.java +++ b/mixer/src/test/java/profiling/BigInteger/AddSub.java @@ -2,6 +2,7 @@ package profiling.BigInteger; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import meerkat.mixer.Utils; import org.factcenter.qilin.primitives.concrete.ECElGamal; @@ -28,7 +29,7 @@ public class AddSub { ECGroup group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); ECElGamal.SK key = new ECElGamal.SK(group, sk); - ConcreteCrypto.ElGamalPublicKey serializedPk = Utils.serializePk(group, key); + ConcreteCrypto.ElGamalPublicKey serializedPk = Util.encodePK(group, key); ECElGamalEncryption enc = new ECElGamalEncryption(); enc.init(serializedPk); diff --git a/mixer/src/test/java/profiling/BigInteger/GenerateRandomness.java b/mixer/src/test/java/profiling/BigInteger/GenerateRandomness.java index ebe80f0..954fed4 100644 --- a/mixer/src/test/java/profiling/BigInteger/GenerateRandomness.java +++ b/mixer/src/test/java/profiling/BigInteger/GenerateRandomness.java @@ -2,6 +2,7 @@ package profiling.BigInteger; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import meerkat.mixer.Utils; import org.factcenter.qilin.primitives.concrete.ECElGamal; @@ -25,7 +26,7 @@ public class GenerateRandomness { BigInteger sk = ECElGamal.generateSecretKey(group, rand); ECElGamal.SK key = new ECElGamal.SK(group, sk); - ConcreteCrypto.ElGamalPublicKey serializedPk = Utils.serializePk(group, key); + ConcreteCrypto.ElGamalPublicKey serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); diff --git a/mixer/src/test/java/profiling/BigInteger/Modulo.java b/mixer/src/test/java/profiling/BigInteger/Modulo.java index d0149b0..42190be 100644 --- a/mixer/src/test/java/profiling/BigInteger/Modulo.java +++ b/mixer/src/test/java/profiling/BigInteger/Modulo.java @@ -2,8 +2,8 @@ package profiling.BigInteger; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; -import meerkat.mixer.Utils; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -27,7 +27,7 @@ public class Modulo { BigInteger sk = ECElGamal.generateSecretKey(group, rand); ECElGamal.SK key = new ECElGamal.SK(group, sk); - ConcreteCrypto.ElGamalPublicKey serializedPk = Utils.serializePk(group, key); + ConcreteCrypto.ElGamalPublicKey serializedPk = Util.encodePK(group, key); ECElGamalEncryption enc = new ECElGamalEncryption(); enc.init(serializedPk); for (int i =0 ; i < tests ; i++){ diff --git a/mixer/src/test/java/profiling/BigInteger/Mul.java b/mixer/src/test/java/profiling/BigInteger/Mul.java index 4ac913a..9164755 100644 --- a/mixer/src/test/java/profiling/BigInteger/Mul.java +++ b/mixer/src/test/java/profiling/BigInteger/Mul.java @@ -2,6 +2,7 @@ package profiling.BigInteger; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import meerkat.mixer.Utils; import org.factcenter.qilin.primitives.concrete.ECElGamal; @@ -28,7 +29,7 @@ public class Mul { ECGroup group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); ECElGamal.SK key = new ECElGamal.SK(group, sk); - ConcreteCrypto.ElGamalPublicKey serializedPk = Utils.serializePk(group, key); + ConcreteCrypto.ElGamalPublicKey serializedPk = Util.encodePK(group, key); ECElGamalEncryption enc = new ECElGamalEncryption(); enc.init(serializedPk); diff --git a/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java b/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java index 5e885f8..5c587de 100644 --- a/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java +++ b/mixer/src/test/java/profiling/Convert/ByteString2ECPoint.java @@ -1,11 +1,11 @@ package profiling.Convert; -import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.mixer.Utils; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Voting; -import meerkat.mixer.Utils; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -30,7 +30,7 @@ public class ByteString2ECPoint { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); tests = 1024 * 19; diff --git a/mixer/src/test/java/profiling/Convert/RerandomizableEncryptedMessage2ElGamalCiphertext.java b/mixer/src/test/java/profiling/Convert/RerandomizableEncryptedMessage2ElGamalCiphertext.java index 3d7435f..943ad1d 100644 --- a/mixer/src/test/java/profiling/Convert/RerandomizableEncryptedMessage2ElGamalCiphertext.java +++ b/mixer/src/test/java/profiling/Convert/RerandomizableEncryptedMessage2ElGamalCiphertext.java @@ -2,6 +2,7 @@ package profiling.Convert; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; @@ -29,7 +30,7 @@ public class RerandomizableEncryptedMessage2ElGamalCiphertext { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); tests = 1024 * 18; diff --git a/mixer/src/test/java/profiling/ECGroup/Add.java b/mixer/src/test/java/profiling/ECGroup/Add.java index e0b5406..34c4832 100644 --- a/mixer/src/test/java/profiling/ECGroup/Add.java +++ b/mixer/src/test/java/profiling/ECGroup/Add.java @@ -2,7 +2,7 @@ package profiling.ECGroup; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.mixer.Utils; +import meerkat.crypto.concrete.Util; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -29,7 +29,7 @@ public class Add { random = new Random(); group = new ECGroup("secp256k1"); encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); + encryptor.init(Util.encodePK(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // generate n; int sqrtn = 128; n = sqrtn*sqrtn; diff --git a/mixer/src/test/java/profiling/ECGroup/Encode.java b/mixer/src/test/java/profiling/ECGroup/Encode.java index 59201e3..b69db71 100644 --- a/mixer/src/test/java/profiling/ECGroup/Encode.java +++ b/mixer/src/test/java/profiling/ECGroup/Encode.java @@ -2,6 +2,7 @@ package profiling.ECGroup; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.mixer.Utils; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECElGamal; @@ -29,7 +30,7 @@ public class Encode { random = new Random(); group = new ECGroup("secp256k1"); encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); + encryptor.init(Util.encodePK(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // generate n; int sqrtn = 128; n = sqrtn*sqrtn; diff --git a/mixer/src/test/java/profiling/ECGroup/Mul.java b/mixer/src/test/java/profiling/ECGroup/Mul.java index 836db0e..d1f9d1f 100644 --- a/mixer/src/test/java/profiling/ECGroup/Mul.java +++ b/mixer/src/test/java/profiling/ECGroup/Mul.java @@ -2,7 +2,7 @@ package profiling.ECGroup; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.mixer.Utils; +import meerkat.crypto.concrete.Util; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -30,7 +30,7 @@ public class Mul { random = new Random(); group = new ECGroup("secp256k1"); encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); + encryptor.init(Util.encodePK(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // generate n int sqrtn = 128; n = sqrtn*sqrtn; diff --git a/mixer/src/test/java/profiling/ECGroup/Negate.java b/mixer/src/test/java/profiling/ECGroup/Negate.java index d190186..0666eba 100644 --- a/mixer/src/test/java/profiling/ECGroup/Negate.java +++ b/mixer/src/test/java/profiling/ECGroup/Negate.java @@ -2,7 +2,7 @@ package profiling.ECGroup; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; -import meerkat.mixer.Utils; +import meerkat.crypto.concrete.Util; import org.bouncycastle.math.ec.ECPoint; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -28,7 +28,7 @@ public class Negate { random = new Random(); group = new ECGroup("secp256k1"); encryptor = new ECElGamalEncryption(); - encryptor.init(Utils.serializePk(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); + encryptor.init(Util.encodePK(group, new ECElGamal.SK(group, ECElGamal.generateSecretKey(group, random)))); // generate n; int sqrtn = 128; n = sqrtn*sqrtn; diff --git a/mixer/src/test/java/profiling/Rerandomize.java b/mixer/src/test/java/profiling/Rerandomize.java index 5a113c9..6428fd6 100644 --- a/mixer/src/test/java/profiling/Rerandomize.java +++ b/mixer/src/test/java/profiling/Rerandomize.java @@ -2,10 +2,11 @@ package profiling; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; +import meerkat.mixer.Utils; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; -import meerkat.mixer.Utils; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; @@ -31,7 +32,7 @@ public class Rerandomize { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); int LogVotes = 10; diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index 94e8f24..acd89c0 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -3,6 +3,7 @@ package profiling; import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; +import meerkat.crypto.concrete.Util; import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; @@ -38,7 +39,7 @@ public class ZeroKnowledgeProof { group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); - serializedPk = Utils.serializePk(group, key); + serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); RandomOracle randomOracle = new DigestOracle(); From 2744005263f18fa834c972a7710515fce3dc3939 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Sat, 21 Jan 2017 23:07:20 +0200 Subject: [PATCH 19/25] Replaced generic RandomOracle with explicit SHA-256 to make description of random oracle simpler for external verifiers --- .../src/main/java/meerkat/mixer/main/Mix.java | 11 +++----- .../mixer/proofs/concrete/Mix2nizk.java | 6 ++--- .../mixer/proofs/generic/SigmaFiatShamir.java | 27 +++++++++++++------ .../java/meerkat/mixer/ECParamTestBase.java | 1 - .../test/java/meerkat/mixer/MixingTest.java | 2 +- .../mixer/proofs/SigmaProtocolTest.java | 8 ++---- .../mixer/proofs/concrete/Mix2ProofTest.java | 2 +- .../java/profiling/ZeroKnowledgeProof.java | 5 ++-- 8 files changed, 31 insertions(+), 31 deletions(-) diff --git a/mixer/src/main/java/meerkat/mixer/main/Mix.java b/mixer/src/main/java/meerkat/mixer/main/Mix.java index 03cc467..dc67dbd 100644 --- a/mixer/src/main/java/meerkat/mixer/main/Mix.java +++ b/mixer/src/main/java/meerkat/mixer/main/Mix.java @@ -13,8 +13,6 @@ import meerkat.mixer.MixerOutput; import meerkat.mixer.proofs.concrete.Mix2nizk; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; import org.factcenter.qilin.primitives.concrete.ECElGamal; import org.factcenter.qilin.primitives.concrete.ECGroup; import org.slf4j.Logger; @@ -30,17 +28,17 @@ import java.util.List; import java.util.Random; import static java.lang.System.exit; -import static java.lang.System.in; /** * Command-line mixProverVerifier and verifier. */ public class Mix { + final static String DEFAULT_ECGROUP = "secp256k1"; final static Logger logger = LoggerFactory.getLogger(Mix.class); + public Random rand; public ECGroup group; public ECElGamalEncryption enc; - public RandomOracle randomOracle; public ConcreteCrypto.ElGamalPublicKey serializedPk; public ECElGamal.SK secretKey; public Mix2nizk mixProverVerifier; @@ -49,7 +47,6 @@ public class Mix { public Mix() { rand = new SecureRandom(); - randomOracle = new DigestOracle(); enc = new ECElGamalEncryption(); serializedPk = null; secretKey = null; @@ -108,7 +105,7 @@ public class Mix { exit(-2); } - mixProverVerifier = new Mix2nizk(rand, enc, randomOracle); + mixProverVerifier = new Mix2nizk(rand, enc); } /** @@ -117,7 +114,7 @@ public class Mix { * @param outFile */ public void createKeypair(File outFile) throws IOException { - group = new ECGroup("secp256k1"); + group = new ECGroup(DEFAULT_ECGROUP); BigInteger sk = ECElGamal.generateSecretKey(group, rand); secretKey = new ECElGamal.SK(group, sk); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java index 5e43851..93b8d24 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java @@ -7,7 +7,6 @@ import meerkat.mixer.proofs.Mix2nizk.Verifier; import meerkat.mixer.proofs.generic.SigmaFiatShamir; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; -import org.factcenter.qilin.primitives.RandomOracle; import org.factcenter.qilin.primitives.concrete.ECGroup; import java.util.Random; @@ -28,15 +27,14 @@ public class Mix2nizk implements Prover, Verifier { /** * @param rand * @param encryptor - * @param randomOracle - use for Fiat–Shamir heuristic */ - public Mix2nizk(Random rand, ECElGamalEncryption encryptor, RandomOracle randomOracle) { + public Mix2nizk(Random rand, ECElGamalEncryption encryptor) { this.rand = rand; this.encryptor = encryptor; this.group = this.encryptor.getGroup(); this.mixParams = new Statements(encryptor); - this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK, randomOracle); + this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK); } /** diff --git a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java index 80085c0..9275fd0 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaFiatShamir.java @@ -3,20 +3,28 @@ package meerkat.mixer.proofs.generic; import com.google.protobuf.Message; import meerkat.mixer.proofs.Concatenator; import meerkat.mixer.proofs.SigmaProtocol; -import org.factcenter.qilin.primitives.RandomOracle; import java.math.BigInteger; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; /** * Transform a Sigma protocol into a NIZK using Fiat-Shamir + * We use SHA-256 explicitly to make it easier to verify in other codebases */ public class SigmaFiatShamir { - final RandomOracle randomOracle; + final static String DIGEST_ALG = "SHA-256"; + final MessageDigest md; final Concatenator.Pair concat; - public SigmaFiatShamir(Concatenator.Pair concat, RandomOracle randomOracle) { + public SigmaFiatShamir(Concatenator.Pair concat) { this.concat = concat; - this.randomOracle = randomOracle; + try { + md = MessageDigest.getInstance(DIGEST_ALG); + } catch (NoSuchAlgorithmException e) { + // Should never happen + throw new RuntimeException("Error in instantiating " + DIGEST_ALG + " digest", e); + } } /** @@ -24,21 +32,24 @@ public class SigmaFiatShamir prover) { FirstMsgType firstMessage = prover.getFirstMessage(); - BigInteger challenge = hash(firstMessage, randomOracle); + BigInteger challenge = hash(firstMessage); FinalMessageType finalMessage = prover.getFinalMessage(challenge); return concat.concatenate(firstMessage, finalMessage); } public boolean verifyNizk(NIZKMsgType NIZK, SigmaProtocol.Verifier verifier) { FirstMsgType firstMessage = concat.getMsg1(NIZK); - BigInteger challenge = hash(firstMessage, randomOracle); + BigInteger challenge = hash(firstMessage); return verifier.verify(firstMessage, challenge, concat.getMsg2(NIZK)); } } diff --git a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java index 0c187cf..23b9c62 100644 --- a/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java +++ b/mixer/src/test/java/meerkat/mixer/ECParamTestBase.java @@ -21,7 +21,6 @@ public class ECParamTestBase { public ECElGamal.SK key; public ECGroup group; public ECElGamalEncryption enc; - public RandomOracle randomOracle = new DigestOracle(); public ConcreteCrypto.ElGamalPublicKey serializedPk; public ECParamTestBase() { diff --git a/mixer/src/test/java/meerkat/mixer/MixingTest.java b/mixer/src/test/java/meerkat/mixer/MixingTest.java index 344e42f..d424a0b 100644 --- a/mixer/src/test/java/meerkat/mixer/MixingTest.java +++ b/mixer/src/test/java/meerkat/mixer/MixingTest.java @@ -29,7 +29,7 @@ public class MixingTest extends ECParamTestBase { random = new Random(1); randomMixer = new Random(2); randomProver = new Random(3); - mix2nizk = new Mix2nizk(randomProver, enc,randomOracle); + mix2nizk = new Mix2nizk(randomProver, enc); mixer = new MixGenerator(mix2nizk, enc); // generate n diff --git a/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java index 01b18d8..2bcddf2 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/SigmaProtocolTest.java @@ -2,8 +2,6 @@ package meerkat.mixer.proofs; import com.google.protobuf.Message; import meerkat.mixer.proofs.generic.SigmaFiatShamir; -import org.factcenter.qilin.primitives.RandomOracle; -import org.factcenter.qilin.primitives.concrete.DigestOracle; import org.factcenter.qilin.util.Pair; import org.junit.Before; import org.junit.Test; @@ -11,7 +9,7 @@ import org.junit.Test; import java.math.BigInteger; import java.util.Random; -import static org.junit.Assert.*; +import static org.junit.Assert.assertTrue; /** * Generic test for Sigma Protocol @@ -19,8 +17,6 @@ import static org.junit.Assert.*; abstract public class SigmaProtocolTest { public final int NUM_REPEAT = 10; - final protected RandomOracle randomOracle = new DigestOracle(); - abstract protected void generateRandomTrueStatement(); abstract protected void generateRandomFalseStatement(); @@ -97,7 +93,7 @@ abstract public class SigmaProtocolTest { for (int i = 0; i < NUM_REPEAT; ++i) { generateRandomTrueStatement(); - SigmaFiatShamir, M1, M2> fiatShamir = new SigmaFiatShamir, M1, M2>(nizkConcat, randomOracle); + SigmaFiatShamir, M1, M2> fiatShamir = new SigmaFiatShamir, M1, M2>(nizkConcat); prover = getNewProver(); Pair nizk = fiatShamir.generateNizk(prover); diff --git a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java index d4c4b77..ff3cac9 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/Mix2ProofTest.java @@ -26,7 +26,7 @@ public class Mix2ProofTest extends ECParamTestBase { @Before public void setup() throws Exception { - nizk = new Mix2nizk(rand, enc, randomOracle); + nizk = new Mix2nizk(rand, enc); verifier = nizk; prover = nizk; } diff --git a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java index acd89c0..b477a9f 100644 --- a/mixer/src/test/java/profiling/ZeroKnowledgeProof.java +++ b/mixer/src/test/java/profiling/ZeroKnowledgeProof.java @@ -35,15 +35,14 @@ public class ZeroKnowledgeProof { Crypto.RerandomizableEncryptedMessage[] reencryptedMessage; public void setup() throws Exception { - rand = new Random(); + rand = new Random(1); group = new ECGroup("secp256k1"); BigInteger sk = ECElGamal.generateSecretKey(group, rand); key = new ECElGamal.SK(group, sk); serializedPk = Util.encodePK(group, key); enc = new ECElGamalEncryption(); enc.init(serializedPk); - RandomOracle randomOracle = new DigestOracle(); - prover = new Mix2nizk(new Random(),enc,randomOracle); + prover = new Mix2nizk(rand,enc); int LogVotes = 12; int layers = 2*LogVotes - 1; n = layers * (1< Date: Sun, 22 Jan 2017 00:24:25 +0200 Subject: [PATCH 20/25] Added mixer documentation --- mixer/docs/concrete_crypto.proto | 1 + mixer/docs/crypto.proto | 1 + mixer/docs/mixer.md | 104 +++++++++++++++++++++++++++++++ mixer/docs/mixing.proto | 1 + 4 files changed, 107 insertions(+) create mode 120000 mixer/docs/concrete_crypto.proto create mode 120000 mixer/docs/crypto.proto create mode 100644 mixer/docs/mixer.md create mode 120000 mixer/docs/mixing.proto diff --git a/mixer/docs/concrete_crypto.proto b/mixer/docs/concrete_crypto.proto new file mode 120000 index 0000000..971513e --- /dev/null +++ b/mixer/docs/concrete_crypto.proto @@ -0,0 +1 @@ +../../meerkat-common/src/main/proto/meerkat/concrete_crypto.proto \ No newline at end of file diff --git a/mixer/docs/crypto.proto b/mixer/docs/crypto.proto new file mode 120000 index 0000000..acd418e --- /dev/null +++ b/mixer/docs/crypto.proto @@ -0,0 +1 @@ +../../meerkat-common/src/main/proto/meerkat/crypto.proto \ No newline at end of file diff --git a/mixer/docs/mixer.md b/mixer/docs/mixer.md new file mode 100644 index 0000000..c668cd9 --- /dev/null +++ b/mixer/docs/mixer.md @@ -0,0 +1,104 @@ +#Mixer File Format +This document attempts to provide sufficient information to write a verifier for our mixnet implementation. + +## High-Level Overview. +The mixer implements Abe's Permutation-network-based mix. The on-disk format of the mixer's output consists of a sequence of protobif messages, written using their writeDelimitedTo() method: +1. A [MixBatchHeader](mixing.proto) message containing the number of switch layers and the number of ciphertexts in each layer (where the latter is given as the base-2 log of the number, since the actual number must be a power of 2). +2. A matrix of ciphertext messages. The matrix is given column by column; the total number of columns is the number of layers + 1 (the first column is the input to the mix, and the final column is the output). The first message in the sequence is ciphertext 0 in column 0, then ciphertext 1 in layer 0, finally ending with ciphertext $2^{logN}-1$ in column $layers$. +3. A matrix of proofs for each 2x2 switch. The matrix is given column by column; the total number of columns is the number of layers. The first message in the matrix sequence is switch 0 in column 0, then switch 1 in column 0, finally ending with switch $2^{logN-1}-1$ in column $layers-1$. + + +## Ciphertexts +For future compatibility, each ciphertext actually written to disk is encoded as an "opaque" [RerandomizableEncryptedMessage](crypto.proto). The data field of this message contains the serialized ElGamalCiphertext message (see below). + +### EC-ElGamal Ciphertexts +Ciphertexts are serialized using the [ElGamalCiphertext](concrete_crypto.proto) message, with fields "c1" and "c2" for the first and second group elements. + +### EC Group elements +Group elements use the [GroupElement](concrete_crypto.proto) message. It's only field is "data", which should be an ASN.1-encoded curve point with compression (see section 4.3.6 of [X9.62-1998](https://www.security-audit.com/files/x9-62-09-20-98.pdf) "Public Key Cryptography For The Financial Services Industry: The Elliptic Curve Digital Signature Algorithm (ECDSA)") + +### EC-ElGamal Key Format +The ECElGamal Key is stored in the [ElGamalPublicKey](concrete_crypto.proto) message that contains a standard DER-encoded SubjectPublicKeyInfo as in [RFC 3279](https://tools.ietf.org/html/rfc3279) (note that this encoding includes the elliptic-curve group parameters). + + + +## Proofs +Each mixing proof is a serialized [Mix2Proof](mixing.proto) message. This consists of a firstMessage field (containing the first message of the Sigma protocol) and a finalMessage field(containing the final message of the Sigma protocol). The challenge is derived from the *serialized form* of the firstMessage field by hashing (see [Fiat-Shamir](#fiat-shamir-random-oracle) below for the hash algorithm), a finalMessage field and a location field (see [Location](#location) below). + +### Proof Statement +The proof statement itself is a disjunction of two conjunctions of Schnorr proofs for discrete-log equivalence, constructed from the ciphertexts. Let $g$ be the group generator and $h$ the ElGamal public key. Given input ciphertexts $a=(a_1,a_2)$ and +$b=(b_1,b_2)$ and output ciphertexts $c=(c_1,c_2)$ and $d=(d_1,d_2)$, the statement proved is: +$$ +(\log_g \frac{c_1}{a_1} = \log_h\frac{c_2}{a_2})\text{ AND } (\log_g \frac{d_1}{b_1} = \log_h\frac{d_2}{b_2}) \\ +\text{OR}\\ +(\log_g \frac{d_1}{a_1} = \log_h\frac{d_2}{a_2}) \text{ AND } (\log_g \frac{c_1}{b_1} = \log_h\frac{c_2}{b_2}) +$$ + +The firstMessage and finalMessage fields are generated using the sigma-protocol disjunction composition of the sigma protocols for the two conjuction statements, and those in turn are generated using the sigma-protocol conjunction statement of the basic Schnorr proofs (more details in the [protobuf file](mixing.proto)). + +### Location +The location field gives the layer number (column) and switchIdx (index within the column) for the 2x2 switch which this proof references. The input ciphertexts to switch $s$ in layer $i$ are in positions $2s$, $2s+1$ in column $i$ of the ciphertext matrix. The indices of the output ciphertexts in column $i+1$ are given in the location field (out0 is the index of the first output ciphertext and out1 the second). + +### Integers +Integers are serialized using the [BigInteger](crypto.proto) protobuf message, whose data field contains the integer encoded as in Java's [BigInteger.toByteArray()](http://docs.oracle.com/javase/7/docs/api/java/math/BigInteger.html#toByteArray()) method. + + +### Fiat-Shamir "Random Oracle" +The Fiat-Shamir heuristic uses a "random oracle". We use the following java code as the implementation of the oracle. + + + public BigInteger hash(byte[] input) { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.reset(); + + byte[] digest = md.digest(input); + return new BigInteger(1,digest); + } + +Note that our Sigma-protocols use Integers as a challenge, so the random oracle returns a BigInteger. The input to the oracle is always a protobuf Message; we convert it to a byte array using its toByteArray() method. + +## The Mixer Command-line Utility +The Mixer application can generate keys, encrypt, mix, verify and decrypt. The jar file can be run using "java -jar mixer.jar" + +Run + + java -jar mixer.jar -h + +To get a summary of command line options. +### Examples + +#### Generate a new Key-Pair + + java -jar mixer.jar -g -k ecelgamal.key + +Generates the keys in the file ecelgamal.key + +#### Encrypt some plaintexts +(run after generating keys) + + java -jar mixer.jar -k ecelgamal.key -e -i infile.txt -o outfile.enc + +**infile.txt** should consist of multiple lines; each line is used as a plaintext. If you get a warning message about inputs being truncated, you must ensure the longest line is shorter than about 20 chars (each plaintext must fit into a single group element, and there is some extra protobuf overhead) + +**outfile.enc** will contain a 0-layer mixnet (i.e., a single column of ciphertexts). The plaintexts will be padded with empty lines to the nearest power of two. + +#### Run the mix network +(run after encrypting some plaintexts) + + java -jar mixer.jar -k ecelgamal.key -i outfile.enc -o mixed.enc + +**mixed.enc** will contain the mixnet output including proofs. + +#### Verify the mix + + java -jar mixer.jar -k ecelgamal.key -i mixed.enc + +This doesn't write output. You can add the "-s" flag for strict verification; strict verification +checks that the Benes network structure matches our implementation exactly (otherwise +the verifier just ensures that the output is a permutation of the input). + +#### Decrypt the output + + java -jar mixer.jar -k ecelgamal.key -d -i mixed.enc -o decrypted.txt + + diff --git a/mixer/docs/mixing.proto b/mixer/docs/mixing.proto new file mode 120000 index 0000000..0f877ce --- /dev/null +++ b/mixer/docs/mixing.proto @@ -0,0 +1 @@ +../src/main/proto/meerkat/mixing.proto \ No newline at end of file From 5b7fbffb09f89000df28a1090829ebca0679b28e Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Mon, 23 Jan 2017 15:40:45 +0200 Subject: [PATCH 21/25] Update to gradle 3.3 --- gradle/wrapper/gradle-wrapper.properties | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 1527da9..2f94d87 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -3,5 +3,5 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-all.zip -distributionSha256Sum=0209696f1723f607c475109cf3ed8b51c8a91bb0cda05af0d4bd980bdefe75cd +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip +distributionSha256Sum=71a787faed83c4ef21e8464cc8452b941b5fcd575043aa29d39d15d879be89f7 From ce0e0e0d62f57617d2b1360d5a4e7b4d4479d5f3 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Mon, 23 Jan 2017 15:41:27 +0200 Subject: [PATCH 22/25] Fix protobuf decoding bug --- .../test/java/meerkat/crypto/concrete/ECElGamalUtils.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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 c40128c..e1368e5 100644 --- a/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java +++ b/meerkat-common/src/test/java/meerkat/crypto/concrete/ECElGamalUtils.java @@ -70,10 +70,10 @@ public class ECElGamalUtils { GroupElement c1encoded = cipherText.getC1(); GroupElement c2encoded = cipherText.getC2(); - ECPoint c1 = group.decode(c1encoded.toByteArray()); - ECPoint c2 = group.decode(c2encoded.toByteArray()); + ECPoint c1 = ECElGamalEncryption.decodeElement(group, c1encoded); + ECPoint c2 = ECElGamalEncryption.decodeElement(group, c2encoded); - ECPoint plaintextEncoded = secretKey.decrypt(new Pair(c1, c2)); + ECPoint plaintextEncoded = secretKey.decrypt(new Pair<>(c1, c2)); byte[] plaintext = group.injectiveDecode(plaintextEncoded); From 53cc13b51b4b9d0c0c21df93cfb3a162bd1db220 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Tue, 24 Jan 2017 16:28:57 +0200 Subject: [PATCH 23/25] Cleaning up unchecked casts --- .../java/meerkat/crypto/dkg/feldman/Protocol.java | 4 ++-- .../java/meerkat/crypto/dkg/feldman/User.java | 2 +- .../java/meerkat/comm/MessageInputStream.java | 13 +++++++------ .../test/java/meerkat/comm/MessageStreamTest.java | 2 +- .../mixer/proofs/concrete/DlogConjunction.java | 2 +- .../meerkat/mixer/proofs/concrete/Mix2nizk.java | 2 +- .../mixer/proofs/generic/SigmaProtocolAnd2.java | 15 +++++++++++---- .../mixer/proofs/generic/SigmaProtocolOr2.java | 15 ++++++++++----- .../proofs/concrete/DlogOrStatementSigmaTest.java | 3 ++- .../PollingStationScannerWebApp.java | 12 ++++++++++-- .../java/meerkat/voting/VotingBoothToyRun.java | 6 +++--- .../voting/storage/StorageManagerMockup.java | 2 +- 12 files changed, 50 insertions(+), 28 deletions(-) diff --git a/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/Protocol.java b/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/Protocol.java index f612b07..781a585 100644 --- a/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/Protocol.java +++ b/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/Protocol.java @@ -104,7 +104,7 @@ public class Protocol extends VerifiableSecretSharing { * setter * @param parties */ - protected void setParties(Party[] parties){ + protected void setParties(Party[] parties){ this.parties = parties; } @@ -112,7 +112,7 @@ public class Protocol extends VerifiableSecretSharing { * getter * @return */ - protected Party[] getParties(){ + protected Party[] getParties(){ return parties; } diff --git a/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/User.java b/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/User.java index f7c4624..235dab6 100644 --- a/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/User.java +++ b/distributed-key-generation/src/main/java/meerkat/crypto/dkg/feldman/User.java @@ -77,7 +77,7 @@ public class User implements Runnable { * All parties participating in key generation. * parties[id-1] has my info. */ - protected final Party[] parties; + protected final Party[] parties; /** * set of all non-disqualified parties diff --git a/meerkat-common/src/main/java/meerkat/comm/MessageInputStream.java b/meerkat-common/src/main/java/meerkat/comm/MessageInputStream.java index b1e5255..bc7c118 100644 --- a/meerkat-common/src/main/java/meerkat/comm/MessageInputStream.java +++ b/meerkat-common/src/main/java/meerkat/comm/MessageInputStream.java @@ -15,11 +15,14 @@ import java.util.List; */ public class MessageInputStream implements Iterable{ + Class type; + private T.Builder builder; private InputStream in; MessageInputStream(InputStream in, Class type) throws IOException, NoSuchMethodException, InvocationTargetException, IllegalAccessException { + this.type = type; this.in = in; this.builder = (T.Builder) type.getMethod("newBuilder").invoke(type); } @@ -41,7 +44,7 @@ public class MessageInputStream implements Iterable{ @Override public T next() { try { - return readMessage(); + return readMessage(type); } catch (IOException e) { return null; } @@ -65,12 +68,10 @@ public class MessageInputStream implements Iterable{ } - public T readMessage() throws IOException{ - + public T readMessage(Class msgType) throws IOException{ builder.clear(); builder.mergeDelimitedFrom(in); - return (T) builder.build(); - + return msgType.cast(builder.build()); } public boolean isAvailable() throws IOException { @@ -82,7 +83,7 @@ public class MessageInputStream implements Iterable{ List list = new LinkedList<>(); while (isAvailable()){ - list.add(readMessage()); + list.add(readMessage(type)); } return list; diff --git a/meerkat-common/src/test/java/meerkat/comm/MessageStreamTest.java b/meerkat-common/src/test/java/meerkat/comm/MessageStreamTest.java index 58dc7c1..27eeca3 100644 --- a/meerkat-common/src/test/java/meerkat/comm/MessageStreamTest.java +++ b/meerkat-common/src/test/java/meerkat/comm/MessageStreamTest.java @@ -81,7 +81,7 @@ public class MessageStreamTest { new ByteArrayInputStream(stream.toByteArray()), BulletinBoardMessage.class); - assertThat("Retrieved message was not identical to send message", comparator.compare(message, in.readMessage()), is(equalTo(0))); + assertThat("Retrieved message was not identical to send message", comparator.compare(message, in.readMessage(BulletinBoardMessage.class)), is(equalTo(0))); } catch (IOException e) { diff --git a/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java index d2487b5..b9a9263 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/DlogConjunction.java @@ -22,7 +22,7 @@ public class DlogConjunction { } } - public static class Simulator extends SigmaProtocolAnd2.Simulator { + public static class Simulator extends SigmaProtocolAnd2.Simulator { public Simulator(ECElGamalEncryption encryptor, Random rand, Statements.AndStatement statement) { super(ProtobufConcatenators.concatAnd1, ProtobufConcatenators.concatAnd2, new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[0]), new SchnorrDlogEquivalence.Simulator(encryptor, rand, statement.clauses[1])); diff --git a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java index 93b8d24..482b694 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/concrete/Mix2nizk.java @@ -34,7 +34,7 @@ public class Mix2nizk implements Prover, Verifier { this.encryptor = encryptor; this.group = this.encryptor.getGroup(); this.mixParams = new Statements(encryptor); - this.mix2NIZK = new SigmaFiatShamir(ProtobufConcatenators.concatNIZK); + this.mix2NIZK = new SigmaFiatShamir<>(ProtobufConcatenators.concatNIZK); } /** diff --git a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java index 3e14edd..c411ef6 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolAnd2.java @@ -16,7 +16,9 @@ public class SigmaProtocolAnd2 { final Concatenator.Pair firstMessageConcatenator; final Concatenator.Pair finalMessageConcatenator; - public Prover(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, + @SafeVarargs + public Prover(Concatenator.Pair firstMessageConcatenator, + Concatenator.Pair finalMessageConcatenator, SigmaProtocol.Prover... provers) { this.firstMessageConcatenator = firstMessageConcatenator; this.finalMessageConcatenator = finalMessageConcatenator; @@ -42,8 +44,10 @@ public class SigmaProtocolAnd2 { final Concatenator.Pair firstMessageConcatenator; final Concatenator.Pair finalMessageConcatenator; - public Verifier(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, - SigmaProtocol.Verifier... verifiers) { + @SafeVarargs + public Verifier(Concatenator.Pair firstMessageConcatenator, + Concatenator.Pair finalMessageConcatenator, + SigmaProtocol.Verifier... verifiers) { this.firstMessageConcatenator = firstMessageConcatenator; this.finalMessageConcatenator = finalMessageConcatenator; this.verifiers = verifiers; @@ -63,7 +67,10 @@ public class SigmaProtocolAnd2 { final Concatenator.Pair firstMessageConcatenator; final Concatenator.Pair finalMessageConcatenator; - public Simulator(Concatenator.Pair firstMessageConcatenator, Concatenator.Pair finalMessageConcatenator, SigmaProtocol.Simulator... simulators) { + @SafeVarargs + public Simulator(Concatenator.Pair firstMessageConcatenator, + Concatenator.Pair finalMessageConcatenator, + SigmaProtocol.Simulator... simulators) { this.firstMessageConcatenator = firstMessageConcatenator; this.finalMessageConcatenator = finalMessageConcatenator; this.simulators = simulators; diff --git a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java index 097d2a8..66dfbf4 100644 --- a/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java +++ b/mixer/src/main/java/meerkat/mixer/proofs/generic/SigmaProtocolOr2.java @@ -44,8 +44,11 @@ public class SigmaProtocolOr2 { * @param simulator * @param proverIdx Which index should the prover be inserted at (0 means first, 1 means second) */ - public Prover(Concatenator.Pair firstMessageConcatenator, Concatenator.Triplet finalMessageConcatenator, ChallengeGenerator challengeGenerator, - SigmaProtocol.Prover prover, SigmaProtocol.Simulator simulator, int proverIdx) { + public Prover(Concatenator.Pair firstMessageConcatenator, + Concatenator.Triplet finalMessageConcatenator, + ChallengeGenerator challengeGenerator, + SigmaProtocol.Prover prover, + SigmaProtocol.Simulator simulator, int proverIdx) { this.firstMessageConcatenator = firstMessageConcatenator; this.finalMessageConcatenator = finalMessageConcatenator; this.challengeGenerator = challengeGenerator; @@ -87,10 +90,11 @@ public class SigmaProtocolOr2 { final SigmaProtocol.Verifier[] verifiers; - - public Verifier(Concatenator.Pair firstMessageConcatenator, Concatenator.Triplet finalMessageConcatenator, + @SafeVarargs + public Verifier(Concatenator.Pair firstMessageConcatenator, + Concatenator.Triplet finalMessageConcatenator, ChallengeGenerator challengeGenerator, - SigmaProtocol.Verifier... verifiers) { + SigmaProtocol.Verifier... verifiers) { this.firstMessageConcatenator = firstMessageConcatenator; this.finalMessageConcatenator = finalMessageConcatenator; this.challengeGenerator = challengeGenerator; @@ -119,6 +123,7 @@ public class SigmaProtocolOr2 { BigInteger simChallenge0; + @SafeVarargs public Simulator(Concatenator.Pair firstMessageConcatenator, Concatenator.Triplet finalMessageConcatenator, ChallengeGenerator challengeGenerator, SigmaProtocol.Simulator... simulators) { diff --git a/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java index 91eca64..a4cb333 100644 --- a/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java +++ b/mixer/src/test/java/meerkat/mixer/proofs/concrete/DlogOrStatementSigmaTest.java @@ -74,7 +74,8 @@ public class DlogOrStatementSigmaTest extends SigmaProtocolTest getNewSimulator() { Mix2.ChallengeGenerator gen = new Mix2.ChallengeGenerator(dlogtest.encryptor, rand); - return new SigmaProtocolOr2.Simulator<>(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, + return new SigmaProtocolOr2.Simulator(ProtobufConcatenators.concatMix1, ProtobufConcatenators.concatMix2, gen, new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[0]), new DlogConjunction.Simulator(dlogtest.encryptor, rand, statements[1])); } diff --git a/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java b/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java index 327c774..db3195d 100644 --- a/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java +++ b/polling-station/src/main/java/meerkat/pollingstation/PollingStationScannerWebApp.java @@ -37,8 +37,16 @@ public class PollingStationScannerWebApp implements PollingStationScanner.Produc * This method is called by the Jetty engine when instantiating the servlet */ @PostConstruct - public void init() throws Exception{ - callbacks = (Iterable>) servletContext.getAttribute(PollingStationWebScanner.CALLBACKS_ATTRIBUTE_NAME); + @SuppressWarnings("unchecked") + public void init() throws Exception { + Object context = servletContext.getAttribute(PollingStationWebScanner.CALLBACKS_ATTRIBUTE_NAME); + + try { + callbacks = (Iterable>) context; + } catch (ClassCastException e) { + throw e; + } + } @POST diff --git a/voting-booth/src/main/java/meerkat/voting/VotingBoothToyRun.java b/voting-booth/src/main/java/meerkat/voting/VotingBoothToyRun.java index 65b6685..5815920 100644 --- a/voting-booth/src/main/java/meerkat/voting/VotingBoothToyRun.java +++ b/voting-booth/src/main/java/meerkat/voting/VotingBoothToyRun.java @@ -90,7 +90,7 @@ public class VotingBoothToyRun { private static List generateChannelChoiceQuestions() { - ArrayList channelChoiceQuestions = new ArrayList(); + ArrayList channelChoiceQuestions = new ArrayList<>(); String[] ans1 = {"Red", "Blue", "Green"}; BallotQuestion ccquestion1 = generateBallotQuestion("What is your favorite color?", "Pick one answer", ans1); @@ -105,7 +105,7 @@ public class VotingBoothToyRun { private static List generateBallotQuestions() { - ArrayList allBallotQuestions = new ArrayList(); + ArrayList allBallotQuestions = new ArrayList<>(); String[] answers1 = {"answer 1", "answer 2", "answer 3", "answer 4"}; allBallotQuestions.add(generateBallotQuestion("question 1. Asking something...", "Pick one answer", answers1)); @@ -222,7 +222,7 @@ public class VotingBoothToyRun { private static void generateSystemMessages() throws IOException{ - Map systemMessageMap = new HashMap(); + Map systemMessageMap = new HashMap<>(); systemMessageMap.put(StorageManager.WAIT_FOR_COMMIT_MESSAGE, UIElement.newBuilder() .setType(UIElementDataType.TEXT) diff --git a/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java b/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java index f556e3b..6f01357 100644 --- a/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java +++ b/voting-booth/src/main/java/meerkat/voting/storage/StorageManagerMockup.java @@ -84,7 +84,7 @@ public class StorageManagerMockup implements StorageManager { logger.error("Could not read from the systemMessages file: '" + systemMessagesFilename + "'."); throw e; } - return systemMessages.getSystemMessage(); + return systemMessages.getSystemMessageMap(); } } From 06526a16db01c6de1caed1f7dab3f839d6eff768 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Tue, 24 Jan 2017 17:17:09 +0200 Subject: [PATCH 24/25] Clean up build files and remove dependency on local nexus repository --- build.gradle | 9 ++-- bulletin-board-client/build.gradle | 55 ++++++------------------- bulletin-board-client/gradlew | 1 + bulletin-board-server/build.gradle | 23 ++--------- distributed-key-generation/build.gradle | 37 +++-------------- meerkat-common/build.gradle | 32 ++++---------- mixer/build.gradle | 40 +++--------------- polling-station/build.gradle | 38 ++--------------- restful-api-common/build.gradle | 35 ++-------------- voting-booth/build.gradle | 38 ++--------------- 10 files changed, 53 insertions(+), 255 deletions(-) create mode 120000 bulletin-board-client/gradlew diff --git a/build.gradle b/build.gradle index 8c01ae9..ed7d229 100644 --- a/build.gradle +++ b/build.gradle @@ -5,9 +5,12 @@ plugins { subprojects { proj -> proj.afterEvaluate { // Used to generate initial maven-dir layout - task "create-dirs" { description = "Create default maven directory structure" } << { - sourceSets*.java.srcDirs*.each { it.mkdirs() } - sourceSets*.resources.srcDirs*.each { it.mkdirs() } + task "create-dirs" { + description = "Create default maven directory structure" + doLast { + sourceSets*.java.srcDirs*.each { it.mkdirs() } + sourceSets*.resources.srcDirs*.each { it.mkdirs() } + } } } } diff --git a/bulletin-board-client/build.gradle b/bulletin-board-client/build.gradle index 8f00228..f870887 100644 --- a/bulletin-board-client/build.gradle +++ b/bulletin-board-client/build.gradle @@ -16,12 +16,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Meerkat Voting Common Library" @@ -38,23 +32,10 @@ dependencies { compile project(':meerkat-common') compile project(':restful-api-common') - // Jersey for RESTful API - compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+' + + // Databases compile 'org.xerial:sqlite-jdbc:3.7.+' - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - - // Crypto - compile 'org.factcenter.qilin:qilin:1.1+' - compile 'org.bouncycastle:bcprov-jdk15on:1.53' - compile 'org.bouncycastle:bcpkix-jdk15on:1.53' - // Depend on test resources from meerkat-common testCompile project(path: ':meerkat-common', configuration: 'testOutput') @@ -178,34 +159,22 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - + // Use local repo if possible mavenLocal(); - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use 'maven central' for other dependencies. mavenCentral() } -task "info" << { - println "Project: ${project.name}" - println "Description: ${project.description}" - println "--------------------------" - println "GroupId: $groupId" - println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" - println "" +task "info" { + doLast { + println "Project: ${project.name}" + println "Description: ${project.description}" + println "--------------------------" + println "GroupId: $groupId" + println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" + println "" + } } info.description 'Print some information about project parameters' diff --git a/bulletin-board-client/gradlew b/bulletin-board-client/gradlew new file mode 120000 index 0000000..502f5a2 --- /dev/null +++ b/bulletin-board-client/gradlew @@ -0,0 +1 @@ +../gradlew \ No newline at end of file diff --git a/bulletin-board-server/build.gradle b/bulletin-board-server/build.gradle index bb28fb8..2ab85b0 100644 --- a/bulletin-board-server/build.gradle +++ b/bulletin-board-server/build.gradle @@ -22,12 +22,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Bulletin-board server web application" @@ -43,9 +37,6 @@ dependencies { compile project(':meerkat-common') compile project(':restful-api-common') - // Jersey for RESTful API - compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+' - // JDBC connections compile 'org.springframework:spring-jdbc:4.2.+' compile 'org.xerial:sqlite-jdbc:3.8.+' @@ -56,14 +47,6 @@ dependencies { // Servlets compile 'javax.servlet:javax.servlet-api:3.0.+' - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - // Depend on test resources from meerkat-common testCompile project(path: ':meerkat-common', configuration: 'testOutput') @@ -220,13 +203,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/distributed-key-generation/build.gradle b/distributed-key-generation/build.gradle index 6befbc4..b47e8f2 100644 --- a/distributed-key-generation/build.gradle +++ b/distributed-key-generation/build.gradle @@ -21,12 +21,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "TODO: Add a description" @@ -41,14 +35,6 @@ dependencies { // Meerkat common compile project(':meerkat-common') - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - // Depend on test resources from meerkat-common testCompile project(path: ':meerkat-common', configuration: 'testOutput') @@ -99,7 +85,7 @@ idea { def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java" - println "Adding $srcDir" +// println "Adding $srcDir" // add protobuf generated sources to generated source dir. if ("test".equals(sourceSet.name)) { testSourceDirs += file(srcDir) @@ -158,21 +144,6 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() @@ -180,13 +151,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/meerkat-common/build.gradle b/meerkat-common/build.gradle index 896a547..bc380ed 100644 --- a/meerkat-common/build.gradle +++ b/meerkat-common/build.gradle @@ -20,12 +20,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Meerkat Voting Common Library" @@ -39,10 +33,12 @@ version += "${isSnapshot ? '-SNAPSHOT' : ''}" dependencies { // Logging compile 'org.slf4j:slf4j-api:1.7.7' - compile 'javax.ws.rs:javax.ws.rs-api:2.0.+' runtime 'ch.qos.logback:logback-classic:1.1.2' runtime 'ch.qos.logback:logback-core:1.1.2' + // RESTful API + compile 'javax.ws.rs:javax.ws.rs-api:2.0.+' + // Google protobufs compile 'com.google.protobuf:protobuf-java:3.+' @@ -50,7 +46,7 @@ dependencies { compile 'com.google.guava:guava:15.0' // Crypto - compile 'org.factcenter.qilin:qilin:1.2.+' + compile 'org.factcenter.qilin:qilin:1.3.+' compile 'org.bouncycastle:bcprov-jdk15on:1.53' testCompile 'junit:junit:4.+' @@ -157,32 +153,20 @@ task fatCapsule(type: FatCapsule){ repositories { mavenLocal(); - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } // Use 'maven central' for other dependencies. mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/mixer/build.gradle b/mixer/build.gradle index 3973fa0..bdde270 100644 --- a/mixer/build.gradle +++ b/mixer/build.gradle @@ -21,12 +21,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Mix network implementation" @@ -41,17 +35,6 @@ dependencies { // Meerkat common compile project(':meerkat-common') - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - - // Crypto - compile 'org.factcenter.qilin:qilin:1.2.+' - // Command-line parsing. compile 'net.sf.jopt-simple:jopt-simple:6.+' @@ -87,7 +70,7 @@ idea { def srcDir = "${protobuf.generatedFilesBaseDir}/$sourceSet.name/java" - println "Adding $srcDir" +// println "Adding $srcDir" // add protobuf generated sources to generated source dir. if ("test".equals(sourceSet.name)) { testSourceDirs += file(srcDir) @@ -146,21 +129,6 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() @@ -168,13 +136,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/polling-station/build.gradle b/polling-station/build.gradle index 2f73721..c45498f 100644 --- a/polling-station/build.gradle +++ b/polling-station/build.gradle @@ -22,12 +22,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Meerkat polling-station application" @@ -43,21 +37,10 @@ dependencies { compile project(':meerkat-common') compile project(':restful-api-common') - // Jersey for RESTful API - compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.5.+' - // Servlets compile 'org.eclipse.jetty:jetty-server:9.3.+' compile 'org.eclipse.jetty:jetty-servlet:9.3.+' - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - testCompile 'junit:junit:4.+' runtime 'org.codehaus.groovy:groovy:2.4.+' @@ -137,21 +120,6 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() @@ -159,13 +127,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/restful-api-common/build.gradle b/restful-api-common/build.gradle index a9c80b9..937b79d 100644 --- a/restful-api-common/build.gradle +++ b/restful-api-common/build.gradle @@ -19,12 +19,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Common classes for implementing Meerkat's RESTful API" @@ -42,14 +36,6 @@ dependencies { // Jersey for RESTful API compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.22.+' - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - testCompile 'junit:junit:4.+' runtime 'org.codehaus.groovy:groovy:2.4.+' @@ -95,21 +81,6 @@ idea { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() @@ -117,13 +88,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' diff --git a/voting-booth/build.gradle b/voting-booth/build.gradle index 0920359..682f398 100644 --- a/voting-booth/build.gradle +++ b/voting-booth/build.gradle @@ -20,12 +20,6 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' - nexusRepository = "https://cs.idc.ac.il/nexus/content/groups/${isSnapshot ? 'unstable' : 'public'}/" - - // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) - // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" } description = "Meerkat voting booth application" @@ -41,22 +35,11 @@ dependencies { compile project(':meerkat-common') compile project(':restful-api-common') - // Jersey for RESTful API - compile 'org.glassfish.jersey.containers:jersey-container-servlet:2.5.+' - // Servlets compile group: 'org.eclipse.jetty', name: 'jetty-server', version: '9.3.+' compile 'org.eclipse.jetty:jetty-server:9.3.+' compile 'org.eclipse.jetty:jetty-servlet:9.3.+' - // Logging - compile 'org.slf4j:slf4j-api:1.7.7' - runtime 'ch.qos.logback:logback-classic:1.1.2' - runtime 'ch.qos.logback:logback-core:1.1.2' - - // Google protobufs - compile 'com.google.protobuf:protobuf-java:3.+' - testCompile 'junit:junit:4.+' runtime 'org.codehaus.groovy:groovy:2.4.+' @@ -140,21 +123,6 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() @@ -162,13 +130,15 @@ repositories { mavenCentral() } -task "info" << { +task "info" { + doLast { println "Project: ${project.name}" -println "Description: ${project.description}" + println "Description: ${project.description}" println "--------------------------" println "GroupId: $groupId" println "Version: $version (${isSnapshot ? 'snapshot' : 'release'})" println "" + } } info.description 'Print some information about project parameters' From b360ae81bb87207e49e01281fa82b59b375822a4 Mon Sep 17 00:00:00 2001 From: Tal Moran Date: Wed, 25 Jan 2017 19:10:18 +0200 Subject: [PATCH 25/25] Fix gradle build files to work without nexus repository credentials --- build.gradle-template | 13 ++++++----- bulletin-board-client/build.gradle | 11 ++++++--- bulletin-board-server/build.gradle | 30 +++++++++---------------- distributed-key-generation/build.gradle | 16 ++++++++----- meerkat-common/build.gradle | 15 ++++++++----- mixer/build.gradle | 13 +++++++---- polling-station/build.gradle | 13 +++++++---- restful-api-common/build.gradle | 13 +++++++---- voting-booth/build.gradle | 13 +++++++---- 9 files changed, 83 insertions(+), 54 deletions(-) diff --git a/build.gradle-template b/build.gradle-template index f80c9f3..9832d46 100644 --- a/build.gradle-template +++ b/build.gradle-template @@ -25,8 +25,11 @@ ext { // Credentials for IDC nexus repositories (needed only for using unstable repositories and publishing) // Should be set in ${HOME}/.gradle/gradle.properties - nexusUser = project.hasProperty('nexusUser') ? project.property('nexusUser') : "" - nexusPassword = project.hasProperty('nexusPassword') ? project.property('nexusPassword') : "" + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "TODO: Add a description" @@ -207,12 +210,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/bulletin-board-client/build.gradle b/bulletin-board-client/build.gradle index f870887..0365e0b 100644 --- a/bulletin-board-client/build.gradle +++ b/bulletin-board-client/build.gradle @@ -16,6 +16,11 @@ ext { isSnapshot = false } ext { groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Meerkat Voting Common Library" @@ -196,12 +201,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/bulletin-board-server/build.gradle b/bulletin-board-server/build.gradle index 2ab85b0..a7a0418 100644 --- a/bulletin-board-server/build.gradle +++ b/bulletin-board-server/build.gradle @@ -21,7 +21,12 @@ apply plugin: 'maven-publish' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Bulletin-board server web application" @@ -179,25 +184,10 @@ if (project.hasProperty('mainClassName') && (mainClassName != null)) { *===================================*/ repositories { - - // Prefer the local nexus repository (it may have 3rd party artifacts not found in mavenCentral) - maven { - url nexusRepository - - if (isSnapshot) { - credentials { username - password - - username nexusUser - password nexusPassword - } - } - } - // Use local maven repository mavenLocal() - jcenter() + //jcenter() // Use 'maven central' for other dependencies. mavenCentral() @@ -233,12 +223,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/distributed-key-generation/build.gradle b/distributed-key-generation/build.gradle index b47e8f2..84f3ad1 100644 --- a/distributed-key-generation/build.gradle +++ b/distributed-key-generation/build.gradle @@ -20,10 +20,16 @@ apply plugin: 'maven-publish' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" + } -description = "TODO: Add a description" +description = "Distributed key generation code" // Your project version version = "0.0" @@ -181,12 +187,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/meerkat-common/build.gradle b/meerkat-common/build.gradle index bc380ed..e019d59 100644 --- a/meerkat-common/build.gradle +++ b/meerkat-common/build.gradle @@ -19,7 +19,12 @@ mainClassName='Demo' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Meerkat Voting Common Library" @@ -46,7 +51,7 @@ dependencies { compile 'com.google.guava:guava:15.0' // Crypto - compile 'org.factcenter.qilin:qilin:1.3.+' + compile 'org.factcenter.qilin:qilin:1.2.+' compile 'org.bouncycastle:bcprov-jdk15on:1.53' testCompile 'junit:junit:4.+' @@ -188,12 +193,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/mixer/build.gradle b/mixer/build.gradle index bdde270..2cbf45d 100644 --- a/mixer/build.gradle +++ b/mixer/build.gradle @@ -20,7 +20,12 @@ mainClassName='meerkat.mixer.main.Mix' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Mix network implementation" @@ -166,12 +171,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/polling-station/build.gradle b/polling-station/build.gradle index c45498f..bf1c1a9 100644 --- a/polling-station/build.gradle +++ b/polling-station/build.gradle @@ -21,7 +21,12 @@ apply plugin: 'maven-publish' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Meerkat polling-station application" @@ -157,12 +162,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/restful-api-common/build.gradle b/restful-api-common/build.gradle index 937b79d..07ef0af 100644 --- a/restful-api-common/build.gradle +++ b/restful-api-common/build.gradle @@ -18,7 +18,12 @@ apply plugin: 'maven-publish' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Common classes for implementing Meerkat's RESTful API" @@ -118,12 +123,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } } diff --git a/voting-booth/build.gradle b/voting-booth/build.gradle index 682f398..e5dd671 100644 --- a/voting-booth/build.gradle +++ b/voting-booth/build.gradle @@ -19,7 +19,12 @@ apply plugin: 'maven-publish' ext { isSnapshot = false } ext { - groupId = 'org.factcenter.meerkat' + groupId = 'org.factcenter.meerkat' + + // Credentials for publishing repositories + publishRepository = "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + publishUser = project.hasProperty('publishUser') ? project.property('publishUser') : "" + publishPassword = project.hasProperty('publishPassword') ? project.property('publishPassword') : "" } description = "Meerkat voting booth application" @@ -160,12 +165,12 @@ publishing { } repositories { maven { - url "https://cs.idc.ac.il/nexus/content/repositories/${project.isSnapshot ? 'snapshots' : 'releases'}" + url publishRepository credentials { username password - username nexusUser - password nexusPassword + username publishUser + password publishPassword } } }