Commit c69b1507fa6737eeb3cd23d30a574a4020a6bd79

Authored by Dylan Clarke
1 parent 4c21d33718
Exists in master

add ballot generator

build.xml
... ... @@ -0,0 +1,27 @@
  1 +<?xml version="1.0" encoding="UTF-8"?>
  2 +
  3 +<project name="ClassroomVoting" default="jar" basedir=".">
  4 + <property name="jar.file" value="../../Classroom Voting/Jars/generator.jar"/>
  5 + <property name="main.class" value="uk.ac.ncl.ndjc9.newclassroomvoting.Driver"/>
  6 +
  7 + <target name ="cleanjar" depends = "clean,jar"/>
  8 +
  9 + <target name="jar">
  10 + <jar jarfile="${jar.file}" >
  11 + <fileset dir="bin"/>
  12 + <zipfileset includes="org/bouncycastle/asn1/**/*.class" src="../sharedlib/bcprov-jdk16-146.jar"/>
  13 + <zipfileset includes="org/bouncycastle/math/**/*.class" src="../sharedlib/bcprov-jdk16-146.jar"/>
  14 + <zipfileset includes="**/*.class" src="../sharedlib/commons-codec-1.5.jar"/>
  15 + <zipfileset includes="**/*.class" src="../sharedlib/javax.json-1.0.jar"/>
  16 + <manifest>
  17 + <attribute name="Main-Class" value = "${main.class}"/>
  18 + <attribute name="Class-Path" value="mysql-connector-java-5.1.15-bin.jar"/>
  19 + </manifest>
  20 + </jar>
  21 + </target>
  22 +
  23 + <target name ="clean">
  24 + <delete file="${jar.file}"/>
  25 + </target>
  26 +
  27 +</project>
0 28 \ No newline at end of file
... ...
manifest
... ... @@ -0,0 +1,3 @@
  1 +Manifest-Version: 1.0
  2 +Class-Path: mysql-connector-java-5.1.15-bin.jar commons-codec-1.5.jar
  3 +Main-Class: uk.ac.ncl.ndjc9.NewClassroomVoting.Generator
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/BallotDatabaseWrapper.java
... ... @@ -0,0 +1,12 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +import java.sql.SQLException;
  4 +
  5 +public interface BallotDatabaseWrapper
  6 +{
  7 +
  8 + public BallotParameters getParameters(int securityLevel) throws SQLException;
  9 + public void addValue(BallotEntry myBallot) throws SQLException;
  10 + public void commitValues() throws SQLException;
  11 +
  12 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/BallotEntry.java
... ... @@ -0,0 +1,61 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +public class BallotEntry
  4 +{
  5 + private int electionID;
  6 + private int questionID;
  7 + private int ballotNumber;
  8 + private int answerNumber;
  9 + private String publicKey;
  10 + private String restructuredKey;
  11 + private String yesValue;
  12 + private String noValue;
  13 + public BallotEntry(int electionID, int questionID, int ballotNumber,
  14 + int answerNumber, String publicKey, String restructuredKey,
  15 + String yesValue, String noValue)
  16 + {
  17 + super();
  18 + this.electionID = electionID;
  19 + this.questionID = questionID;
  20 + this.ballotNumber = ballotNumber;
  21 + this.answerNumber = answerNumber;
  22 + this.publicKey = publicKey;
  23 + this.restructuredKey = restructuredKey;
  24 + this.yesValue = yesValue;
  25 + this.noValue = noValue;
  26 + }
  27 + public int getElectionID()
  28 + {
  29 + return electionID;
  30 + }
  31 + public int getQuestionID()
  32 + {
  33 + return questionID;
  34 + }
  35 + public int getBallotNumber()
  36 + {
  37 + return ballotNumber;
  38 + }
  39 + public int getAnswerNumber()
  40 + {
  41 + return answerNumber;
  42 + }
  43 + public String getPublicKey()
  44 + {
  45 + return publicKey;
  46 + }
  47 + public String getRestructuredKey()
  48 + {
  49 + return restructuredKey;
  50 + }
  51 + public String getYesValue()
  52 + {
  53 + return yesValue;
  54 + }
  55 + public String getNoValue()
  56 + {
  57 + return noValue;
  58 + }
  59 +
  60 +
  61 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/BallotGenerator.java
... ... @@ -0,0 +1,262 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +import java.io.StringWriter;
  4 +import java.math.BigInteger;
  5 +import java.security.MessageDigest;
  6 +import java.security.SecureRandom;
  7 +import java.sql.SQLException;
  8 +import java.util.ArrayList;
  9 +import java.util.logging.Level;
  10 +import java.util.logging.Logger;
  11 +
  12 +import javax.json.Json;
  13 +import javax.json.JsonObject;
  14 +import javax.json.JsonWriter;
  15 +
  16 +import org.apache.commons.codec.binary.Base64;
  17 +import org.bouncycastle.math.ec.ECPoint;
  18 +
  19 +public class BallotGenerator implements Runnable
  20 +{
  21 +
  22 + private BallotParameters myParams;
  23 + private int electionID;
  24 + private int questionID;
  25 + private int answerNumber;
  26 + private int ballots;
  27 + private BallotDatabaseWrapper myWrapper;
  28 + private SecureRandom mySecureRand;
  29 +
  30 +
  31 +
  32 +
  33 + public BallotGenerator(BallotParameters myParams, int electionID,
  34 + int questionID, int answerNumber, int ballots,
  35 + BallotDatabaseWrapper myWrapper, SecureRandom mySecureRand)
  36 + {
  37 + super();
  38 + this.myParams = myParams;
  39 + this.electionID = electionID;
  40 + this.questionID = questionID;
  41 + this.answerNumber = answerNumber;
  42 + //currently allowing answer, election and question numbers to be less than 1
  43 + //as they are just identifiers and there's no logical reason to
  44 + //prevent them being less than 1, even though we don't use them
  45 + //that way at present
  46 +
  47 + //make sure that we're generating at least one ballot
  48 + if (ballots <1)
  49 + {
  50 + throw new IllegalArgumentException("Invalid number of ballots");
  51 +
  52 + }
  53 + this.ballots = ballots;
  54 + this.myWrapper = myWrapper;
  55 + this.mySecureRand = mySecureRand;
  56 + }
  57 +
  58 + public void run()
  59 + {
  60 + try
  61 + {
  62 + ArrayList<ECPoint> myPublicKeys = new ArrayList<ECPoint>();
  63 + ArrayList<BigInteger> myPrivateKeys = new ArrayList<BigInteger>();
  64 + ECPoint lastRestructuredKey = null;
  65 +
  66 + //loop through all ballots and generate private and public keys
  67 + for (int i=0; i<ballots; i++)
  68 + {
  69 + //generate a private key and public key for each ballot/candidate
  70 +
  71 + //private key - generate random number between 1 and order
  72 + BigInteger r;
  73 + do
  74 + {
  75 + r = BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand));
  76 + } while (r.compareTo(myParams.getOrder()) > 0);
  77 +
  78 + myPrivateKeys.add(r);
  79 +
  80 + //public key - private key multiplied by point
  81 + myPublicKeys.add(myParams.getMyPoint().multiply(r));
  82 +
  83 + }
  84 +
  85 + for (int i=0;i<ballots;i++)
  86 + {
  87 + //generate restructured key
  88 + ECPoint temp = myParams.getMyCurve().getInfinity();
  89 + if (i==0) //if it's the first ballot then do it the long way
  90 + {
  91 +
  92 + for (int k=1; k<ballots;k++)
  93 + {
  94 + temp = temp.subtract(myPublicKeys.get(k));
  95 + }
  96 + lastRestructuredKey = temp;
  97 + }
  98 + else //otherwise generate it from the preceding ballot
  99 + {
  100 + temp = myPublicKeys.get(i).add(myPublicKeys.get(i-1)).add(lastRestructuredKey);
  101 + lastRestructuredKey = temp;
  102 + }
  103 +
  104 +
  105 +
  106 + ECPoint noPoint = temp.multiply(myPrivateKeys.get(i));
  107 + ECPoint yesPoint = noPoint.add(myParams.getMyPoint());
  108 +
  109 + //generate random values for w,r2,d2
  110 + BigInteger w = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  111 + while(w.compareTo(myParams.getOrder()) > 0 )
  112 + {
  113 + w = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  114 + }
  115 + BigInteger rTwo = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  116 + while( rTwo.compareTo(myParams.getOrder()) > 0 )
  117 + {
  118 + rTwo = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  119 + }
  120 + BigInteger dTwo= (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  121 + while( dTwo.compareTo(myParams.getOrder()) > 0 )
  122 + {
  123 + dTwo = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  124 + }
  125 +
  126 +
  127 + //calculate a1,a2,b1,b2 values
  128 + ECPoint aOne=myParams.getMyPoint().multiply(w);
  129 + ECPoint bOne=temp.multiply(w);
  130 + ECPoint aTwo = myParams.getMyPoint().multiply(rTwo).add(myPublicKeys.get(i).multiply(dTwo));
  131 + ECPoint bTwo = temp.multiply(rTwo).add(noPoint.subtract(myParams.getMyPoint()).multiply(dTwo));
  132 + BigInteger c= BigInteger.ZERO;
  133 +
  134 + //generate hash and hence C value for no proof
  135 + String valueToHash = "32"+(i+1)+""+new BigInteger(myPublicKeys.get(i).getEncoded()).bitLength()+""+ElectionUtils.formatForElection(myPublicKeys.get(i))+new BigInteger(noPoint.getEncoded()).bitLength()+ElectionUtils.formatForElection(noPoint)+new BigInteger(aOne.getEncoded()).bitLength()+ ElectionUtils.formatForElection(aOne) + new BigInteger(bOne.getEncoded()).bitLength()+ElectionUtils.formatForElection(bOne);
  136 + valueToHash = valueToHash +new BigInteger(aTwo.getEncoded()).bitLength() + ElectionUtils.formatForElection(aTwo)+new BigInteger(bTwo.getEncoded()).bitLength()+ElectionUtils.formatForElection(bTwo);
  137 + c = generateHash(valueToHash);
  138 +
  139 + //calculate DOne and ROne
  140 + BigInteger dOne = c.subtract(dTwo).mod(myParams.getOrder());
  141 + BigInteger rOne = w.subtract(myPrivateKeys.get(i).multiply(dOne)).mod(myParams.getOrder());
  142 +
  143 +
  144 + // build up JSON object
  145 + JsonObject noValue = Json.createObjectBuilder()
  146 + .add("value", ElectionUtils.formatForElection(noPoint))
  147 + .add("proof", Json.createObjectBuilder()
  148 + .add("a1", ElectionUtils.formatForElection(aOne))
  149 + .add("a2", ElectionUtils.formatForElection(aTwo))
  150 + .add("b1", ElectionUtils.formatForElection(bOne))
  151 + .add("b2", ElectionUtils.formatForElection(bTwo))
  152 + .add("d1",Base64.encodeBase64String(dOne.toByteArray()))
  153 + .add("d2",Base64.encodeBase64String(dTwo.toByteArray()))
  154 + .add("r1",Base64.encodeBase64String(rOne.toByteArray()))
  155 + .add("r2",Base64.encodeBase64String(rTwo.toByteArray()))
  156 + .build()).build();
  157 +
  158 + //generate random values for w,r1,d1
  159 + w = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  160 + while(w.compareTo(myParams.getOrder()) > 0 )
  161 + {
  162 + w = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  163 + }
  164 +
  165 + rOne = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  166 + while( rOne.compareTo(myParams.getOrder()) > 0 )
  167 + {
  168 + rOne = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  169 + }
  170 +
  171 + dOne= (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  172 + while( dOne.compareTo(myParams.getOrder()) > 0 )
  173 + {
  174 + dOne = (BigInteger.ONE.add(new BigInteger(myParams.getOrder().bitLength(), mySecureRand)));
  175 + }
  176 +
  177 + //calculate a1,a2,b1,b2 values
  178 + aOne=myParams.getMyPoint().multiply(rOne).add(myPublicKeys.get(i).multiply(dOne));
  179 + bOne=(temp.multiply(rOne).add(yesPoint.multiply(dOne)));
  180 + aTwo=myParams.getMyPoint().multiply(w);
  181 + bTwo=temp.multiply(w);
  182 +
  183 + //generate hash and hence C value for yes proof
  184 + valueToHash = "32"+(i+1)+""+new BigInteger(myPublicKeys.get(i).getEncoded()).bitLength()+""+ElectionUtils.formatForElection(myPublicKeys.get(i))+new BigInteger(yesPoint.getEncoded()).bitLength()+ElectionUtils.formatForElection(yesPoint)+new BigInteger(aOne.getEncoded()).bitLength()+ ElectionUtils.formatForElection(aOne) + new BigInteger(bOne.getEncoded()).bitLength()+ElectionUtils.formatForElection(bOne);
  185 + valueToHash = valueToHash +new BigInteger(aTwo.getEncoded()).bitLength() + ElectionUtils.formatForElection(aTwo)+new BigInteger(bTwo.getEncoded()).bitLength()+ElectionUtils.formatForElection(bTwo);
  186 +
  187 +
  188 + c = generateHash(valueToHash);
  189 +
  190 + //generate DTwo and RTwo values
  191 + dTwo=c.subtract(dOne).mod(myParams.getOrder());
  192 + rTwo=w.subtract(myPrivateKeys.get(i).multiply(dTwo)).mod(myParams.getOrder());
  193 +
  194 + //build JSON object
  195 + JsonObject yesValue = Json.createObjectBuilder()
  196 + .add("value", ElectionUtils.formatForElection(yesPoint))
  197 + .add("proof", Json.createObjectBuilder()
  198 + .add("a1", ElectionUtils.formatForElection(aOne))
  199 + .add("a2", ElectionUtils.formatForElection(aTwo))
  200 + .add("b1", ElectionUtils.formatForElection(bOne))
  201 + .add("b2", ElectionUtils.formatForElection(bTwo))
  202 + .add("d1",Base64.encodeBase64String(dOne.toByteArray()))
  203 + .add("d2",Base64.encodeBase64String(dTwo.toByteArray()))
  204 + .add("r1",Base64.encodeBase64String(rOne.toByteArray()))
  205 + .add("r2",Base64.encodeBase64String(rTwo.toByteArray()))
  206 + .build()).build();
  207 +
  208 + //convert JSON object for yes ballot into string
  209 + StringWriter myWriter = new StringWriter();
  210 + JsonWriter jsonWriter = Json.createWriter(myWriter);
  211 + jsonWriter.write(yesValue);
  212 + jsonWriter.close();
  213 + String yesString = myWriter.getBuffer().toString();
  214 +
  215 + //convert JSON object for no ballot into string
  216 + myWriter = new StringWriter();
  217 + jsonWriter = Json.createWriter(myWriter);
  218 + jsonWriter.write(noValue);
  219 + jsonWriter.close();
  220 + String noString = myWriter.getBuffer().toString();
  221 +
  222 + //add entry for this ballot to database
  223 + BallotEntry myEntry = new BallotEntry(electionID,questionID,(i+1),answerNumber,ElectionUtils.formatForElection(myPublicKeys.get(i)),ElectionUtils.formatForElection(temp),yesString,noString);
  224 + myWrapper.addValue(myEntry);
  225 +
  226 +
  227 + }
  228 + myWrapper.commitValues();
  229 +
  230 +
  231 + }
  232 + catch (SQLException e)
  233 + {
  234 + System.out.println(e);
  235 + } catch (SecurityException e)
  236 + {
  237 + e.printStackTrace();
  238 + }
  239 +
  240 +
  241 + }
  242 +
  243 + private BigInteger generateHash(String valueToHash)
  244 + {
  245 + try
  246 + {
  247 + MessageDigest md = MessageDigest.getInstance("SHA-512");
  248 + //generate hash string using the relevant values with their bitlength pre-appended
  249 +
  250 + //hash the hash string and return;
  251 + byte[] tempArray = valueToHash.getBytes();
  252 + tempArray = md.digest(tempArray);
  253 + return new BigInteger(tempArray);
  254 + }
  255 + catch (Exception e)
  256 + {
  257 + String logEntry = e.toString();
  258 + Logger.getLogger("").log(Level.SEVERE,logEntry);
  259 + }
  260 + return BigInteger.ZERO;
  261 + }
  262 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/BallotParameters.java
... ... @@ -0,0 +1,45 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +import java.math.BigInteger;
  4 +
  5 +import org.bouncycastle.math.ec.ECCurve;
  6 +import org.bouncycastle.math.ec.ECPoint;
  7 +
  8 +public class BallotParameters
  9 +{
  10 + private BigInteger primeModulus;
  11 + private BigInteger order;
  12 + private ECPoint myPoint;
  13 + private ECCurve myCurve;
  14 + public BigInteger getPrimeModulus()
  15 + {
  16 + return primeModulus;
  17 + }
  18 +
  19 + public BigInteger getOrder()
  20 + {
  21 + return order;
  22 + }
  23 +
  24 +
  25 + public ECPoint getMyPoint()
  26 + {
  27 + return myPoint;
  28 + }
  29 +
  30 + public ECCurve getMyCurve()
  31 + {
  32 + return myCurve;
  33 + }
  34 +
  35 + public BallotParameters(BigInteger primeModulus, BigInteger order, ECPoint myPoint,ECCurve myCurve)
  36 + {
  37 + super();
  38 + this.primeModulus = primeModulus;
  39 + this.order = order;
  40 + this.myPoint = myPoint;
  41 + this.myCurve = myCurve;
  42 + }
  43 +
  44 +
  45 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/Driver.java
... ... @@ -0,0 +1,172 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +
  4 +import java.io.FileInputStream;
  5 +import java.io.IOException;
  6 +import java.io.PrintWriter;
  7 +import java.math.BigInteger;
  8 +import java.net.ServerSocket;
  9 +import java.net.Socket;
  10 +import java.security.MessageDigest;
  11 +import java.security.SecureRandom;
  12 +import java.sql.Connection;
  13 +import java.sql.DriverManager;
  14 +import java.sql.PreparedStatement;
  15 +import java.sql.ResultSet;
  16 +import java.sql.SQLException;
  17 +import java.util.ArrayList;
  18 +import java.util.Date;
  19 +import java.util.Properties;
  20 +import java.util.Scanner;
  21 +import java.util.logging.FileHandler;
  22 +import java.util.logging.Level;
  23 +import java.util.logging.Logger;
  24 +import java.util.logging.Handler;
  25 +import java.io.StringWriter;
  26 +
  27 +
  28 +import javax.json.*;
  29 +
  30 +import org.apache.commons.codec.binary.Base64;
  31 +import org.bouncycastle.math.ec.ECCurve;
  32 +import org.bouncycastle.math.ec.ECPoint;
  33 +
  34 +
  35 +import java.util.concurrent.ExecutorService;
  36 +import java.util.concurrent.Executors;
  37 +
  38 +public class Driver
  39 +{
  40 + static Driver myGenerator;
  41 + static String url;
  42 + static String password;
  43 + static String userName;
  44 + static String workingDir;
  45 + static SecureRandom mySecureRand;
  46 +
  47 + private static Handler handler;
  48 +
  49 +
  50 + public static final int MAX_THREADS = Runtime.getRuntime().availableProcessors();
  51 +
  52 + //We use two executorservices as we have two types of thread
  53 + //Each type (ballot generation and election generation)
  54 + //must be queued separately
  55 + //Ballot generation is slow and doesn't need to happen
  56 + //instantly. Election generation is quick and ideally
  57 + //will happen very quickly.
  58 + private static ExecutorService executorService;
  59 +
  60 + public static void main (String args[]) throws IOException
  61 + {
  62 + executorService = Executors.newFixedThreadPool(MAX_THREADS);
  63 + mySecureRand = new SecureRandom();
  64 + String propertiesDirectory = "";
  65 + if (args.length > 0)
  66 + {
  67 + propertiesDirectory = args[0];
  68 + }
  69 + //open a socket on port 4449
  70 +
  71 + ServerSocket serverSocket = null;
  72 + try
  73 + {
  74 + serverSocket = new ServerSocket(4449);
  75 + //get database connection parameters from properties file and make available to other methods
  76 + Properties prop = new Properties();
  77 + prop.load(new FileInputStream(propertiesDirectory+"classroom.properties"));
  78 + url = prop.getProperty("protocol") + "://" + prop.getProperty("baseurl") + "/" + prop.getProperty("database");
  79 + userName = prop.getProperty("username");
  80 + password = prop.getProperty("password");
  81 + workingDir = prop.getProperty("workingdir");
  82 + handler = new FileHandler(workingDir+"ballotgen.log", 16000, 20);
  83 + Logger.getLogger("").addHandler(handler);
  84 + Logger.getLogger("").log(Level.INFO,"Started-new");
  85 +
  86 + }
  87 + catch (IOException e)
  88 + {
  89 + System.err.println(e);
  90 + System.exit(1);
  91 + }
  92 +
  93 + Socket clientSocket = null;
  94 + boolean finish = false;
  95 +
  96 + //keep receiving requests until stopped
  97 + while (!finish)
  98 + {
  99 + //use a client socket to get the incoming request
  100 + clientSocket = serverSocket.accept();
  101 + try
  102 + {
  103 + PrintWriter out = new PrintWriter(clientSocket.getOutputStream(), true);
  104 +
  105 + try
  106 + {
  107 + //get data from clientSocket
  108 + Scanner myScanner = new Scanner(clientSocket.getInputStream());
  109 +
  110 + //extract JSON object document
  111 + JsonObject doc = ElectionUtils.getDocument(myScanner);
  112 +
  113 +
  114 +
  115 + Connection conn = null;
  116 + Class.forName ("com.mysql.jdbc.Driver").newInstance ();
  117 + conn = DriverManager.getConnection (Driver.url, Driver.userName, Driver.password);
  118 + conn.setAutoCommit(false);
  119 +
  120 +
  121 +
  122 + int electionID = doc.getInt("electionID");
  123 + int questionID = doc.getInt("questionID");
  124 + int answerNumber = doc.getInt("answerNumber");
  125 + int ballots = doc.getInt("ballots");
  126 + int securityLevel = doc.getInt("securitylevel");
  127 +
  128 + PreparedStatement stmt;
  129 + stmt = conn.prepareStatement("INSERT INTO ballotJSON (electionID,questionID,ballotNumber,answerNumber,publicKey,restructuredKey,yesValue,noValue) VALUES (?,?,?,?,?,?,?,?)");
  130 +
  131 +
  132 + BallotDatabaseWrapper myDatabaseWrapper = new SQLDatabaseWrapper(conn,stmt);
  133 +
  134 + BallotParameters myParams = myDatabaseWrapper.getParameters(securityLevel);
  135 +
  136 + //respond to generator page
  137 + out.println("HTTP/1.1 200 OK\r\nDate:"+new Date().toString()+"\r\nServer:Apache\r\nKeep-Alive: timeout=5, max=99\r\nConnection: Keep-Alive\r\nContent-Type: text/html\r\n\r\n"+electionID);
  138 +
  139 + out.close();
  140 + executorService.submit(new BallotGenerator(myParams,electionID,questionID,answerNumber,ballots,myDatabaseWrapper,mySecureRand));
  141 +
  142 + }
  143 + catch (Exception e)
  144 + {
  145 + String logEntry = e.toString();
  146 + Logger.getLogger("").log(Level.SEVERE,logEntry);
  147 + }
  148 +
  149 +
  150 + clientSocket.close();
  151 + }catch(IOException ioe)
  152 + {
  153 + System.out.println("Error closing client connection");
  154 + }
  155 +
  156 +
  157 + }
  158 + serverSocket.close();
  159 + executorService.shutdown();
  160 +
  161 + }
  162 +
  163 +
  164 +
  165 +
  166 +
  167 +
  168 +
  169 +}
  170 +
  171 +
  172 +
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/ElectionUtils.java
... ... @@ -0,0 +1,43 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +
  4 +
  5 +
  6 +
  7 +
  8 +import org.bouncycastle.math.ec.ECPoint;
  9 +
  10 +import java.util.Scanner;
  11 +import java.io.StringReader;
  12 +
  13 +import javax.json.*;
  14 +
  15 +import org.apache.commons.codec.binary.Base64;
  16 +
  17 +public class ElectionUtils
  18 +{
  19 + //returns the value of a point formated for inclusion in the election database
  20 + public static String formatForElection(ECPoint myPoint)
  21 + {
  22 + String temp = Base64.encodeBase64String(myPoint.getEncoded());
  23 + temp = (temp.indexOf("=")>-1?temp.substring(0,temp.indexOf("=")):temp);
  24 + return temp;
  25 + }
  26 +
  27 +
  28 + //takes a scanner that can access the clientsocket and returns a JSON document
  29 + public static JsonObject getDocument(Scanner myScanner)
  30 + {
  31 +
  32 +
  33 + String jsonString = myScanner.nextLine();
  34 + //throw away the bit of http request that isn't JSON
  35 + jsonString = jsonString.substring(0,jsonString.length()-11);
  36 + JsonReader myReader = Json.createReader(new StringReader(jsonString));
  37 + JsonObject myJsonObject = myReader.readObject();
  38 +
  39 + return myJsonObject;
  40 + }
  41 +
  42 +
  43 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/SQLDatabaseWrapper.java
... ... @@ -0,0 +1,70 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +import java.math.BigInteger;
  4 +import java.sql.Connection;
  5 +import java.sql.PreparedStatement;
  6 +import java.sql.ResultSet;
  7 +import java.sql.SQLException;
  8 +
  9 +import org.bouncycastle.math.ec.ECCurve;
  10 +import org.bouncycastle.math.ec.ECPoint;
  11 +
  12 +public class SQLDatabaseWrapper implements BallotDatabaseWrapper
  13 +{
  14 + private Connection conn;
  15 + private PreparedStatement stmt;
  16 +
  17 + public SQLDatabaseWrapper(Connection conn, PreparedStatement stmt)
  18 + {
  19 + super();
  20 + this.conn = conn;
  21 + this.stmt = stmt;
  22 + }
  23 +
  24 + @Override
  25 + public BallotParameters getParameters(int securityLevel) throws SQLException
  26 + {
  27 + PreparedStatement stmt;
  28 +
  29 + stmt = conn.prepareStatement("SELECT paraA,paraB,primeModulus,pointX,pointY,pointOrder FROM ECParameters WHERE securityLevel = ?");
  30 + stmt.setInt(1,securityLevel);
  31 + ResultSet rs = stmt.executeQuery();
  32 + rs.next();
  33 +
  34 + BigInteger primeModulus = new BigInteger(rs.getString(3),16);
  35 + BigInteger order = new BigInteger(rs.getString(6),16);
  36 + ECCurve myCurve = new ECCurve.Fp(primeModulus,new BigInteger(rs.getString(1),16),new BigInteger(rs.getString(2),16));
  37 +
  38 + ECPoint myPoint = myCurve.createPoint(new BigInteger(rs.getString(4),16),new BigInteger(rs.getString(5),16),false);
  39 + BallotParameters myParams = new BallotParameters(primeModulus,order,myPoint,myCurve);
  40 + return myParams;
  41 + }
  42 +
  43 + @Override
  44 + public void addValue(BallotEntry myBallot) throws SQLException
  45 + {
  46 + // TODO Auto-generated method stub
  47 + stmt.setInt(1,myBallot.getElectionID());
  48 + stmt.setInt(2,myBallot.getQuestionID());
  49 + stmt.setInt(3,myBallot.getBallotNumber());
  50 + stmt.setInt(4,myBallot.getAnswerNumber());
  51 + stmt.setString(5,myBallot.getPublicKey());
  52 + stmt.setString(6,myBallot.getRestructuredKey());
  53 + stmt.setString(7,myBallot.getYesValue());
  54 + stmt.setString(8,myBallot.getNoValue());
  55 +
  56 + stmt.addBatch();
  57 +
  58 + }
  59 +
  60 + @Override
  61 + public void commitValues() throws SQLException
  62 + {
  63 + //commit values to database
  64 + stmt.executeBatch();
  65 + conn.commit();
  66 + conn.close();
  67 +
  68 + }
  69 +
  70 +}
... ...
src/uk/ac/ncl/ndjc9/newclassroomvoting/TestBallotGenerator.java
... ... @@ -0,0 +1,452 @@
  1 +package uk.ac.ncl.ndjc9.newclassroomvoting;
  2 +
  3 +import static org.junit.Assert.*;
  4 +
  5 +import java.io.FileReader;
  6 +import java.io.StringReader;
  7 +import java.math.BigInteger;
  8 +import java.security.MessageDigest;
  9 +import java.security.SecureRandom;
  10 +
  11 +import javax.json.Json;
  12 +import javax.json.JsonObject;
  13 +import javax.json.JsonReader;
  14 +
  15 +import org.apache.commons.codec.binary.Base64;
  16 +import org.bouncycastle.math.ec.ECPoint;
  17 +import org.junit.Assert;
  18 +import org.junit.Test;
  19 +
  20 +
  21 +public class TestBallotGenerator
  22 +{
  23 +
  24 + @Test(expected=IllegalArgumentException.class)
  25 + //test that we get an exception when
  26 + //we give an invalid number of ballots
  27 + public void testInvalidNumberOfBallots()
  28 + {
  29 + SecureRandom mySecureRand = new SecureRandom();
  30 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  31 + //security level is irrelevant for the TestDatabaseWrapper
  32 + try
  33 + {
  34 + BallotParameters myParams = myWrapper.getParameters(1);
  35 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,0,myWrapper,mySecureRand);
  36 +
  37 + }
  38 + catch (IllegalArgumentException e)
  39 + {
  40 + throw e;
  41 +
  42 + }
  43 + catch (Exception e)
  44 + {
  45 + fail("wrong exception thrown");
  46 +
  47 + }
  48 +
  49 + }
  50 +
  51 + @Test
  52 + //test that the correct number of ballots are generated
  53 + public void testNumberOfBallots()
  54 + {
  55 + SecureRandom mySecureRand = new SecureRandom();
  56 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  57 + //security level is irrelevant for the TestDatabaseWrapper
  58 + try
  59 + {
  60 + BallotParameters myParams = myWrapper.getParameters(1);
  61 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,3,myWrapper,mySecureRand);
  62 + //do this rather than use a separate thread as we're just testing the code linearly
  63 + myBallotGenerator.run();
  64 +
  65 + Assert.assertTrue(myWrapper.getMyBallotEntries().size() == 3);
  66 +
  67 +
  68 + }
  69 + catch (Exception e)
  70 + {
  71 + fail("exception thrown");
  72 +
  73 + }
  74 +
  75 + }
  76 +
  77 + @Test
  78 + //test that the correct election ID is used
  79 + public void testElectionID()
  80 + {
  81 + SecureRandom mySecureRand = new SecureRandom();
  82 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  83 + //security level is irrelevant for the TestDatabaseWrapper
  84 + try
  85 + {
  86 + BallotParameters myParams = myWrapper.getParameters(1);
  87 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,3,1,1,1,myWrapper,mySecureRand);
  88 + //do this rather than use a separate thread as we're just testing the code linearly
  89 + myBallotGenerator.run();
  90 +
  91 + Assert.assertTrue(myWrapper.getMyBallotEntries().get(0).getElectionID() == 3);
  92 +
  93 + }
  94 + catch (Exception e)
  95 + {
  96 + fail("exception thrown");
  97 +
  98 + }
  99 +
  100 + }
  101 +
  102 + @Test
  103 + //test that the correct question ID is used
  104 + public void testQuestionID()
  105 + {
  106 + SecureRandom mySecureRand = new SecureRandom();
  107 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  108 + //security level is irrelevant for the TestDatabaseWrapper
  109 + try
  110 + {
  111 + BallotParameters myParams = myWrapper.getParameters(1);
  112 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,3,1,1,myWrapper,mySecureRand);
  113 + //do this rather than use a separate thread as we're just testing the code linearly
  114 + myBallotGenerator.run();
  115 +
  116 + Assert.assertTrue(myWrapper.getMyBallotEntries().get(0).getQuestionID() == 3);
  117 +
  118 +
  119 + }
  120 + catch (Exception e)
  121 + {
  122 + fail("exception thrown");
  123 +
  124 + }
  125 +
  126 + }
  127 +
  128 + @Test
  129 + //test that the correct answer number is used
  130 + public void testAnswerNumber()
  131 + {
  132 + SecureRandom mySecureRand = new SecureRandom();
  133 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  134 + //security level is irrelevant for the TestDatabaseWrapper
  135 + try
  136 + {
  137 + BallotParameters myParams = myWrapper.getParameters(1);
  138 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,3,1,myWrapper,mySecureRand);
  139 + //do this rather than use a separate thread as we're just testing the code linearly
  140 + myBallotGenerator.run();
  141 +
  142 + Assert.assertTrue(myWrapper.getMyBallotEntries().get(0).getAnswerNumber() == 3);
  143 +
  144 +
  145 + }
  146 + catch (Exception e)
  147 + {
  148 + fail("exception thrown");
  149 +
  150 + }
  151 +
  152 + }
  153 +
  154 + @Test
  155 + //test that the correct ballot numbers are used
  156 + public void testBallotNumbers()
  157 + {
  158 + SecureRandom mySecureRand = new SecureRandom();
  159 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  160 + //security level is irrelevant for the TestDatabaseWrapper
  161 + try
  162 + {
  163 + BallotParameters myParams = myWrapper.getParameters(1);
  164 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,3,myWrapper,mySecureRand);
  165 + //do this rather than use a separate thread as we're just testing the code linearly
  166 + myBallotGenerator.run();
  167 +
  168 + for (int i=0; i<3;i++)
  169 + {
  170 + Assert.assertTrue(myWrapper.getMyBallotEntries().get(i).getBallotNumber() == (i+1));
  171 + }
  172 +
  173 + }
  174 + catch (Exception e)
  175 + {
  176 + fail("exception thrown");
  177 +
  178 + }
  179 +
  180 + }
  181 +
  182 +
  183 + @Test
  184 + //test that the correct relationship exists between yes and no ballots
  185 + public void testYesNoRelationship()
  186 + {
  187 + SecureRandom mySecureRand = new SecureRandom();
  188 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  189 + //security level is irrelevant for the TestDatabaseWrapper
  190 + try
  191 + {
  192 + BallotParameters myParams = myWrapper.getParameters(1);
  193 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,1,myWrapper,mySecureRand);
  194 + //do this rather than use a separate thread as we're just testing the code linearly
  195 + myBallotGenerator.run();
  196 +
  197 + BallotEntry myEntry = myWrapper.getMyBallotEntries().get(0);
  198 +
  199 + //get yes value
  200 + JsonReader myReader = Json.createReader(new StringReader(myEntry.getYesValue()));
  201 + JsonObject myJsonObject = myReader.readObject();
  202 + ECPoint yesValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  203 +
  204 + //get no value
  205 + myReader = Json.createReader(new StringReader(myEntry.getNoValue()));
  206 + myJsonObject = myReader.readObject();
  207 + ECPoint noValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  208 +
  209 + //test relationship
  210 + Assert.assertTrue(yesValue.equals(noValue.add(myParams.getMyPoint())));
  211 +
  212 + }
  213 + catch (Exception e)
  214 + {
  215 + fail("exception thrown");
  216 +
  217 + }
  218 +
  219 + }
  220 +
  221 +
  222 + @Test
  223 + //test that adding a set of no ballots does give the value corresponding to no votes cast
  224 + public void testNoValueAddition()
  225 + {
  226 + SecureRandom mySecureRand = new SecureRandom();
  227 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  228 + //security level is irrelevant for the TestDatabaseWrapper
  229 + try
  230 + {
  231 + BallotParameters myParams = myWrapper.getParameters(1);
  232 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,3,myWrapper,mySecureRand);
  233 + //do this rather than use a separate thread as we're just testing the code linearly
  234 + myBallotGenerator.run();
  235 +
  236 + ECPoint sum = myParams.getMyCurve().getInfinity();
  237 + for (int i=0;i<3;i++)
  238 + {
  239 + BallotEntry myEntry = myWrapper.getMyBallotEntries().get(i);
  240 +
  241 + //get no value
  242 + JsonReader myReader = Json.createReader(new StringReader(myEntry.getNoValue()));
  243 + JsonObject myJsonObject = myReader.readObject();
  244 + ECPoint noValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  245 + //add to sum
  246 + sum = sum.add(noValue);
  247 + }
  248 +
  249 + //test sum is equal to point at infinity
  250 + Assert.assertTrue(sum.equals(myParams.getMyCurve().getInfinity()));
  251 +
  252 + }
  253 + catch (Exception e)
  254 + {
  255 + fail("exception thrown");
  256 +
  257 + }
  258 +
  259 + }
  260 +
  261 +
  262 + @Test
  263 + //test that adding a set of yes ballots does give the value corresponding to all votes cast for yes
  264 + public void testYesValueAddition()
  265 + {
  266 + SecureRandom mySecureRand = new SecureRandom();
  267 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  268 + //security level is irrelevant for the TestDatabaseWrapper
  269 + try
  270 + {
  271 + BallotParameters myParams = myWrapper.getParameters(1);
  272 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,3,myWrapper,mySecureRand);
  273 + //do this rather than use a separate thread as we're just testing the code linearly
  274 + myBallotGenerator.run();
  275 +
  276 + ECPoint sum = myParams.getMyCurve().getInfinity();
  277 + for (int i=0;i<3;i++)
  278 + {
  279 + BallotEntry myEntry = myWrapper.getMyBallotEntries().get(i);
  280 +
  281 + //get yes value
  282 + JsonReader myReader = Json.createReader(new StringReader(myEntry.getYesValue()));
  283 + JsonObject myJsonObject = myReader.readObject();
  284 + ECPoint yesValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  285 + //add to sum
  286 + sum = sum.add(yesValue);
  287 + }
  288 +
  289 + //test sum is equal myPoint * 3
  290 + Assert.assertTrue(sum.equals(myParams.getMyPoint().multiply(new BigInteger("3"))));
  291 +
  292 + }
  293 + catch (Exception e)
  294 + {
  295 + fail("exception thrown");
  296 +
  297 + }
  298 +
  299 + }
  300 +
  301 + @Test
  302 + //test that casting one yes ballot and all the other no ballots does give the value corresponding to
  303 + //one yes vote cast
  304 + public void testMixedAddition()
  305 + {
  306 + SecureRandom mySecureRand = new SecureRandom();
  307 + TestDatabaseWrapper myWrapper = new TestDatabaseWrapper();
  308 + //security level is irrelevant for the TestDatabaseWrapper
  309 + try
  310 + {
  311 + BallotParameters myParams = myWrapper.getParameters(1);
  312 + BallotGenerator myBallotGenerator = new BallotGenerator(myParams,1,1,1,3,myWrapper,mySecureRand);
  313 + //do this rather than use a separate thread as we're just testing the code linearly
  314 + myBallotGenerator.run();
  315 +
  316 + ECPoint sum = myParams.getMyCurve().getInfinity();
  317 + for (int i=0;i<2;i++)
  318 + {
  319 + BallotEntry myEntry = myWrapper.getMyBallotEntries().get(i);
  320 +
  321 + //get no value
  322 + JsonReader myReader = Json.createReader(new StringReader(myEntry.getNoValue()));
  323 + JsonObject myJsonObject = myReader.readObject();
  324 + ECPoint noValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  325 + //add to sum
  326 + sum = sum.add(noValue);
  327 + }
  328 +
  329 + BallotEntry myEntry = myWrapper.getMyBallotEntries().get(2);
  330 + JsonReader myReader = Json.createReader(new StringReader(myEntry.getYesValue()));
  331 + JsonObject myJsonObject = myReader.readObject();
  332 + ECPoint yesValue = myParams.getMyCurve().decodePoint(Base64.decodeBase64(myJsonObject.getString("value")));
  333 + //add to sum
  334 + sum = sum.add(yesValue);
  335 +
  336 +