diff --git a/mixer/src/main/java/main/BatchConverter.java b/mixer/src/main/java/main/BatchConverter.java new file mode 100644 index 0000000..0ac2e93 --- /dev/null +++ b/mixer/src/main/java/main/BatchConverter.java @@ -0,0 +1,91 @@ +package main; + +import com.google.protobuf.ByteString; +import meerkat.protobuf.BulletinBoardAPI; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import qilin.util.Pair; + +import java.math.BigInteger; +import java.util.ArrayList; +import java.util.List; + +/** + * Created by Tzlil on 12/17/2015. + */ + +public class BatchConverter { + + private final int n,layers; + public BatchConverter(int n,int layers){ + this.n = n; + this.layers = layers; + } + private ByteString IntegerToByteString(int a){ + return ByteString.copyFrom(BigInteger.valueOf(a).toByteArray()); + } + + private int ByteString2Integer(ByteString bs) { + return Integer.valueOf(bs.toString()); + } + + public List mixerOutput2BatchData + (Pair mixerOutput) { + + List result = new ArrayList(); + + result.add(BulletinBoardAPI.BatchData.newBuilder() + .setData(IntegerToByteString(n)) + .build()); + + for (Mixing.ZeroKnowledgeProof[] zkpLayer : mixerOutput.a) { + for (Mixing.ZeroKnowledgeProof zkp : zkpLayer) { + result.add(BulletinBoardAPI.BatchData.newBuilder() + .setData(zkp.toByteString()) + .build()); + } + } + for (Crypto.RerandomizableEncryptedMessage[] encryptionLayer : mixerOutput.b) { + for (Crypto.RerandomizableEncryptedMessage encryption : encryptionLayer) { + result.add(BulletinBoardAPI.BatchData.newBuilder() + .setData(encryption.toByteString()) + .build()); + } + } + return result; + } + + public Pair batchDataList2MixerOutput + (List batchDataList) throws Exception { + + if (n != ByteString2Integer(batchDataList.remove(0).getData())){ + throw new Exception(); + } + + int nDiv2 = n >>1; + Mixing.ZeroKnowledgeProof[][] proofs = new Mixing.ZeroKnowledgeProof[layers][nDiv2]; + for (int layer = 0; layer (proofs,encryptions); + + } + +} + diff --git a/mixer/src/main/java/main/BatchHandler.java b/mixer/src/main/java/main/BatchHandler.java new file mode 100644 index 0000000..7e49e6b --- /dev/null +++ b/mixer/src/main/java/main/BatchHandler.java @@ -0,0 +1,79 @@ +package main; + +import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Mixing; +import necessary.AsyncBulletinBoardClient; +import necessary.BulletinBoardClient; +import necessary.CompleteBatch; +import qilin.util.Pair; +import verifier.VerifyTable; + +import java.util.Arrays; +import java.util.List; + +/** + * Created by Tzlil on 12/17/2015. + */ +public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback { + + private Pair mixerOutput; + private boolean msgReceived; + private Throwable t; + private CompleteBatch msg; + + private final int n, layers; + private final Mix2ZeroKnowledgeVerifier verifier; + + public BatchHandler(int n, int layers, Mix2ZeroKnowledgeVerifier verifier) { + this.mixerOutput = null; + this.n = n; + this.layers = layers; + this.msgReceived = false; + this.t = null; + this.verifier = verifier; + } + + @Override + public void handleCallback(CompleteBatch msg) { + this.msg = msg; + this.msgReceived = true; + } + + @Override + public void handleFailure(Throwable t) { + this.t = t; + this.msgReceived = true; + } + + + public boolean isMsgReceived() { + return msgReceived; + } + + private void convertMessage() throws Exception { + BatchConverter batchConverter = new BatchConverter(n,layers); + mixerOutput = batchConverter.batchDataList2MixerOutput(msg.getBatchDataList()); + } + + public boolean verifyTable() throws Exception { + if (mixerOutput == null) { + convertMessage(); + } + return VerifyTable.verifyTable(verifier, n, mixerOutput); + } + + public List getInputForMixer() throws Throwable { + if (t != null) { + throw t; + } + if (mixerOutput == null) { + convertMessage(); + if (!VerifyTable.verifyTable(verifier, n, mixerOutput)) { + throw new Exception("in valid table"); + } + } + return Arrays.asList(mixerOutput.b[mixerOutput.b.length - 1]); + } +} + diff --git a/mixer/src/main/java/main/MainMixing.java b/mixer/src/main/java/main/MainMixing.java index ab832d7..a37c604 100644 --- a/mixer/src/main/java/main/MainMixing.java +++ b/mixer/src/main/java/main/MainMixing.java @@ -1,7 +1,5 @@ package main; -import com.google.protobuf.ByteString; -import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.crypto.mixnet.Mixer; import meerkat.protobuf.BulletinBoardAPI; @@ -9,13 +7,10 @@ import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; import necessary.AsyncBulletinBoardClient; import necessary.BulletinBoardClient; -import necessary.SignedBatch; import qilin.util.Pair; -import java.math.BigInteger; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; @@ -24,10 +19,10 @@ import java.util.List; */ public class MainMixing { - private Mixer mixer; - private Mix2ZeroKnowledgeVerifier verifier; - private int n, layers; - private AsyncBulletinBoardClient asyncBulletinBoardClient; + private final Mixer mixer; + private final Mix2ZeroKnowledgeVerifier verifier; + private final int n, layers; + private final AsyncBulletinBoardClient asyncBulletinBoardClient; private final byte[] id; private final int mixerOrder; @@ -43,7 +38,7 @@ public class MainMixing { this.id = id; } - public void main(List prevBatchIds, int batchId, BulletinBoardClient.ClientCallback callback) throws Exception { + public void main(List prevBatchIds, int batchId, AsyncBulletinBoardClient.ClientCallback callback) throws Throwable { List mixerInput; @@ -52,11 +47,14 @@ public class MainMixing { List batchHandlers = new ArrayList(prevBatchIds.size()); BatchHandler currentBatchHandler; for (Integer prevBatchId : prevBatchIds) { - currentBatchHandler = new BatchHandler(n, layers); - asyncBulletinBoardClient.readBatch(id, prevBatchId, currentBatchHandler); + currentBatchHandler = new BatchHandler(n, layers,verifier); + asyncBulletinBoardClient.readBatch(id, prevBatchId,currentBatchHandler); batchHandlers.add(currentBatchHandler); } + // ToDo : assert table continues + // ToDo : assert signature validity + boolean allDone = false; while (!allDone) { try { @@ -64,17 +62,18 @@ public class MainMixing { } catch (InterruptedException e) { // do nothing } - // check all handlers done + // check all handlers messages were received allDone = true; for (BatchHandler batchHandler : batchHandlers) { - allDone &= batchHandler.done; + allDone &= batchHandler.isMsgReceived(); } } // assert all handlers succeeded for (BatchHandler batchHandler : batchHandlers) { - if(batchHandler.e != null) - throw batchHandler.e; + if(!batchHandler.verifyTable()){ + throw new Exception("invalid input"); + } } BatchHandler lastBatchHandler = batchHandlers.get(batchHandlers.size() - 1); @@ -93,177 +92,14 @@ public class MainMixing { private void updateBB(Pair mixerOutput - , int batchId, BulletinBoardClient.ClientCallback callback) { + , int batchId, AsyncBulletinBoardClient.ClientCallback callback) { - BatchConverter batchConverter = new BatchConverter(); + BatchConverter batchConverter = new BatchConverter(n,layers); List batchDataList = batchConverter.mixerOutput2BatchData(mixerOutput); asyncBulletinBoardClient.postBatch(id, batchId, batchDataList, callback); } - private class BatchConverter { - - ByteString IntegerToByteString(int a){ - return ByteString.copyFrom(BigInteger.valueOf(a).toByteArray()); - } - - int ByteString2Integer(ByteString bs) { - return Integer.valueOf(bs.toString()); - } - - List mixerOutput2BatchData - (Pair mixerOutput) { - - List result = new ArrayList(); - - // - - result.add(BulletinBoardAPI.BatchData.newBuilder() - .setData(IntegerToByteString(n)) - .build()); - - for (Mixing.ZeroKnowledgeProof[] zkpLayer : mixerOutput.a) { - for (Mixing.ZeroKnowledgeProof zkp : zkpLayer) { - result.add(BulletinBoardAPI.BatchData.newBuilder() - .setData(zkp.toByteString()) - .build()); - } - } - for (Crypto.RerandomizableEncryptedMessage[] encryptionLayer : mixerOutput.b) { - for (Crypto.RerandomizableEncryptedMessage encryption : encryptionLayer) { - result.add(BulletinBoardAPI.BatchData.newBuilder() - .setData(encryption.toByteString()) - .build()); - } - } - return result; - } - Pair batchDataList2MixerOutput - (List batchDataList) throws Exception { - - if (n != ByteString2Integer(batchDataList.remove(0).getData())){ - throw new Exception(); - } - - int nDiv2 = n >>1; - Mixing.ZeroKnowledgeProof[][] proofs = new Mixing.ZeroKnowledgeProof[layers][nDiv2]; - for (int layer = 0; layer (proofs,encryptions); - - } - - } - private class BatchHandler implements BulletinBoardClient.ClientCallback { - - public Pair mixerOutput; - public boolean done; - private int n,layers; - private Exception e; - - public BatchHandler(int n, int layers) { - this.n = n; - this.layers = layers; - done = false; - e = null; - } - - // convert batch message to MixerInput - // and verify it - @Override - public void handleCallback(SignedBatch msg) { - BatchConverter batchConverter = new BatchConverter(); - try { - mixerOutput = batchConverter.batchDataList2MixerOutput(msg.getBatchDataList()); - done = verifyTable(); - } catch (Exception e) { - this.e = e; - done = true; - } - } - - @Override - public void handleFailure(Throwable t) { - - } - - private boolean verifyTable() throws InvalidProtocolBufferException { - int index1,index2,layer; - - //initialize locationChecksum table - // use for check BeneshNet validity - boolean[][] locationChecksum = new boolean[layers][n]; - for (boolean[] locationChecksumLayer: locationChecksum) { - Arrays.fill(locationChecksumLayer,false); - } - - Mixing.ZeroKnowledgeProof[][] zeroKnowledgeProofs = mixerOutput.a; - Crypto.RerandomizableEncryptedMessage[][] rerandomizableEncryptedMessages = mixerOutput.b; - - for (Mixing.ZeroKnowledgeProof[] zkpLayer: zeroKnowledgeProofs) { - for (Mixing.ZeroKnowledgeProof zkp: zkpLayer) { - Mixing.ZeroKnowledgeProof.Location location = zkp.getLocation(); - index1 = location.getI(); - index2 = location.getJ(); - layer = location.getLayer(); - - // check location validity - if (layer > layers >> 1) { - if (index2 - index1 != n >> (layers - layer)) - return false; - } - else{ - if (index2 - index1 != n >> (layer + 1)) - return false; - } - - // mark location in table - locationChecksum[layer][index1] = true; - locationChecksum[layer][index2] = true; - - // verify proof - if(!verifier.verify(rerandomizableEncryptedMessages[index1][layer], - rerandomizableEncryptedMessages[index2][layer], - rerandomizableEncryptedMessages[index1][layer + 1], - rerandomizableEncryptedMessages[index2][layer + 1], - zkp)) - return false; - } - } - - // verify all necessary locations for BeneshNet were proved - for (boolean[] checksumLayer: locationChecksum) { - for (boolean locationBoolean: checksumLayer) { - if (!locationBoolean) - return false; - } - } - return true; - } - - public List getInputForMixer() - { - return Arrays.asList(mixerOutput.b[mixerOutput.b.length - 1]); - } - } - } diff --git a/mixer/src/main/java/necessary/AsyncBulletinBoardClient.java b/mixer/src/main/java/necessary/AsyncBulletinBoardClient.java index b8847f9..6dcc1f1 100644 --- a/mixer/src/main/java/necessary/AsyncBulletinBoardClient.java +++ b/mixer/src/main/java/necessary/AsyncBulletinBoardClient.java @@ -1,21 +1,30 @@ package necessary; - import meerkat.protobuf.BulletinBoardAPI.*; +import meerkat.protobuf.BulletinBoardAPI.*; - import java.util.List; +import java.util.List; /** * Created by Arbel Deutsch Peled on 14-Dec-15. */ public interface AsyncBulletinBoardClient extends BulletinBoardClient { + public interface ClientCallback { + void handleCallback(T msg); + void handleFailure(Throwable t); + } + + public interface MessageHandler { + void handleNewMessages(List messageList); + } + /** * Post a message to the bulletin board in an asynchronous manner * @param msg is the message to be posted * @param callback is a class containing methods to handle the result of the operation * @return a unique message ID for the message, that can be later used to retrieve the batch */ - MessageID postMessage(BulletinBoardMessage msg, ClientCallback callback); + public MessageID postMessage(BulletinBoardMessage msg, ClientCallback callback); /** * This method allows for sending large messages as a batch to the bulletin board @@ -26,12 +35,12 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient { * @param callback is a callback function class for handling results of the operation * @return a unique message ID for the entire message, that can be later used to retrieve the batch */ - MessageID postBatch(byte[] signerId, int batchId, List batchDataList, int startPosition, ClientCallback callback); + public MessageID postBatch(byte[] signerId, int batchId, List batchDataList, int startPosition, ClientCallback callback); /** * Overloading of the postBatch method in which startPosition is set to the default value 0 */ - MessageID postBatch(byte[] signerId, int batchId, List batchDataList, ClientCallback callback); + public MessageID postBatch(byte[] signerId, int batchId, List batchDataList, ClientCallback callback); /** * Check how "safe" a given message is in an asynchronous manner @@ -39,7 +48,7 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient { * @param id is the unique message identifier for retrieval * @param callback is a callback function class for handling results of the operation */ - void getRedundancy(MessageID id, ClientCallback callback); + public void getRedundancy(MessageID id, ClientCallback callback); /** * Read all messages posted matching the given filter in an asynchronous manner @@ -49,7 +58,7 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient { * @param filterList return only messages that match the filters (null means no filtering). * @param callback is a callback function class for handling results of the operation */ - void readMessages(MessageFilterList filterList, ClientCallback> callback); + public void readMessages(MessageFilterList filterList, ClientCallback> callback); /** * Read a given batch message from the bulletin board @@ -57,6 +66,13 @@ public interface AsyncBulletinBoardClient extends BulletinBoardClient { * @param batchId is the unique (per signer) ID of the batch * @param callback is a callback class for handling the result of the operation */ - void readBatch(byte[] signerId, int batchId, ClientCallback callback); + public void readBatch(byte[] signerId, int batchId, ClientCallback callback); + + /** + * Subscribes to a notifier that will return any new messages on the server that match the given filters + * @param filterList defines the set of filters for message retrieval + * @param messageHandler defines the handler for new messages received + */ + public void subscribe(MessageFilterList filterList, MessageHandler messageHandler); } diff --git a/mixer/src/main/java/necessary/BulletinBoardClient.java b/mixer/src/main/java/necessary/BulletinBoardClient.java index 6442c40..d8f9f28 100644 --- a/mixer/src/main/java/necessary/BulletinBoardClient.java +++ b/mixer/src/main/java/necessary/BulletinBoardClient.java @@ -56,7 +56,7 @@ public interface BulletinBoardClient { /** * Closes all connections, if any. - * This is done in a synchronous (blocking) way. + * This is msgRecived in a synchronous (blocking) way. */ void close(); diff --git a/mixer/src/main/java/necessary/CompleteBatch.java b/mixer/src/main/java/necessary/CompleteBatch.java new file mode 100644 index 0000000..d108a7d --- /dev/null +++ b/mixer/src/main/java/necessary/CompleteBatch.java @@ -0,0 +1,68 @@ +package necessary; + + + import meerkat.protobuf.BulletinBoardAPI.*; + import meerkat.protobuf.Crypto.*; + + import java.util.LinkedList; + import java.util.List; + +/** + * Created by Arbel Deutsch Peled on 14-Dec-15. + * + * A data structure for holding a complete batch message along with its signature + */ +public class CompleteBatch { + + private BeginBatchMessage beginBatchMessage; + private List batchDataList; + private Signature signature; + + public CompleteBatch() { + batchDataList = new LinkedList(); + } + + public CompleteBatch(BeginBatchMessage newBeginBatchMessage) { + this(); + beginBatchMessage = newBeginBatchMessage; + } + + public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List newDataList) { + this(newBeginBatchMessage); + appendBatchData(newDataList); + } + + public CompleteBatch(BeginBatchMessage newBeginBatchMessage, List newDataList, Signature newSignature) { + this(newBeginBatchMessage, newDataList); + signature = newSignature; + } + + public BeginBatchMessage getBeginBatchMessage() { + return beginBatchMessage; + } + + public List getBatchDataList() { + return batchDataList; + } + + public Signature getSignature() { + return signature; + } + + public void setBeginBatchMessage(BeginBatchMessage beginBatchMessage) { + this.beginBatchMessage = beginBatchMessage; + } + + public void appendBatchData(BatchData newBatchData) { + batchDataList.add(newBatchData); + } + + public void appendBatchData(List newBatchDataList) { + batchDataList.addAll(newBatchDataList); + } + + public void setSignature(Signature newSignature) { + signature = newSignature; + } + +} diff --git a/mixer/src/main/java/necessary/SignedBatch.java b/mixer/src/main/java/necessary/SignedBatch.java deleted file mode 100644 index 6aecebf..0000000 --- a/mixer/src/main/java/necessary/SignedBatch.java +++ /dev/null @@ -1,54 +0,0 @@ -package necessary; - -/** - * Created by Tzlil on 12/27/2015. - */ - - import meerkat.protobuf.BulletinBoardAPI.*; - import meerkat.protobuf.Crypto.*; - - import java.util.LinkedList; - import java.util.List; - -/** - * Created by Arbel Deutsch Peled on 14-Dec-15. - * - * A data structure for holding both a batch message and its signature - */ -public class SignedBatch { - - private List batchDataList; - private Signature signature; - - public SignedBatch() { - batchDataList = new LinkedList(); - } - - public SignedBatch(List newDataList) { - this(); - appendBatchData(newDataList); - } - - public SignedBatch(List newDataList, Signature newSignature) { - this(newDataList); - signature = newSignature; - } - - public List getBatchDataList() { - return batchDataList; - } - - public Signature getSignature() { - return signature; - } - - public void appendBatchData(BatchData newBatchData) { - batchDataList.add(newBatchData); - } - - public void appendBatchData(List newBatchDataList) { - batchDataList.addAll(newBatchDataList); - } - - -} diff --git a/mixer/src/main/java/prover/ProofOrganizer.java b/mixer/src/main/java/prover/ProofOrganizer.java index 3dae29c..16b032b 100644 --- a/mixer/src/main/java/prover/ProofOrganizer.java +++ b/mixer/src/main/java/prover/ProofOrganizer.java @@ -7,70 +7,79 @@ import meerkat.protobuf.Crypto; */ public class ProofOrganizer { - private final Crypto.RerandomizableEncryptedMessage e1; - private final Crypto.RerandomizableEncryptedMessage e2; - private final Crypto.RerandomizableEncryptedMessage e1New; - private final Crypto.RerandomizableEncryptedMessage e2New; + private final OrProofInput first; + private final OrProofInput second; + private final OrProofInput third; + private final OrProofInput fourth; + + protected ProofOrganizer(Crypto.RerandomizableEncryptedMessage e1,Crypto.RerandomizableEncryptedMessage e2 + ,Crypto.RerandomizableEncryptedMessage e1New,Crypto.RerandomizableEncryptedMessage e2New + ,Crypto.EncryptionRandomness r1,Crypto.EncryptionRandomness r2,boolean switched) { + if(!switched) { + this.first = new OrProofInput(e1, e1New, e2, e1New, r1,TrueCouple.left); + this.second = new OrProofInput(e1, e1New, e1, e2New,r1,TrueCouple.left); + this.third = new OrProofInput(e2, e1New, e2, e2New,r2,TrueCouple.right); + this.fourth = new OrProofInput(e1, e2New, e2, e2New,r2,TrueCouple.right); + }else{ + this.first = new OrProofInput(e1, e1New, e2, e1New, r2,TrueCouple.right); + this.second = new OrProofInput(e1, e1New, e1, e2New,r1,TrueCouple.right); + this.third = new OrProofInput(e2, e1New, e2, e2New,r2,TrueCouple.left); + this.fourth = new OrProofInput(e1, e2New, e2, e2New,r1,TrueCouple.left); + } + + } - //in1, out1, in2, out1, - //in1, out1, in1, out2 - //in2, out1, in2, out2, - //in1, out2, in2, out2 public ProofOrganizer(Crypto.RerandomizableEncryptedMessage e1,Crypto.RerandomizableEncryptedMessage e2 - ,Crypto.RerandomizableEncryptedMessage e1New,Crypto.RerandomizableEncryptedMessage e2New) - { - this.e1 = e1; - this.e2 = e2; - this.e1New = e1New; - this.e2New = e2New; - + ,Crypto.RerandomizableEncryptedMessage e1New,Crypto.RerandomizableEncryptedMessage e2New) { + this.first = new OrProofInput(e1, e1New, e2, e1New, null,TrueCouple.unknown); + this.second = new OrProofInput(e1, e1New, e1, e2New,null,TrueCouple.unknown); + this.third = new OrProofInput(e2, e1New, e2, e2New,null,TrueCouple.unknown); + this.fourth = new OrProofInput(e1, e2New, e2, e2New,null,TrueCouple.unknown); } public enum OrProofOrder{ first,second,third,fourth } - public Crypto.RerandomizableEncryptedMessage getE1(OrProofOrder orProofOrder) - { - switch (orProofOrder){ - case third: - return e2; - default: - return e1; - } - + public enum TrueCouple{ + left,right,unknown } - public Crypto.RerandomizableEncryptedMessage getE1New(OrProofOrder orProofOrder) - { + + public OrProofInput getOrProofInput(OrProofOrder orProofOrder){ switch (orProofOrder){ - case fourth: - return e2New; - default: - return e1New; - } - } - - public Crypto.RerandomizableEncryptedMessage getE2(OrProofOrder orProofOrder) - { - switch (orProofOrder){ - case second: - return e1; - default: - return e2; - } - - } - - public Crypto.RerandomizableEncryptedMessage getE2New(OrProofOrder orProofOrder) - { - switch (orProofOrder){ case first: - return e1New; - default: - return e2New; + return this.first; + case second: + return this.second; + case third: + return this.third; + case fourth: + return this.fourth; } + return null; + } + public class OrProofInput{ + + + public final Crypto.RerandomizableEncryptedMessage e1; + public final Crypto.RerandomizableEncryptedMessage e1New; + public final Crypto.RerandomizableEncryptedMessage e2; + public final Crypto.RerandomizableEncryptedMessage e2New; + protected final Crypto.EncryptionRandomness x; + protected final TrueCouple flag; + + private OrProofInput(Crypto.RerandomizableEncryptedMessage e1, Crypto.RerandomizableEncryptedMessage e1New, + Crypto.RerandomizableEncryptedMessage e2, Crypto.RerandomizableEncryptedMessage e2New, + Crypto.EncryptionRandomness x, TrueCouple flag) { + this.e1 = e1; + this.e1New = e1New; + this.e2 = e2; + this.e2New = e2New; + this.x = x; + this.flag = flag; + } } } diff --git a/mixer/src/main/java/prover/Prover.java b/mixer/src/main/java/prover/Prover.java index 7712a41..5cbd2c0 100644 --- a/mixer/src/main/java/prover/Prover.java +++ b/mixer/src/main/java/prover/Prover.java @@ -5,6 +5,7 @@ import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; +import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.ConcreteCrypto.ElGamalCiphertext; import meerkat.protobuf.Crypto; import meerkat.protobuf.Mixing; @@ -13,6 +14,7 @@ import qilin.primitives.RandomOracle; import qilin.primitives.concrete.ECGroup; import java.math.BigInteger; +import java.util.List; import java.util.Random; public class Prover implements Mix2ZeroKnowledgeProver { @@ -23,8 +25,6 @@ public class Prover implements Mix2ZeroKnowledgeProver { ECElGamalEncryption ecElGamalEncryption; ECPoint g,h; - Mix2ZeroKnowledgeVerifier verifier; - public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle) { this.rand = rand; @@ -33,20 +33,6 @@ public class Prover implements Mix2ZeroKnowledgeProver { this.group = ecElGamalEncryption.getGroup(); this.g = group.getGenerator(); this.h = ecElGamalEncryption.getElGamalPK().getPK(); - - verifier = null; - } - - public Prover(Random rand,ECElGamalEncryption encryptor,RandomOracle randomOracle,Mix2ZeroKnowledgeVerifier verifier) { - - this.rand = rand; - this.ecElGamalEncryption = encryptor; - this.randomOracle = randomOracle; - this.group = ecElGamalEncryption.getGroup(); - this.g = group.getGenerator(); - this.h = ecElGamalEncryption.getElGamalPK().getPK(); - - this.verifier = verifier; } @@ -60,58 +46,23 @@ public class Prover implements Mix2ZeroKnowledgeProver { Crypto.EncryptionRandomness r2) throws InvalidProtocolBufferException { Mixing.ZeroKnowledgeProof.OrProof first,second,third,fourth; - ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2); - if (!sw) - { - first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), - organizer.getE2(ProofOrganizer.OrProofOrder.first), - organizer.getE1New(ProofOrganizer.OrProofOrder.first), - organizer.getE2New(ProofOrganizer.OrProofOrder.first), - r1, true); - second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), - organizer.getE2(ProofOrganizer.OrProofOrder.second), - organizer.getE1New(ProofOrganizer.OrProofOrder.second), - organizer.getE2New(ProofOrganizer.OrProofOrder.second), r1, true); - third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), - organizer.getE2(ProofOrganizer.OrProofOrder.third), - organizer.getE1New(ProofOrganizer.OrProofOrder.third), - organizer.getE2New(ProofOrganizer.OrProofOrder.third), r2, false); - fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2(ProofOrganizer.OrProofOrder.fourth), - organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), r2, false); - } - else - { - first = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), - organizer.getE2(ProofOrganizer.OrProofOrder.first), - organizer.getE1New(ProofOrganizer.OrProofOrder.first), - organizer.getE2New(ProofOrganizer.OrProofOrder.first), - r2, false); - second = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), - organizer.getE2(ProofOrganizer.OrProofOrder.second), - organizer.getE1New(ProofOrganizer.OrProofOrder.second), - organizer.getE2New(ProofOrganizer.OrProofOrder.second), - r1, false); - third = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), - organizer.getE2(ProofOrganizer.OrProofOrder.third), - organizer.getE1New(ProofOrganizer.OrProofOrder.third), - organizer.getE2New(ProofOrganizer.OrProofOrder.third), - r2, true); - fourth = createOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2(ProofOrganizer.OrProofOrder.fourth), - organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), - r1, true); - } + ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2,r1,r2,sw); + + System.out.println("first"); + first = createOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.first)); + System.out.println("second"); + second = createOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.second)); + System.out.println("third"); + third = createOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.third)); + System.out.println("fourth"); + fourth = createOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.fourth)); + 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) @@ -120,31 +71,18 @@ public class Prover implements Mix2ZeroKnowledgeProver { .setLocation(location) .build(); - //debuging - if (verifier != null){ - if (!verifier.verify(in1,in2,out1,out2,result)){ - - System.out.print(location.toString()); - System.out.println("switch value : " + sw); - } - } - return result; } - private Mixing.ZeroKnowledgeProof.OrProof createOrProof(Crypto.RerandomizableEncryptedMessage e1, - Crypto.RerandomizableEncryptedMessage e2, - Crypto.RerandomizableEncryptedMessage e1New, - Crypto.RerandomizableEncryptedMessage e2New, - Crypto.EncryptionRandomness x, - boolean flag) throws InvalidProtocolBufferException { + private Mixing.ZeroKnowledgeProof.OrProof createOrProof(ProofOrganizer.OrProofInput orProofInput) + throws InvalidProtocolBufferException { - ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1); - ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2); - ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1New); - ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2New); + ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e1); + ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e2); + ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e1New); + ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e2New); - return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,x,flag); + return createOrProofElGamal(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProofInput.x,orProofInput.flag); } @@ -163,7 +101,7 @@ public class Prover implements Mix2ZeroKnowledgeProver { ElGamalCiphertext e1New, ElGamalCiphertext e2New, Crypto.EncryptionRandomness x, - boolean flag) { + ProofOrganizer.TrueCouple flag) { ECPoint g1 = g; ECPoint h1 = group.add(convert2ECPoint(e1New.getC1()),group.negate(convert2ECPoint(e1.getC1()))); @@ -178,68 +116,79 @@ public class Prover implements Mix2ZeroKnowledgeProver { BigInteger r = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); BigInteger c1,c2,z,zTag; ECPoint u,v,uTag,vTag; - if (flag) - { - c2 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - zTag = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - //step 1 - u = group.multiply(g1, r); - v = group.multiply(g2, r); - uTag = group.add(group.multiply(g1Tag, zTag), group.negate(group.multiply(h1Tag, c2))); - vTag = group.add(group.multiply(g2Tag, zTag), group.negate(group.multiply(h2Tag, c2))); - //step 2 - // c1 = (hash(input + step1) + group size - c2)% group size - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(group.encode(g1))) - .setH1(ByteString.copyFrom(group.encode(h1))) - .setG2(ByteString.copyFrom(group.encode(g2))) - .setH2(ByteString.copyFrom(group.encode(h2))) - .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) - .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) - .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) - .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) - .setU(ByteString.copyFrom(group.encode(u))) - .setV(ByteString.copyFrom(group.encode(v))) - .setUTag(ByteString.copyFrom(group.encode(uTag))) - .setVTag(ByteString.copyFrom(group.encode(vTag))) - .build(); - c1 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound()); - //step 3 - //z = (r + c1 * x) % group size; - z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); - } - else - { - c1 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - z = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); - //step 1 - uTag = group.multiply(g1Tag, r); - vTag = group.multiply(g2Tag, r); - u = group.add(group.multiply(g1, z), group.negate(group.multiply(h1, c1))); - v = group.add(group.multiply(g2, z), group.negate(group.multiply(h2, c1))); - //step 2 - // c1 = (hash(input + step1) + group size - c1)% group size - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle = - Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() - .setG1(ByteString.copyFrom(group.encode(g1))) - .setH1(ByteString.copyFrom(group.encode(h1))) - .setG2(ByteString.copyFrom(group.encode(g2))) - .setH2(ByteString.copyFrom(group.encode(h2))) - .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) - .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) - .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) - .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) - .setU(ByteString.copyFrom(group.encode(u))) - .setV(ByteString.copyFrom(group.encode(v))) - .setUTag(ByteString.copyFrom(group.encode(uTag))) - .setVTag(ByteString.copyFrom(group.encode(vTag))) - .build(); - c2 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound()); - //step 3 - //zTag = (r + c2 * x) % group size; - zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); + Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle forRandomOracle; + switch (flag) { + case left: + c2 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + zTag = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + //step 1 + u = group.multiply(g1, r); + v = group.multiply(g2, r); + 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 + forRandomOracle = + Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() + .setG1(ByteString.copyFrom(group.encode(g1))) + .setH1(ByteString.copyFrom(group.encode(h1))) + .setG2(ByteString.copyFrom(group.encode(g2))) + .setH2(ByteString.copyFrom(group.encode(h2))) + .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) + .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) + .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) + .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) + .setU(ByteString.copyFrom(group.encode(u))) + .setV(ByteString.copyFrom(group.encode(v))) + .setUTag(ByteString.copyFrom(group.encode(uTag))) + .setVTag(ByteString.copyFrom(group.encode(vTag))) + .build(); + c1 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c2)).mod(group.orderUpperBound()); + //step 3 + //z = (r + c1 * x) % group size; + z = r.add(c1.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); + break; + case right: + c1 = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + z = new BigInteger(ecElGamalEncryption.generateRandomness(rand).getData().toByteArray()).mod(group.orderUpperBound()); + //step 1 + uTag = group.multiply(g1Tag, r); + vTag = group.multiply(g2Tag, r); + 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 + forRandomOracle = + Mixing.ZeroKnowledgeProof.OrProof.ForRandomOracle.newBuilder() + .setG1(ByteString.copyFrom(group.encode(g1))) + .setH1(ByteString.copyFrom(group.encode(h1))) + .setG2(ByteString.copyFrom(group.encode(g2))) + .setH2(ByteString.copyFrom(group.encode(h2))) + .setG1Tag(ByteString.copyFrom(group.encode(g1Tag))) + .setH1Tag(ByteString.copyFrom(group.encode(h1Tag))) + .setG2Tag(ByteString.copyFrom(group.encode(g2Tag))) + .setH2Tag(ByteString.copyFrom(group.encode(h2Tag))) + .setU(ByteString.copyFrom(group.encode(u))) + .setV(ByteString.copyFrom(group.encode(v))) + .setUTag(ByteString.copyFrom(group.encode(uTag))) + .setVTag(ByteString.copyFrom(group.encode(vTag))) + .build(); + c2 = hash(forRandomOracle).add(group.orderUpperBound().subtract(c1)).mod(group.orderUpperBound()); + //step 3 + //zTag = (r + c2 * x) % group size; + zTag = r.add(c2.multiply(new BigInteger(x.getData().toByteArray()))).mod(group.orderUpperBound()); + break; + default: + return null; } + + //debugging + assert (group.multiply(g1, z).equals(group.add(u, group.multiply(h1,c1)))); + assert (group.multiply(g2, z).equals(group.add(v, group.multiply(h2,c1)))); + assert (group.multiply(g1Tag, zTag).equals(group.add(uTag, group.multiply(h1Tag,c2)))); + assert (group.multiply(g2Tag, zTag).equals(group.add(vTag, group.multiply(h2Tag,c2)))); + + return Mixing.ZeroKnowledgeProof.OrProof.newBuilder() .setG1(ByteString.copyFrom(group.encode(g1))) .setH1(ByteString.copyFrom(group.encode(h1))) diff --git a/mixer/src/main/java/verifier/Verifier.java b/mixer/src/main/java/verifier/Verifier.java index c8c9914..977abfc 100644 --- a/mixer/src/main/java/verifier/Verifier.java +++ b/mixer/src/main/java/verifier/Verifier.java @@ -59,41 +59,20 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { Mixing.ZeroKnowledgeProof proof) throws InvalidProtocolBufferException { ProofOrganizer organizer = new ProofOrganizer(in1,in2,out1,out2); - return verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.first), - organizer.getE2(ProofOrganizer.OrProofOrder.first), - organizer.getE1New(ProofOrganizer.OrProofOrder.first), - organizer.getE2New(ProofOrganizer.OrProofOrder.first), - proof.getFirst(),ProofOrganizer.OrProofOrder.first)&& - verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.second), - organizer.getE2(ProofOrganizer.OrProofOrder.second), - organizer.getE1New(ProofOrganizer.OrProofOrder.second), - organizer.getE2New(ProofOrganizer.OrProofOrder.second), - proof.getSecond(),ProofOrganizer.OrProofOrder.second)&& - verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.third), - organizer.getE2(ProofOrganizer.OrProofOrder.third), - organizer.getE1New(ProofOrganizer.OrProofOrder.third), - organizer.getE2New(ProofOrganizer.OrProofOrder.third), - proof.getThird(),ProofOrganizer.OrProofOrder.third)&& - verifyOrProof(organizer.getE1(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2(ProofOrganizer.OrProofOrder.fourth), - organizer.getE1New(ProofOrganizer.OrProofOrder.fourth), - organizer.getE2New(ProofOrganizer.OrProofOrder.fourth), - proof.getFourth(),ProofOrganizer.OrProofOrder.fourth); + return verifyOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.first), proof.getFirst())&& + verifyOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.second), proof.getSecond())&& + verifyOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.third), proof.getThird())&& + verifyOrProof(organizer.getOrProofInput(ProofOrganizer.OrProofOrder.fourth), proof.getFourth()); + } - - - public boolean verifyOrProof(Crypto.RerandomizableEncryptedMessage e1, - Crypto.RerandomizableEncryptedMessage e2, - Crypto.RerandomizableEncryptedMessage e1Tag, - Crypto.RerandomizableEncryptedMessage e2Tag, - Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder) throws InvalidProtocolBufferException { - - ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1); - ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2); - ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1Tag); - ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2Tag); - return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof,orProofOrder); + public boolean verifyOrProof(ProofOrganizer.OrProofInput orProofInput, Mixing.ZeroKnowledgeProof.OrProof orProof) + throws InvalidProtocolBufferException { + ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e1); + ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e2); + ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e1New); + ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(orProofInput.e2New); + return verifyElGamaOrProof(e1ElGamal,e2ElGamal,e1TagElGamal,e2TagElGamal,orProof); } @@ -173,7 +152,7 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { ElGamalCiphertext e2, ElGamalCiphertext e1New, ElGamalCiphertext e2New, - Mixing.ZeroKnowledgeProof.OrProof orProof, ProofOrganizer.OrProofOrder orProofOrder) + Mixing.ZeroKnowledgeProof.OrProof orProof) { parseOrProof(orProof); List conditions = createConditionsList(e1,e2,e1New,e2New); @@ -184,7 +163,6 @@ public class Verifier implements Mix2ZeroKnowledgeVerifier { if (result){ result = false; System.out.print("\n\n\n"); - System.out.println(orProofOrder.toString()); } System.out.println(condition.errorDescripton); } diff --git a/mixer/src/test/java/mixer/MixingText.java b/mixer/src/test/java/mixer/MixingText.java index a4b9c81..ac05513 100644 --- a/mixer/src/test/java/mixer/MixingText.java +++ b/mixer/src/test/java/mixer/MixingText.java @@ -50,7 +50,7 @@ public class MixingText { randomProver = new Random(); randomOracle = new DigestOracle(); verifier = new Verifier(encryptor,randomOracle); - prover = new Prover(randomProver,encryptor,randomOracle,verifier); + prover = new Prover(randomProver,encryptor,randomOracle); mixer = new Mixer(randomMixer,prover,encryptor); // generate n diff --git a/mixer/src/test/java/mixer/RerandomizeTest.java b/mixer/src/test/java/mixer/RerandomizeTest.java new file mode 100644 index 0000000..6e29bb5 --- /dev/null +++ b/mixer/src/test/java/mixer/RerandomizeTest.java @@ -0,0 +1,85 @@ +package mixer; + +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.protobuf.ConcreteCrypto; +import meerkat.protobuf.Crypto; +import meerkat.protobuf.Voting; +import org.bouncycastle.math.ec.ECPoint; +import org.junit.Before; +import org.junit.Test; +import prover.Prover; +import qilin.primitives.RandomOracle; +import qilin.primitives.concrete.DigestOracle; +import qilin.primitives.concrete.ECElGamal; +import qilin.primitives.concrete.ECGroup; +import verifier.Verifier; + +import java.math.BigInteger; +import java.util.Random; + +/** + * Created by Tzlil on 1/17/2016. + */ +public class RerandomizeTest { + + Random rand; + ECElGamal.SK key; + ECGroup group; + ECElGamalEncryption enc; + ConcreteCrypto.ElGamalPublicKey serializedPk; + ECPoint g ; + ECPoint h ; + @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 = Utiles.serializePk(group, key); + enc = new ECElGamalEncryption(); + enc.init(serializedPk); + RandomOracle randomOracle = new DigestOracle(); + g = group.getGenerator(); + h = enc.getElGamalPK().getPK(); + } + + private ECPoint convert2ECPoint(ByteString bs){ + return group.decode(bs.toByteArray()); + } + + public void oneRerandomizeTest() throws InvalidProtocolBufferException { + Voting.PlaintextBallot msg = Utiles.genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15. + + Crypto.EncryptionRandomness r = enc.generateRandomness(rand); + + + Crypto.RerandomizableEncryptedMessage e = enc.encrypt(msg, enc.generateRandomness(rand)); + Crypto.RerandomizableEncryptedMessage eNew = enc.rerandomize(e, r); + + assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e).equals(msg)); + assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, eNew).equals(msg)); + + ConcreteCrypto.ElGamalCiphertext eElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e); + ConcreteCrypto.ElGamalCiphertext eNewElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(eNew); + + assert (g.multiply(new BigInteger(r.getData().toByteArray())).equals( + group.add(convert2ECPoint(eNewElGamal.getC1()),group.negate(convert2ECPoint(eElGamal.getC1()))))); + assert (h.multiply(new BigInteger(r.getData().toByteArray())).equals( + group.add(convert2ECPoint(eNewElGamal.getC2()), group.negate(convert2ECPoint(eElGamal.getC2()))))); + } + + @Test + public void rerandomizeTest() throws InvalidProtocolBufferException { + + int tests = 1000; + + for (int i = 0; i < tests; i ++){ + System.out.println("rerandomiz test #" + i); + oneRerandomizeTest(); + } + } +} diff --git a/mixer/src/test/java/mixer/ZeroKnowledgeProofTest.java b/mixer/src/test/java/mixer/ZeroKnowledgeProofTest.java index 9c50f74..a0952e2 100644 --- a/mixer/src/test/java/mixer/ZeroKnowledgeProofTest.java +++ b/mixer/src/test/java/mixer/ZeroKnowledgeProofTest.java @@ -1,5 +1,6 @@ package mixer; +import com.google.protobuf.ByteString; import com.google.protobuf.InvalidProtocolBufferException; import meerkat.crypto.concrete.ECElGamalEncryption; import meerkat.crypto.mixnet.Mix2ZeroKnowledgeProver; @@ -7,6 +8,7 @@ import meerkat.crypto.mixnet.Mix2ZeroKnowledgeVerifier; import meerkat.protobuf.ConcreteCrypto; import meerkat.protobuf.Crypto; import meerkat.protobuf.Voting; +import org.bouncycastle.math.ec.ECPoint; import org.junit.Before; import org.junit.Test; import prover.Prover; @@ -45,12 +47,11 @@ public class ZeroKnowledgeProofTest { prover = new Prover(new Random(),enc,randomOracle); } - - - + private ECPoint convert2ECPoint(ByteString bs){ + return group.decode(bs.toByteArray()); + } public void oneZKPTest() throws InvalidProtocolBufferException { - Voting.PlaintextBallot msg1 = Utiles.genRandomBallot(2,3,16); // 2 questions with 3 answers each, in range 0-15. Voting.PlaintextBallot msg2 = Utiles.genRandomBallot(2,3,16); Crypto.EncryptionRandomness r1 = enc.generateRandomness(rand); @@ -58,13 +59,33 @@ public class ZeroKnowledgeProofTest { Crypto.RerandomizableEncryptedMessage e1 = enc.encrypt(msg1, enc.generateRandomness(rand)); Crypto.RerandomizableEncryptedMessage e2 = enc.encrypt(msg2, enc.generateRandomness(rand)); - Crypto.RerandomizableEncryptedMessage e1Tag = enc.rerandomize(e1, r1); - Crypto.RerandomizableEncryptedMessage e2Tag = enc.rerandomize(e2, r2); + Crypto.RerandomizableEncryptedMessage e1New = enc.rerandomize(e1, r1); + Crypto.RerandomizableEncryptedMessage e2New = enc.rerandomize(e2, r2); + assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1).equals(msg1)); - assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1Tag).equals(msg1)); + assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e1New).equals(msg1)); assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2).equals(msg2)); - assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2Tag).equals(msg2)); - assert (verifier.verify(e1,e2,e1Tag,e2Tag,prover.prove(e1,e2,e1Tag,e2Tag,false,0,0,0,r1,r2))); + assert (Utiles.decrypt(Voting.PlaintextBallot.class, key, group, e2New).equals(msg2)); + + ECPoint g = group.getGenerator(); + ECPoint h = enc.getElGamalPK().getPK(); + + ConcreteCrypto.ElGamalCiphertext e1ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1); + ConcreteCrypto.ElGamalCiphertext e2ElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2); + ConcreteCrypto.ElGamalCiphertext e1TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e1New); + ConcreteCrypto.ElGamalCiphertext e2TagElGamal = ECElGamalEncryption.rerandomizableEncryptedMessage2ElGamalCiphertext(e2New); + + + assert (g.multiply(new BigInteger(r1.getData().toByteArray())).equals( + group.add(convert2ECPoint(e1TagElGamal.getC1()),group.negate(convert2ECPoint(e1ElGamal.getC1()))))); + assert (h.multiply(new BigInteger(r1.getData().toByteArray())).equals( + group.add(convert2ECPoint(e1TagElGamal.getC2()),group.negate(convert2ECPoint(e1ElGamal.getC2()))))); + assert (g.multiply(new BigInteger(r2.getData().toByteArray())).equals( + group.add(convert2ECPoint(e2TagElGamal.getC1()),group.negate(convert2ECPoint(e2ElGamal.getC1()))))); + assert (h.multiply(new BigInteger(r2.getData().toByteArray())).equals( + group.add(convert2ECPoint(e2TagElGamal.getC2()),group.negate(convert2ECPoint(e2ElGamal.getC2()))))); + + assert (verifier.verify(e1,e2,e1New,e2New,prover.prove(e1,e2,e1New,e2New,false,0,0,0,r1,r2))); } @Test @@ -73,7 +94,7 @@ public class ZeroKnowledgeProofTest { int tests = 1000; for (int i = 0; i < tests; i ++){ - System.out.println("test " + i); + System.out.println("ZKP test #" + i); oneZKPTest(); } }