161 lines
6.4 KiB
Java
161 lines
6.4 KiB
Java
/*
|
|
* This file is produced by Sarah Jamie Lewis, Olivier Pereira and Vanessa Teague to demonstrate a trapdoor in
|
|
* the SwissVote-Scytl implementation of Bayer-Groth proofs.
|
|
*
|
|
* It is intended to be applied to our four demonstration proof transcripts, made available along with
|
|
* this file. The transcripts pass verification but change the outcome of the election.
|
|
*
|
|
* March 1st, 2019.
|
|
*
|
|
*/
|
|
package com.scytl.products.ov.mixnet;
|
|
|
|
import java.io.ByteArrayInputStream;
|
|
import java.io.ByteArrayOutputStream;
|
|
import java.io.FileInputStream;
|
|
import java.io.IOException;
|
|
|
|
import java.math.BigInteger;
|
|
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.ArrayList;
|
|
import java.util.List;
|
|
|
|
|
|
import com.scytl.products.ov.mixnet.commons.io.*;
|
|
|
|
import org.junit.Assert;
|
|
import org.junit.BeforeClass;
|
|
import org.junit.Test;
|
|
|
|
import com.scytl.cryptolib.api.exceptions.GeneralCryptoLibException;
|
|
import com.scytl.cryptolib.elgamal.bean.ElGamalPublicKey;
|
|
import com.scytl.cryptolib.elgamal.cryptoapi.Ciphertext;
|
|
import com.scytl.cryptolib.mathematical.groups.impl.ZpSubgroup;
|
|
import com.scytl.products.ov.mixnet.commons.ballots.ElGamalEncryptedBallots;
|
|
import com.scytl.products.ov.mixnet.commons.beans.proofs.ShuffleProof;
|
|
import com.scytl.products.ov.mixnet.commons.homomorphic.impl.GjosteenElGamal;
|
|
import com.scytl.products.ov.mixnet.commons.proofs.bg.commitments.CommitmentParams;
|
|
import com.scytl.products.ov.mixnet.commons.tools.CiphertextTools;
|
|
import com.scytl.products.ov.mixnet.commons.tools.MatrixArranger;
|
|
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiation;
|
|
import com.scytl.products.ov.mixnet.commons.tools.MultiExponentiationImpl;
|
|
import com.scytl.products.ov.mixnet.commons.validation.EncryptedBallotsDuplicationValidator;
|
|
import com.scytl.products.ov.mixnet.commons.validation.EncryptedBallotsValidator;
|
|
import com.scytl.products.ov.mixnet.commons.validation.EncryptedBallotsValidatorManager;
|
|
import com.scytl.products.ov.mixnet.proofs.bg.shuffle.ShuffleProofVerifier;
|
|
|
|
import static com.scytl.products.ov.mixnet.commons.io.CommitmentParamsReader.readCommitmentParamsFromStream;
|
|
|
|
public class BaseBGMixnetIOVerifierITest {
|
|
|
|
private static ZpSubgroup zp;
|
|
|
|
private static int m;
|
|
|
|
private static int n;
|
|
|
|
|
|
private static int numiterations;
|
|
|
|
private static CommitmentParams commitmentParams;
|
|
|
|
private static GjosteenElGamal elgamal;
|
|
|
|
private static JSONProofsReader proofsReader;
|
|
|
|
private static ElGamalEncryptedBallotsLoader elgamalEncryptedBallotsLoader;
|
|
|
|
private static MultiExponentiation limMultiExpo;
|
|
|
|
private static CiphertextTools ciphertextTools;
|
|
|
|
// Comment out as appropriate depending on whether you're running the full test or the zero test
|
|
private static boolean CHEATING2 = true;
|
|
private static String zeroFlag = "";
|
|
//private static String zeroFlag = "-zero";
|
|
static String twoFlag = CHEATING2 ? "-2" : "";
|
|
|
|
private static String proofsPath="/tmp/SwissVoteTest/proofs"+twoFlag+zeroFlag+"/";
|
|
|
|
@BeforeClass
|
|
public static void setUp() throws IOException, GeneralCryptoLibException {
|
|
|
|
BigInteger p = new BigInteger("15294034768093677312256663166625633354362303");
|
|
BigInteger q = p.subtract(BigInteger.ONE).divide(BigInteger.valueOf(2));
|
|
BigInteger g = new BigInteger("2");
|
|
|
|
zp = new ZpSubgroup(g, p, q);
|
|
ElGamalPublicKey pubKey = ElgamalPublicKeyReader.readPublicKeyFromStream(new FileInputStream(proofsPath+"publicKey"+twoFlag+zeroFlag+".out"));
|
|
elgamal = new GjosteenElGamal(zp,pubKey);
|
|
|
|
m = 2;
|
|
|
|
n = 2;
|
|
|
|
proofsReader = new JSONProofsReader();
|
|
|
|
final List<EncryptedBallotsValidator> listValidators = new ArrayList<>();
|
|
listValidators.add(new EncryptedBallotsDuplicationValidator());
|
|
EncryptedBallotsValidatorManager validator = new EncryptedBallotsValidatorManager(listValidators);
|
|
elgamalEncryptedBallotsLoader = new ElGamalEncryptedBallotsLoader(validator);
|
|
|
|
limMultiExpo = MultiExponentiationImpl.getInstance();
|
|
|
|
ciphertextTools = new CiphertextTools(limMultiExpo);
|
|
}
|
|
|
|
private static CommitmentParams readCommitmentParamsFromFile() throws IOException {
|
|
|
|
final Path pathCommitmentParamsFile =
|
|
Paths.get(proofsPath+"commitmentParams"+twoFlag+zeroFlag+".out");
|
|
FileInputStream fis = new FileInputStream(pathCommitmentParamsFile.toFile());
|
|
return readCommitmentParamsFromStream(zp, fis);
|
|
}
|
|
|
|
@Test
|
|
public void givenSmallConfigWhenShuffleThenOK()
|
|
throws IOException, GeneralCryptoLibException {
|
|
|
|
// /////////////////////////////////////////////////
|
|
//
|
|
// Verify the proofs
|
|
//
|
|
// /////////////////////////////////////////////////
|
|
|
|
final ElGamalEncryptedBallots encryptedBallots_VerifierCopy =
|
|
elgamalEncryptedBallotsLoader.loadCSV(zp, new FileInputStream(proofsPath+"input"+twoFlag+zeroFlag+".csv"));
|
|
|
|
final Ciphertext[][] originalCiphertexts_VerifierCopy =
|
|
MatrixArranger.arrangeInCiphertextMatrix(encryptedBallots_VerifierCopy, m, n);
|
|
|
|
final ElGamalEncryptedBallots reencryptedBallots;
|
|
reencryptedBallots = elgamalEncryptedBallotsLoader.loadCSV(zp, new FileInputStream(
|
|
Paths.get(proofsPath+"output"+twoFlag+zeroFlag+".csv").toFile()));
|
|
|
|
final Ciphertext[][] reencryptedCiphertexts_VerifierCopy =
|
|
MatrixArranger.arrangeInCiphertextMatrix(reencryptedBallots, m, n);
|
|
|
|
commitmentParams = readCommitmentParamsFromFile();
|
|
System.out.println(commitmentParams.getG()[0]);
|
|
|
|
final ShuffleProofVerifier verifier = new ShuffleProofVerifier(zp, elgamal, commitmentParams,
|
|
originalCiphertexts_VerifierCopy, reencryptedCiphertexts_VerifierCopy, m, n, 0, numiterations,
|
|
ciphertextTools, limMultiExpo);
|
|
|
|
final ShuffleProof shuffleProof_VerifierCopy = proofsReader.read(
|
|
new FileInputStream(Paths.get(proofsPath+"complete-proof"+twoFlag+zeroFlag+".json").toFile()));
|
|
|
|
System.out.println("Shuffle Proof: "+ shuffleProof_VerifierCopy.getSecondAnswer().toString());
|
|
|
|
final boolean testResult = verifier.verifyProof(shuffleProof_VerifierCopy.getInitialMessage(),
|
|
shuffleProof_VerifierCopy.getFirstAnswer(), shuffleProof_VerifierCopy.getSecondAnswer());
|
|
|
|
final String errorMsg = "proofs failed to validate";
|
|
Assert.assertTrue(errorMsg, testResult);
|
|
}
|
|
}
|
|
|
|
|