Committing before moving to another new and better branch
parent
9d19d82477
commit
3f5b5ab1e4
|
@ -78,7 +78,7 @@ message BallotQuestionNew {
|
||||||
bool is_mandatory = 1;
|
bool is_mandatory = 1;
|
||||||
UIElement question = 2;
|
UIElement question = 2;
|
||||||
UIElement description = 3;
|
UIElement description = 3;
|
||||||
repeated UIElement answers = 4;
|
repeated UIElement answer = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -110,7 +110,7 @@ message ElectionParams {
|
||||||
uint32 mixerThreshold = 5;
|
uint32 mixerThreshold = 5;
|
||||||
|
|
||||||
// Candidate list (or other question format)
|
// Candidate list (or other question format)
|
||||||
repeated BallotQuestionNew questions = 6;
|
repeated BallotQuestionNew question = 6;
|
||||||
|
|
||||||
// Translation table between answers and plaintext encoding
|
// Translation table between answers and plaintext encoding
|
||||||
//BallotAnswerTranslationTable answerTranslationTable = 7;
|
//BallotAnswerTranslationTable answerTranslationTable = 7;
|
||||||
|
|
|
@ -11,7 +11,6 @@ import meerkat.crypto.Encryption;
|
||||||
import meerkat.protobuf.Crypto.EncryptionPublicKey;
|
import meerkat.protobuf.Crypto.EncryptionPublicKey;
|
||||||
import meerkat.protobuf.Crypto.EncryptionRandomness;
|
import meerkat.protobuf.Crypto.EncryptionRandomness;
|
||||||
import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage;
|
import meerkat.protobuf.Crypto.RerandomizableEncryptedMessage;
|
||||||
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
|
|
||||||
|
|
||||||
public class EncryptionFake implements Encryption {
|
public class EncryptionFake implements Encryption {
|
||||||
|
|
||||||
|
@ -43,7 +42,7 @@ public class EncryptionFake implements Encryption {
|
||||||
throws InvalidProtocolBufferException {
|
throws InvalidProtocolBufferException {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
System.err.println("rerandomize: not implemented!");
|
System.err.println("rerandomize: not implemented!");
|
||||||
throw new NotImplementedException();
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,18 +1,28 @@
|
||||||
package meerkat.voting;
|
package meerkat.voting;
|
||||||
|
|
||||||
|
import meerkat.crypto.concrete.ECElGamalEncryption;
|
||||||
|
import meerkat.crypto.concrete.GlobalCryptoSetup;
|
||||||
|
import meerkat.protobuf.ConcreteCrypto;
|
||||||
import meerkat.protobuf.Voting.*;
|
import meerkat.protobuf.Voting.*;
|
||||||
import meerkat.crypto.Encryption;
|
import meerkat.crypto.Encryption;
|
||||||
import meerkat.protobuf.Crypto.*;
|
import meerkat.protobuf.Crypto.*;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.security.KeyFactory;
|
||||||
import java.util.List;
|
import java.security.NoSuchAlgorithmException;
|
||||||
|
import java.security.PublicKey;
|
||||||
|
import java.security.spec.InvalidKeySpecException;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
import com.google.protobuf.ByteString;
|
||||||
|
import org.bouncycastle.jce.spec.*;
|
||||||
|
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.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
|
||||||
public class VotingBoothToy implements VotingBooth, Runnable {
|
public class VotingBoothToy implements VotingBooth, Runnable {
|
||||||
|
@ -29,18 +39,18 @@ public class VotingBoothToy implements VotingBooth, Runnable {
|
||||||
private VotingBooth.UI m_ui;
|
private VotingBooth.UI m_ui;
|
||||||
|
|
||||||
//TODO: where do I use these?
|
//TODO: where do I use these?
|
||||||
SignatureVerificationKey a_signatureKeys[];
|
//SignatureVerificationKey a_signatureKeys[];
|
||||||
|
|
||||||
Encryption m_encryption;
|
Encryption m_encryptor;
|
||||||
Random m_random;
|
Random m_random;
|
||||||
|
|
||||||
|
Logger logger;
|
||||||
|
|
||||||
|
|
||||||
public VotingBoothToy () {
|
public VotingBoothToy () {
|
||||||
|
logger = LoggerFactory.getLogger(VotingBoothToy.class);
|
||||||
a_queue = new ArrayBlockingQueue<VBMessage> (m_queueSize, true);
|
a_queue = new ArrayBlockingQueue<VBMessage> (m_queueSize, true);
|
||||||
|
|
||||||
m_encryption = new EncryptionFake(m_ballotEncryptionKey);
|
|
||||||
m_random = new Random();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerUI (UI ui) {
|
public void registerUI (UI ui) {
|
||||||
|
@ -76,11 +86,11 @@ public class VotingBoothToy implements VotingBooth, Runnable {
|
||||||
|
|
||||||
// encrypt
|
// encrypt
|
||||||
RerandomizableEncryptedMessage encMsg;
|
RerandomizableEncryptedMessage encMsg;
|
||||||
EncryptionRandomness rnd = m_encryption.generateRandomness(m_random);
|
EncryptionRandomness rnd = m_encryptor.generateRandomness(m_random);
|
||||||
try {
|
try {
|
||||||
// simulate taking a lot of time
|
// simulate taking a lot of time
|
||||||
Thread.sleep(30000);
|
Thread.sleep(5000);
|
||||||
encMsg = m_encryption.encrypt(ptb, rnd);
|
encMsg = m_encryptor.encrypt(ptb, rnd);
|
||||||
}
|
}
|
||||||
catch (InterruptedException e) {
|
catch (InterruptedException e) {
|
||||||
System.err.println("debug: VotingBoothToy encrypt interrupted!");
|
System.err.println("debug: VotingBoothToy encrypt interrupted!");
|
||||||
|
@ -117,20 +127,56 @@ public class VotingBoothToy implements VotingBooth, Runnable {
|
||||||
this.m_ballotEncryptionKey = globalParams.getBallotEncryptionKey();
|
this.m_ballotEncryptionKey = globalParams.getBallotEncryptionKey();
|
||||||
//this.l_questions = globalParams.getQuestionsList();
|
//this.l_questions = globalParams.getQuestionsList();
|
||||||
|
|
||||||
List<SignatureVerificationKey> l_signatureKeys = boothParams.getPscVerificationKeysList();
|
// List<SignatureVerificationKey> l_signatureKeys = boothParams.getPscVerificationKeysList();
|
||||||
a_signatureKeys = new SignatureVerificationKey[l_signatureKeys.size()];
|
// a_signatureKeys = new SignatureVerificationKey[l_signatureKeys.size()];
|
||||||
int i = 0;
|
// int i = 0;
|
||||||
for (SignatureVerificationKey q: l_signatureKeys) {
|
// for (SignatureVerificationKey q: l_signatureKeys) {
|
||||||
a_signatureKeys[i] = q;
|
// a_signatureKeys[i] = q;
|
||||||
++i;
|
// ++i;
|
||||||
}
|
// }
|
||||||
|
|
||||||
|
m_random = new Random();
|
||||||
|
ECGroup group = new ECGroup("secp256k1");
|
||||||
|
java.math.BigInteger sk = ECElGamal.generateSecretKey(group, m_random);
|
||||||
|
ElGamal.SK<ECPoint> key = new ECElGamal.SK(group, sk);
|
||||||
|
ConcreteCrypto.ElGamalPublicKey serializedPk = serializePk(group, key);
|
||||||
|
m_encryptor = new ECElGamalEncryption();
|
||||||
|
m_encryptor.init(serializedPk);
|
||||||
|
|
||||||
|
|
||||||
|
//TODO: generate my own signature key
|
||||||
|
System.err.println("Here the controller should create its own signature key");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void registerVBUI (VotingBooth.UI ui)
|
|
||||||
{
|
/**
|
||||||
m_ui = ui;
|
* This method was copied from a test file
|
||||||
|
* It must be resolved in another way!
|
||||||
|
* //TODO: where should this method be declared?
|
||||||
|
*/
|
||||||
|
public ConcreteCrypto.ElGamalPublicKey serializePk(ECGroup group, ElGamal.PK<ECPoint> pk) {
|
||||||
|
ECPoint pkPoint = pk.getPK();
|
||||||
|
ECParameterSpec params = group.getCurveParams();
|
||||||
|
|
||||||
|
ECPublicKeySpec pubKeySpec = new ECPublicKeySpec(pkPoint, params);
|
||||||
|
|
||||||
|
try {
|
||||||
|
final String ENCRYPTION_KEY_ALGORITHM = "ECDH";
|
||||||
|
|
||||||
|
KeyFactory fact = KeyFactory.getInstance(ENCRYPTION_KEY_ALGORITHM,
|
||||||
|
GlobalCryptoSetup.getBouncyCastleProvider());
|
||||||
|
PublicKey javaPk = fact.generatePublic(pubKeySpec);
|
||||||
|
ConcreteCrypto.ElGamalPublicKey serializedPk = ConcreteCrypto.ElGamalPublicKey.newBuilder()
|
||||||
|
.setSubjectPublicKeyInfo(ByteString.copyFrom(javaPk.getEncoded())).build();
|
||||||
|
|
||||||
|
return serializedPk;
|
||||||
|
} catch (NoSuchAlgorithmException |InvalidKeySpecException e) {
|
||||||
|
System.err.println("Should never happen!");
|
||||||
|
throw new RuntimeException("Error converting public key!", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see meerkat.voting.VotingBooth#submitBallot(meerkat.protobuf.Voting.PlaintextBallot)
|
* @see meerkat.voting.VotingBooth#submitBallot(meerkat.protobuf.Voting.PlaintextBallot)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -1,120 +1,275 @@
|
||||||
/**
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
package meerkat.voting;
|
package meerkat.voting;
|
||||||
|
|
||||||
|
import com.google.protobuf.ByteString;
|
||||||
|
import meerkat.protobuf.Voting;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.util.Date;
|
import java.util.*;
|
||||||
import java.util.List;
|
|
||||||
import java.util.StringTokenizer;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.ArrayBlockingQueue;
|
import java.util.concurrent.ArrayBlockingQueue;
|
||||||
|
|
||||||
import com.google.protobuf.ByteString;
|
|
||||||
|
|
||||||
import meerkat.protobuf.Voting.*;
|
|
||||||
import meerkat.voting.VotingBooth.UI;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author hai
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public class VotingBoothToyConsoleUI implements UI, Runnable {
|
|
||||||
|
|
||||||
|
public class VotingBoothToyConsoleUI implements VotingBooth.UI, Runnable {
|
||||||
private BufferedReader m_in;
|
private BufferedReader m_in;
|
||||||
private VotingBooth m_vbController;
|
private VotingBooth m_vbController;
|
||||||
//private SharedPlaintextBallotMessage m_sharedPlaintext;
|
|
||||||
//private SharedEncryptedBallotMessage m_sharedEncrypted;
|
|
||||||
private ArrayBlockingQueue<VBMessage> a_queue;
|
private ArrayBlockingQueue<VBMessage> a_queue;
|
||||||
static private int m_queueSize = 5;
|
static private int m_queueSize = 5;
|
||||||
private BallotQuestionNew a_questions[];
|
private Voting.BallotQuestionNew a_questions[];
|
||||||
private int m_serialNumber;
|
private int m_serialNumber;
|
||||||
private PlaintextBallot m_plaintextBallot;
|
private Voting.PlaintextBallot m_plaintextBallot;
|
||||||
private EncryptedBallot m_encryptedBallot;
|
private Voting.EncryptedBallot m_encryptedBallot;
|
||||||
private BallotSecrets m_ballotSecrets;
|
private Voting.BallotSecrets m_ballotSecrets;
|
||||||
private int m_waitForControllerMillisecTimeout = 10;
|
private final Logger logger;
|
||||||
|
private String m_channel;
|
||||||
|
private boolean b_isInitialized;
|
||||||
|
private boolean b_allowRecastOfAudittedBallot;
|
||||||
|
private int m_waitForControllerMillisecTimeout = 100;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* constructor for the Console-UI class
|
||||||
|
*/
|
||||||
|
public VotingBoothToyConsoleUI() {
|
||||||
|
logger = LoggerFactory.getLogger(VotingBoothToyConsoleUI.class);
|
||||||
|
|
||||||
public VotingBoothToyConsoleUI () {
|
a_queue = new ArrayBlockingQueue<>(m_queueSize, true);
|
||||||
a_queue = new ArrayBlockingQueue<VBMessage> (m_queueSize, true);
|
|
||||||
}
|
|
||||||
|
|
||||||
public VotingBoothToyConsoleUI(ElectionParams globalParams) {
|
|
||||||
m_serialNumber = 0;
|
|
||||||
|
|
||||||
List<BallotQuestionNew> l_questions = globalParams.getQuestionsList();
|
|
||||||
a_questions = new BallotQuestionNew[l_questions.size()];
|
|
||||||
m_in = new BufferedReader(new InputStreamReader(System.in));
|
m_in = new BufferedReader(new InputStreamReader(System.in));
|
||||||
|
|
||||||
|
b_isInitialized = false;
|
||||||
|
b_allowRecastOfAudittedBallot = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* a function for setting behavior of the VotingBoothToy.
|
||||||
|
* If it is set to true, then a ballot which was auditted can be printed again for casting.
|
||||||
|
* If it is false, then after auditing, the voter has to answer all questions again.
|
||||||
|
* Default is false (cannot re-cast an auditted ballot)
|
||||||
|
*/
|
||||||
|
public void setAllowRecastOfAudittedBallot (boolean b) {
|
||||||
|
b_allowRecastOfAudittedBallot = b;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* initialize the election params
|
||||||
|
*/
|
||||||
|
public void init(Voting.ElectionParams globalParams) {
|
||||||
|
m_serialNumber = 0;
|
||||||
|
|
||||||
|
List<Voting.BallotQuestionNew> l_questions = globalParams.getQuestionList();
|
||||||
|
a_questions = new Voting.BallotQuestionNew[l_questions.size()];
|
||||||
|
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (BallotQuestionNew q: l_questions) {
|
for (Voting.BallotQuestionNew q: l_questions) {
|
||||||
a_questions[i] = q;
|
a_questions[i] = q;
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
b_isInitialized = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
logger.debug("run: initializing the magic!");
|
||||||
|
|
||||||
|
if ((! b_isInitialized) || isHardwareKeyInserted())
|
||||||
|
{
|
||||||
|
runAdminSetupScenario();
|
||||||
|
}
|
||||||
|
|
||||||
|
runVoterScenario();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checks if someone inserted a hardware key.
|
||||||
|
* This is used to decided whther to run Voter scenario or Admin-Setup scenario
|
||||||
|
*/
|
||||||
|
private boolean isHardwareKeyInserted() {
|
||||||
|
logger.warn("isHardwareKeyInserted: currently always false -> so running Voter scenario");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runVoterScenario() {
|
||||||
|
while (true) {
|
||||||
|
logger.debug("votingBegin: preparing console UI for a new user.");
|
||||||
|
// clear history from memory
|
||||||
|
eraseEncryption();
|
||||||
|
erasePlaintext();
|
||||||
|
showWelcomeScreen();
|
||||||
|
++m_serialNumber;
|
||||||
|
runVotingFlow();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void runAdminSetupScenario() {
|
||||||
|
if (! isHardwareKeyInserted())
|
||||||
|
{
|
||||||
|
System.out.println ("Waiting For hardware key to be inserted by admin...");
|
||||||
|
showNotInitializedScreen();
|
||||||
|
}
|
||||||
|
while (! isHardwareKeyInserted())
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
catch (InterruptedException e)
|
||||||
|
{
|
||||||
|
logger.error ("runAdminSetupScenario: interrupted while waiting for admin hardware key to be inserted");
|
||||||
|
throw new RuntimeException("runAdminSetupScenario: interrupted while waiting for admin hardware key to be inserted");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println ("runAdminSetupScenario: found hardware key");
|
||||||
|
throw new UnsupportedOperationException("runAdminSetupScenario: not yet implemented");
|
||||||
|
}
|
||||||
|
|
||||||
|
private String readInputLine() {
|
||||||
|
String s;
|
||||||
|
try {
|
||||||
|
s = this.m_in.readLine();
|
||||||
|
} catch (IOException e) {
|
||||||
|
logger.error("readInputLine: some error with reading input. " + e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see meerkat.voting.VotingBooth.UI#votingBegin()
|
* @see meerkat.voting.VotingBooth.UI#votingBegin()
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void votingBegin() {
|
public void votingBegin() {
|
||||||
System.err.println ("UI debug: preparing console UI for a new user.");
|
throw new UnsupportedOperationException("votingBegin: this is actually not a good method for the interface. just run() instead");
|
||||||
|
}
|
||||||
|
|
||||||
// clear history from memory
|
|
||||||
eraseEncryption();
|
|
||||||
erasePlaintext();
|
|
||||||
|
|
||||||
System.out.println ("UI screen: Welcome. Press to start");
|
/*
|
||||||
|
* This is a welcome screen for the voter
|
||||||
|
*/
|
||||||
|
private void showWelcomeScreen() {
|
||||||
|
System.out.println("UI screen: Welcome. Press to start");
|
||||||
readInputLine();
|
readInputLine();
|
||||||
|
|
||||||
++ m_serialNumber;
|
|
||||||
|
|
||||||
runVotingFlow ();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void runVotingFlow () {
|
/*
|
||||||
|
* This is a not-initialized error message screen
|
||||||
|
*/
|
||||||
|
private void showNotInitializedScreen() {
|
||||||
|
System.out.println("UI screen: Election params were not yet initialized");
|
||||||
|
System.out.println("UI screen: You must reboot the machine with an admin USB stick plugged in");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* erase previous encryption from memory
|
||||||
|
*/
|
||||||
|
private void eraseEncryption() {
|
||||||
|
//TODO: should we clean memory 'stronger'?
|
||||||
|
if (m_encryptedBallot != null) {
|
||||||
|
m_encryptedBallot = null;
|
||||||
|
}
|
||||||
|
if (m_ballotSecrets != null) {
|
||||||
|
m_ballotSecrets = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* erase previous plaintext from memory
|
||||||
|
*/
|
||||||
|
private void erasePlaintext() {
|
||||||
|
//TODO: should we clean memory 'stronger'?
|
||||||
|
if (m_plaintextBallot != null) {
|
||||||
|
m_plaintextBallot = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The voter first needs to choose a channel
|
||||||
|
*/
|
||||||
|
|
||||||
|
private String chooseChannel() {
|
||||||
|
System.out.println("UI screen: Choose channel");
|
||||||
|
System.out.println("UI screen: currently does nothing. Just type any string you like");
|
||||||
|
m_channel = readInputLine();
|
||||||
|
return m_channel;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The voting process itself
|
||||||
|
*/
|
||||||
|
private void runVotingFlow() {
|
||||||
try {
|
try {
|
||||||
|
boolean votingOccured = listQuestionsToUserAndGetAnswers();
|
||||||
boolean votingOccured = listQuestionsToUserAndGetAnswers ();
|
if (votingOccured) {
|
||||||
|
|
||||||
if (! votingOccured)
|
|
||||||
{
|
|
||||||
// cancel vote;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
printBallotFlow();
|
printBallotFlow();
|
||||||
}
|
}
|
||||||
|
} catch (IOException e) {
|
||||||
}
|
|
||||||
catch (IOException e) {
|
|
||||||
System.err.println("UI debug: IO error");
|
System.err.println("UI debug: IO error");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void printBallotFlow () throws IOException{
|
||||||
|
logger.warn("UI debug: printBallotFlow currently not multithreaded... will fix it...");
|
||||||
|
|
||||||
|
boolean ended = false;
|
||||||
|
while (!ended) {
|
||||||
|
sendBallotToControllerForEncryptionAndWaitForResponse ();
|
||||||
|
sendBallotToPrinterAndWaitToEnd();
|
||||||
|
ended = castOrAudit();
|
||||||
|
eraseEncryption();
|
||||||
|
}
|
||||||
|
erasePlaintext();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This function sends the ballot to the printer
|
||||||
|
*/
|
||||||
private void sendBallotToPrinterAndWaitToEnd () {
|
private void sendBallotToPrinterAndWaitToEnd () {
|
||||||
System.err.println("UI debug: sendBallotToPrinterAndWaitToEnd: still not multithreaded...");
|
logger.warn("UI debug: sendBallotToPrinterAndWaitToEnd: still not multithreaded...");
|
||||||
System.out.println("UI screen: printing ballot wait for printing to end");
|
System.out.println("UI screen: printing ballot wait for printing to end");
|
||||||
System.out.println("UI printer: printing ballot");
|
System.out.println("UI printer: printing ballot");
|
||||||
}
|
}
|
||||||
|
|
||||||
// returns true if cast or cancelled
|
/*
|
||||||
|
* This function sends the audit to the printer
|
||||||
|
*/
|
||||||
|
private void sendAuditToPrinterAndWaitToEnd () {
|
||||||
|
logger.warn("UI debug: sendAuditToPrinterAndWaitToEnd: still not multithreaded...");
|
||||||
|
System.out.println("UI printer: printing audit");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void showPrintingAuditScreen () {
|
||||||
|
System.out.println("UI screen: printing audit wait for printing to end");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* checks if the voter wants to cast the ballot or audit
|
||||||
|
* returns true if done with this ballot (cast or cancelled)
|
||||||
|
* returns false if still needs the current ballot info
|
||||||
|
*/
|
||||||
private boolean castOrAudit () throws IOException{
|
private boolean castOrAudit () throws IOException{
|
||||||
System.out.println("UI screen: (c)ast or (a)udit?");
|
System.out.println("UI screen: (c)ast or (a)udit?");
|
||||||
String choice = readInputLine();
|
String choice = readInputLine();
|
||||||
|
if (null == choice) {
|
||||||
|
logger.error("castOrAudit: got null as response");
|
||||||
|
throw new IOException();
|
||||||
|
}
|
||||||
if (choice.equals("a") || choice.equals("audit")) {
|
if (choice.equals("a") || choice.equals("audit")) {
|
||||||
System.err.println ("UI debug: voter decided to audit");
|
logger.debug ("UI debug: voter decided to audit");
|
||||||
System.out.println("UI screen: printing audit wait for printing to end");
|
showPrintingAuditScreen();
|
||||||
System.out.println("UI printer: printing audit");
|
sendAuditToPrinterAndWaitToEnd ();
|
||||||
|
|
||||||
|
if (!b_allowRecastOfAudittedBallot) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
System.out.println("Do you still want to keep this vote? Type 'y' for casting/auditing the same vote. Type 'n' tp start from scratch");
|
System.out.println("Do you still want to keep this vote? Type 'y' for casting/auditing the same vote. Type 'n' tp start from scratch");
|
||||||
String choice2 = readInputLine();
|
String choice2 = readInputLine();
|
||||||
|
if (null == choice2) {
|
||||||
|
logger.error("castOrAudit: got null as response");
|
||||||
|
throw new IOException ();
|
||||||
|
}
|
||||||
if (choice2.equals("y") || choice.equals("yes")) {
|
if (choice2.equals("y") || choice.equals("yes")) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -136,142 +291,75 @@ public class VotingBoothToyConsoleUI implements UI, Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private void eraseEncryption () {
|
|
||||||
//TODO: should we clean memory 'stronger'?
|
|
||||||
if (m_encryptedBallot != null) {
|
|
||||||
m_encryptedBallot = null;
|
|
||||||
}
|
|
||||||
if (m_ballotSecrets != null) {
|
|
||||||
m_ballotSecrets = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void erasePlaintext () {
|
|
||||||
//TODO: should we clean memory 'stronger'?
|
|
||||||
if (m_plaintextBallot != null) {
|
|
||||||
m_plaintextBallot = null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void printBallotFlow () throws IOException{
|
|
||||||
System.err.println("UI debug: printBallotFlow currently not multithreaded... will fix it...");
|
|
||||||
|
|
||||||
boolean ended = false;
|
|
||||||
while (!ended) {
|
|
||||||
sendBallotToControllerForEncryptionAndWaitForResponse ();
|
|
||||||
sendBallotToPrinterAndWaitToEnd();
|
|
||||||
ended = castOrAudit();
|
|
||||||
eraseEncryption();
|
|
||||||
}
|
|
||||||
erasePlaintext();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
|
||||||
* @see meerkat.voting.VotingBooth.UI#commitToEncryptedBallot(meerkat.voting.EncryptedBallot)
|
|
||||||
*/
|
|
||||||
@Override
|
|
||||||
public void commitToEncryptedBallot(EncryptedBallot encryptedBallot, BallotSecrets secrets) {
|
|
||||||
try {
|
|
||||||
a_queue.put (VBMessage.newControllerResponse(encryptedBallot, secrets));
|
|
||||||
}
|
|
||||||
catch (InterruptedException e) {
|
|
||||||
System.err.println ("Interrupted in VotingBoothToyConsoleUI.commitToEncryptedBallot");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void run () {
|
|
||||||
System.out.println("UI screen: Initializing the magic");
|
|
||||||
|
|
||||||
System.out.println("UI screen: press something to start the system");
|
|
||||||
readInputLine();
|
|
||||||
|
|
||||||
while (true) {
|
|
||||||
votingBegin();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public void registerVBController (VotingBooth vb)
|
|
||||||
{
|
|
||||||
m_vbController = vb;
|
|
||||||
//m_sharedPlaintext = sharedPlaintext;
|
|
||||||
//m_sharedEncrypted = sharedEncrypted;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* returns true if voting finished successfully
|
* returns true if voting finished successfully
|
||||||
* false if cancelled in the middle
|
* false if cancelled in the middle
|
||||||
*/
|
*/
|
||||||
private boolean listQuestionsToUserAndGetAnswers()
|
private boolean listQuestionsToUserAndGetAnswers() throws IOException {
|
||||||
{
|
Voting.PlaintextBallot.Builder ptbb = Voting.PlaintextBallot.newBuilder();
|
||||||
PlaintextBallot.Builder ptbb = PlaintextBallot.newBuilder();
|
|
||||||
|
|
||||||
ptbb.setSerialNumber(m_serialNumber);
|
ptbb.setSerialNumber(m_serialNumber);
|
||||||
|
|
||||||
|
Voting.BallotAnswer answers[] = new Voting.BallotAnswer[a_questions.length];
|
||||||
int index = 0;
|
int index = 0;
|
||||||
while (index < a_questions.length) {
|
while (index < a_questions.length) {
|
||||||
BallotQuestionNew q = a_questions[index];
|
Voting.BallotQuestionNew q = a_questions[index];
|
||||||
if (q.getIsMandatory()) {
|
if (q.getIsMandatory()) {
|
||||||
throw new UnsupportedOperationException("question " + index + " is marked as mandatory");
|
throw new UnsupportedOperationException("listQuestionsToUserAndGetAnswers: question " + index + " is marked as mandatory");
|
||||||
}
|
}
|
||||||
|
|
||||||
printQuestion(index, q);
|
showQuestionOnScreen(index, q);
|
||||||
System.out.println("UI screen: Enter your answer. You can also type 'back' or 'cancel'");
|
System.out.println("UI screen: Enter your answer. You can also type '(b)ack' or '(c)ancel' or '(s)kip");
|
||||||
String s = readInputLine();
|
String s = readInputLine();
|
||||||
|
if (null == s) {
|
||||||
|
logger.error("listQuestionsToUserAndGetAnswers: got null as response");
|
||||||
|
throw new IOException("");
|
||||||
|
}
|
||||||
|
|
||||||
if (s.equals("cancel") || (index == 0 && s.equals("back"))) {
|
if ((s.equals("cancel") || s.equals("c")) || (index == 0 && (s.equals("back") || s.equals("b")))) {
|
||||||
erasePlaintext();
|
erasePlaintext();
|
||||||
return false;
|
return false;
|
||||||
}
|
} else if (s.equals("back") || s.equals("b")) {
|
||||||
|
|
||||||
if (s.equals("back")) {
|
|
||||||
--index;
|
--index;
|
||||||
continue;
|
} else if (s.equals("skip") || s.equals("s")) {
|
||||||
}
|
answers[index] = translateStringAnswerToProtoBufMessageAnswer("");
|
||||||
|
|
||||||
if (s.equals("skip")) {
|
|
||||||
++index;
|
++index;
|
||||||
continue;
|
} else {
|
||||||
}
|
answers[index] = translateStringAnswerToProtoBufMessageAnswer(s);
|
||||||
|
++index;
|
||||||
BallotAnswer answer = translateStringAnswerToProtoBufMessageAnswer (s);
|
}
|
||||||
ptbb.setAnswers(index, answer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ptbb.addAllAnswers(Arrays.asList(answers));
|
||||||
m_plaintextBallot = ptbb.build();
|
m_plaintextBallot = ptbb.build();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String readInputLine () {
|
private Voting.BallotAnswer translateStringAnswerToProtoBufMessageAnswer(String s) {
|
||||||
String s;
|
Voting.BallotAnswer.Builder bab = Voting.BallotAnswer.newBuilder();
|
||||||
try {
|
StringTokenizer st = new StringTokenizer(s);
|
||||||
s = this.m_in.readLine();
|
while (st.hasMoreTokens()) {
|
||||||
}
|
bab.addAnswer(Integer.parseInt(st.nextToken()));
|
||||||
catch (IOException e) {
|
|
||||||
System.err.println("UI debug: VotingBegin(): some error with reading input. " + e);
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return s;
|
return bab.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
private void printQuestion (int i, BallotQuestionNew q) {
|
* show question on the screen for the voter
|
||||||
|
*/
|
||||||
|
private void showQuestionOnScreen(int i, Voting.BallotQuestionNew q) {
|
||||||
|
|
||||||
boolean isText = true;
|
boolean isText = true;
|
||||||
|
|
||||||
if (q.getQuestion().getType() != UIElementDataType.TEXT
|
if (q.getQuestion().getType() != Voting.UIElementDataType.TEXT
|
||||||
|| q.getDescription().getType() != UIElementDataType.TEXT) {
|
|| q.getDescription().getType() != Voting.UIElementDataType.TEXT) {
|
||||||
isText = false;
|
isText = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (UIElement answer : q.getAnswersList()) {
|
for (Voting.UIElement answer : q.getAnswerList()) {
|
||||||
if (answer.getType() != UIElementDataType.TEXT) {
|
if (answer.getType() != Voting.UIElementDataType.TEXT) {
|
||||||
isText = false;
|
isText = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -287,33 +375,40 @@ public class VotingBoothToyConsoleUI implements UI, Runnable {
|
||||||
System.out.println("Question text: " + bytesToString(q.getQuestion().getData()));
|
System.out.println("Question text: " + bytesToString(q.getQuestion().getData()));
|
||||||
System.out.println("Description: " + bytesToString(q.getDescription().getData()));
|
System.out.println("Description: " + bytesToString(q.getDescription().getData()));
|
||||||
int answerIndex = 0;
|
int answerIndex = 0;
|
||||||
for (UIElement answer : q.getAnswersList()) {
|
for (Voting.UIElement answer : q.getAnswerList()) {
|
||||||
++answerIndex;
|
++answerIndex;
|
||||||
System.out.println("Answer " + answerIndex + ": " + bytesToString(answer.getData()));
|
System.out.println("Answer " + answerIndex + ": " + bytesToString(answer.getData()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String bytesToString (ByteString data) {
|
/*
|
||||||
|
* Returns the UTF8 decoding of byte-string data
|
||||||
|
*/
|
||||||
|
private static String bytesToString(ByteString data) {
|
||||||
return data.toStringUtf8();
|
return data.toStringUtf8();
|
||||||
}
|
}
|
||||||
|
|
||||||
private BallotAnswer translateStringAnswerToProtoBufMessageAnswer (String s) {
|
|
||||||
BallotAnswer.Builder bab = BallotAnswer.newBuilder();
|
/*
|
||||||
StringTokenizer st = new StringTokenizer(s);
|
* Registering the controller, so we have an object to send encryption queries to
|
||||||
int index = 0;
|
*/
|
||||||
while (st.hasMoreTokens()) {
|
public void registerVBController(VotingBooth vb) {
|
||||||
++index;
|
m_vbController = vb;
|
||||||
bab.setAnswer(index, Integer.parseInt(st.nextToken()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
BallotAnswer ba = bab.build();
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void tick () {
|
/* (non-Javadoc)
|
||||||
// adds a 'tick'. If queue is full, do nothing
|
* @see meerkat.voting.VotingBooth.UI#commitToEncryptedBallot(meerkat.voting.EncryptedBallot)
|
||||||
a_queue.add (VBMessage.newTick());
|
*/
|
||||||
|
@Override
|
||||||
|
public void commitToEncryptedBallot(Voting.EncryptedBallot encryptedBallot, Voting.BallotSecrets secrets) {
|
||||||
|
try {
|
||||||
|
a_queue.put (VBMessage.newControllerResponse(encryptedBallot, secrets));
|
||||||
|
}
|
||||||
|
catch (InterruptedException e) {
|
||||||
|
System.err.println ("Interrupted in VotingBoothToyConsoleUI.commitToEncryptedBallot");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -339,7 +434,7 @@ public class VotingBoothToyConsoleUI implements UI, Runnable {
|
||||||
|
|
||||||
while (m_encryptedBallot == null)
|
while (m_encryptedBallot == null)
|
||||||
{
|
{
|
||||||
VBMessage msg = null;
|
VBMessage msg;
|
||||||
try {
|
try {
|
||||||
msg = a_queue.take();
|
msg = a_queue.take();
|
||||||
}
|
}
|
||||||
|
@ -359,9 +454,10 @@ public class VotingBoothToyConsoleUI implements UI, Runnable {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
System.out.println("\nUI debug: Received EncryptedBallot");
|
logger.debug("sendBallotToControllerForEncryptionAndWaitForResponse: Received EncryptedBallot");
|
||||||
timer.cancel();
|
timer.cancel();
|
||||||
timer.purge();
|
timer.purge();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,11 @@ import com.google.protobuf.ByteString;
|
||||||
import meerkat.protobuf.Crypto.SignatureType;
|
import meerkat.protobuf.Crypto.SignatureType;
|
||||||
import meerkat.protobuf.Crypto.SignatureVerificationKey;
|
import meerkat.protobuf.Crypto.SignatureVerificationKey;
|
||||||
import meerkat.protobuf.Voting.*;
|
import meerkat.protobuf.Voting.*;
|
||||||
|
import org.slf4j.Logger;
|
||||||
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class VotingBoothToyDemoRun {
|
public class VotingBoothToyDemoRun {
|
||||||
|
final static Logger logger = LoggerFactory.getLogger(VotingBoothToyDemoRun.class);
|
||||||
|
|
||||||
static int N_SIGNATURE_VERIFICATION_KEYS = 3;
|
static int N_SIGNATURE_VERIFICATION_KEYS = 3;
|
||||||
|
|
||||||
|
@ -15,16 +18,19 @@ public class VotingBoothToyDemoRun {
|
||||||
VotingBoothToy vbController = new VotingBoothToy ();
|
VotingBoothToy vbController = new VotingBoothToy ();
|
||||||
VotingBoothToyConsoleUI ui = new VotingBoothToyConsoleUI();
|
VotingBoothToyConsoleUI ui = new VotingBoothToyConsoleUI();
|
||||||
|
|
||||||
|
logger.debug("Running with {} args", args.length);
|
||||||
vbController.registerUI (ui);
|
vbController.registerUI (ui);
|
||||||
ui.registerVBController(vbController);
|
ui.registerVBController(vbController);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
BoothParams boothParams = generateDemoBoothParams();
|
BoothParams boothParams = generateDemoBoothParams();
|
||||||
ElectionParams electionParams = generateDemoElectionParams();
|
ElectionParams electionParams = generateDemoElectionParams();
|
||||||
|
|
||||||
vbController.init(electionParams, boothParams);
|
vbController.init(electionParams, boothParams);
|
||||||
|
ui.init(electionParams);
|
||||||
|
|
||||||
Thread controllerThread = new Thread(new VotingBoothToy ());
|
Thread controllerThread = new Thread(vbController);
|
||||||
Thread uiThread = new Thread(ui);
|
Thread uiThread = new Thread(ui);
|
||||||
|
|
||||||
controllerThread.start();
|
controllerThread.start();
|
||||||
|
@ -66,7 +72,7 @@ public class VotingBoothToyDemoRun {
|
||||||
.setType(UIElementDataType.TEXT)
|
.setType(UIElementDataType.TEXT)
|
||||||
.setData(stringToBytes(answerStr))
|
.setData(stringToBytes(answerStr))
|
||||||
.build();
|
.build();
|
||||||
bqb.addAnswers(answer);
|
bqb.addAnswer(answer);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bqb.build();
|
return bqb.build();
|
||||||
|
@ -90,9 +96,9 @@ public class VotingBoothToyDemoRun {
|
||||||
|
|
||||||
ElectionParams.Builder epb = ElectionParams.newBuilder();
|
ElectionParams.Builder epb = ElectionParams.newBuilder();
|
||||||
epb.setTrusteeSignatureThreshold(5);
|
epb.setTrusteeSignatureThreshold(5);
|
||||||
epb.setQuestions(0, question1);
|
epb.addQuestion(question1);
|
||||||
epb.setQuestions(1, question2);
|
epb.addQuestion(question2);
|
||||||
epb.setQuestions(2, question3);
|
epb.addQuestion(question3);
|
||||||
|
|
||||||
return epb.build();
|
return epb.build();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue