More refactoring, wrote command-line mixer application (no BB access as of yet)
parent
273338010d
commit
43d4fb75b2
|
@ -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<ECPoint> 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 extends Message> T decrypt(Class<T> 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<ECPoint, ECPoint>(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");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -10,4 +10,4 @@ message BroadcastMessage {
|
|||
bool is_private = 3;
|
||||
|
||||
bytes payload = 5;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.+'
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
../gradlew
|
|
@ -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<RerandomizableEncryptedMessage> ciphertexts,Random random) throws InvalidProtocolBufferException {
|
||||
|
@ -197,5 +197,4 @@ public class MixGenerator {
|
|||
|
||||
return new meerkat.mixer.MixerOutput(logN, proofsTable, encryptionTable);
|
||||
}
|
||||
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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<BulletinBoardAPI.BatchChunk> 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
|
||||
|
|
|
@ -12,8 +12,8 @@ import java.util.List;
|
|||
|
||||
/**
|
||||
* Created by Tzlil on 12/17/2015.
|
||||
* implements AsyncBulletinBoardClient.ClientCallback<CompleteBatch>
|
||||
*/
|
||||
* Handles callback for receiving a complete mix proof table from the bulletin board.
|
||||
*/
|
||||
public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<CompleteBatch> {
|
||||
|
||||
private MixerOutput mixerOutput;
|
||||
|
@ -61,7 +61,7 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
|
|||
}
|
||||
|
||||
/**
|
||||
* convert batch data to meerkat.mixer.network output
|
||||
* convert batch data to meerkat.mixProverVerifier.network output
|
||||
* @throws Exception
|
||||
*/
|
||||
private void convertMessage() throws Exception {
|
||||
|
@ -71,29 +71,29 @@ public class BatchHandler implements AsyncBulletinBoardClient.ClientCallback<Com
|
|||
|
||||
/**
|
||||
* call convert message, and if succeed verify the table
|
||||
* @return return true iff the given batch message is valid meerkat.mixer.network output
|
||||
* @return return true iff the given batch message is valid meerkat.mixProverVerifier.network output
|
||||
* @throws Exception
|
||||
*/
|
||||
public boolean verifyTable() throws Exception {
|
||||
public boolean verifyTable(boolean strict) throws Exception {
|
||||
if (mixerOutput == null) {
|
||||
convertMessage();
|
||||
}
|
||||
return MixVerifier.verifyTable(verifier, mixerOutput);
|
||||
return MixVerifier.verifyTable(verifier, mixerOutput, strict);
|
||||
}
|
||||
|
||||
/**
|
||||
* extract input for meerkat.mixer.network from previous mixers output
|
||||
* extract input for meerkat.mixProverVerifier.network from previous mixers output
|
||||
* @return last layer of encrypted votes as list
|
||||
* @throws Throwable in case if failure
|
||||
*/
|
||||
public List<Crypto.RerandomizableEncryptedMessage> getInputForMixer() throws Throwable {
|
||||
public List<Crypto.RerandomizableEncryptedMessage> 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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Integer> prevBatchIds, int batchId, Random random, AsyncBulletinBoardClient.ClientCallback<?> callback) throws Throwable {
|
||||
public void main(List<Integer> prevBatchIds, int batchId, boolean strictVerification, Random random, AsyncBulletinBoardClient.ClientCallback<?> callback) throws Throwable {
|
||||
|
||||
List<Crypto.RerandomizableEncryptedMessage> 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
|
||||
|
|
|
@ -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<Crypto.RerandomizableEncryptedMessage> 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<String> 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<Void> OPT_HELP = parser.accepts("help", "Print help");
|
||||
final OptionSpec<Void> OPT_GENKEY = parser.accepts("genkey", "Generate a key-pair (write into key file)");
|
||||
final OptionSpec<Void> OPT_DECRYPT = parser.accepts("decrypt", "Decrypt using given keypair");
|
||||
final OptionSpec<File> OPT_KEYFILE = parser.accepts("keys", "File containing public key (or keypair for decryption)").withRequiredArg().ofType(File.class);
|
||||
final OptionSpec<Void> OPT_ENCRYPT = parser.accepts("encrypt", "Decrypt using given keypair");
|
||||
final OptionSpec<Void> OPT_STRICT = parser.accepts("strict", "Use strict verification (verify that network matches our Benes implementation)");
|
||||
final OptionSpec<File> 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<File> 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();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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 {
|
||||
|
||||
|
|
|
@ -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<Crypto.RerandomizableEncryptedMessage> 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<Crypto.RerandomizableEncryptedMessage> 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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<Crypto.RerandomizableEncryptedMessage> generateMixerInput(){
|
||||
public List<Crypto.RerandomizableEncryptedMessage> generateMixerInput(int n){
|
||||
List<Crypto.RerandomizableEncryptedMessage> result = new ArrayList<Crypto.RerandomizableEncryptedMessage>();
|
||||
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<Crypto.RerandomizableEncryptedMessage> mixerInput = generateMixerInput();
|
||||
List<Crypto.RerandomizableEncryptedMessage> 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");
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<ECPoint> 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 extends Message> T decrypt(Class<T> 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<ECPoint, ECPoint>(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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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++){
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue