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();