Going home
This commit is contained in:
parent
77508479b4
commit
89533a54b1
9 changed files with 256 additions and 151 deletions
|
@ -208,6 +208,11 @@ class Ballot(models.Model):
|
|||
cast = models.BooleanField(default=False)
|
||||
|
||||
|
||||
class EncBallot(models.Model):
|
||||
handle = models.CharField(primary_key=True, default=uuid.uuid4, editable=False, max_length=255)
|
||||
ballot = models.CharField(max_length=4096)
|
||||
|
||||
|
||||
# Implements the new binary encoding scheme
|
||||
class EncryptedVote(models.Model):
|
||||
ballot = models.ForeignKey(Ballot, on_delete=models.CASCADE, related_name="encrypted_vote")
|
||||
|
|
|
@ -20,5 +20,6 @@ urlpatterns = [
|
|||
url(r'^(?P<event_id>[0-9a-f-]+)/prepare/$', views.event_trustee_setup, name='prepare-event'),
|
||||
url(r'^(?P<event_id>[0-9a-f-]+)/poll/(?P<poll_id>[0-9a-f-]+)/vote/$', views.event_vote, name='event-vote'),
|
||||
url(r'^(?P<event_id>[0-9a-f-]+)/create/poll/$', login_required(views.manage_questions), name='create-poll'),
|
||||
url(r'^(?P<event_id>[0-9a-f-]+)/poll/(?P<poll_id>[0-9a-f-]+)/edit$', login_required(views.edit_poll), name='edit-poll')
|
||||
url(r'^(?P<event_id>[0-9a-f-]+)/poll/(?P<poll_id>[0-9a-f-]+)/edit$', login_required(views.edit_poll), name='edit-poll'),
|
||||
url(r'^audit/$', views.vote_audit, name='vote_audit')
|
||||
]
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
import urllib
|
||||
import urllib2
|
||||
import json
|
||||
import logging
|
||||
import base64
|
||||
|
||||
from django.contrib import messages
|
||||
from django.http import HttpResponseRedirect, HttpResponse, Http404
|
||||
|
@ -11,7 +13,7 @@ from django.views import generic
|
|||
from django.conf import settings
|
||||
|
||||
from .forms import PollForm, OptionFormset, VoteForm, EventSetupForm, EventEditForm
|
||||
from .models import Event, Poll, Ballot, EncryptedVote, TrusteeKey, PartialBallotDecryption, CombinedBallot, VoteFragment
|
||||
from .models import Event, Poll, Ballot, EncBallot, EncryptedVote, TrusteeKey, PartialBallotDecryption, CombinedBallot, VoteFragment
|
||||
from allauthdemo.auth.models import DemoUser
|
||||
|
||||
from .tasks import email_trustees_prep, update_EID, generate_combpk, event_ended, create_ballots
|
||||
|
@ -110,6 +112,15 @@ def edit_poll(request, event_id, poll_id):
|
|||
return HttpResponseRedirect(reverse('polls:event-polls', args=[poll.event_id]))
|
||||
|
||||
|
||||
def vote_audit(request):
|
||||
encryptedBallot = get_object_or_404(EncBallot, handle=''+urllib.quote_plus(request.GET.get('handle', None)))
|
||||
|
||||
return render(request, "polls/vote_audit.html",
|
||||
{
|
||||
"ballot": encryptedBallot.ballot
|
||||
})
|
||||
|
||||
|
||||
def event_vote(request, event_id, poll_id):
|
||||
event = get_object_or_404(Event, pk=event_id)
|
||||
|
||||
|
@ -172,10 +183,21 @@ def event_vote(request, event_id, poll_id):
|
|||
cant_vote_reason = "The event either isn't ready for voting or it has expired and therefore you cannot vote."
|
||||
|
||||
if request.method == "POST":
|
||||
data = json.loads(request.POST.lists()[0][0])
|
||||
ballot_json = data['ballot']
|
||||
ballot_json = json.loads(request.POST.get('ballot'))
|
||||
encrypted_votes_json = ballot_json['encryptedVotes']
|
||||
|
||||
enc_ballot_json = request.POST.get('encBallot')
|
||||
handle_json = request.POST.get('handle')
|
||||
|
||||
# Adds or replaces the encrypted un-submitted ballot to the database for the auditor app to pick up later
|
||||
if EncBallot.objects.filter(handle=handle_json).exists():
|
||||
b = EncBallot.objects.get(handle=handle_json)
|
||||
b.ballot = ballot_json
|
||||
b.save()
|
||||
else:
|
||||
b = EncBallot(handle=handle_json, ballot=enc_ballot_json)
|
||||
b.save()
|
||||
|
||||
# Before storing the encrypted votes, we need the voter's ballot
|
||||
ballot, created = Ballot.objects.get_or_create(voter=email_key[0].user, poll=poll)
|
||||
EncryptedVote.objects.filter(ballot=ballot).delete()
|
||||
|
|
|
@ -11,16 +11,16 @@
|
|||
<script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/js/bootstrap.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.10.6/moment.min.js"></script>
|
||||
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.17.37/js/bootstrap-datetimepicker.min.js"></script>
|
||||
<script src="https://bitwiseshiftleft.github.io/sjcl/sjcl.js"></script>
|
||||
<script src='https://www.google.com/recaptcha/api.js'></script>
|
||||
<script
|
||||
src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js"
|
||||
integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU="
|
||||
crossorigin="anonymous"></script>
|
||||
<script src="https://code.jquery.com/ui/1.12.1/jquery-ui.min.js" integrity="sha256-VazP97ZCwtekAsvgPBSUwPFKdrwD3unUfSGVYrahUqU=" crossorigin="anonymous"></script>
|
||||
|
||||
<script src="{% static 'js/papaparse.min.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/qrcode.min.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/create-event-poll.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/decrypt_event.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/event_vote.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/vote_audit.js' %}" type="text/javascript"></script>
|
||||
<script src="{% static 'js/encrypt.js' %}" type="text/javascript"></script>
|
||||
|
||||
<script type="text/javascript" src="{% static 'js/core/rand.js' %}"></script>
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
</span>
|
||||
|
||||
<!-- Poll Voting Section -->
|
||||
<p id="poll-num" hidden>{{ poll_num}}</p>
|
||||
<h3>Poll {{ poll_num }} of {{ poll_count }}: {{object.question_text}}</h3>
|
||||
<hr/>
|
||||
|
||||
|
@ -124,7 +125,7 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
<button id="close-button" type="button" class="btn btn-danger" data-dismiss="modal">Close without submitting vote</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
18
allauthdemo/templates/polls/vote_audit.html
Normal file
18
allauthdemo/templates/polls/vote_audit.html
Normal file
|
@ -0,0 +1,18 @@
|
|||
{% extends "bases/bootstrap-with-nav.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<input id="SK" value="temporary" type="text"/>
|
||||
<button id="begin-test">Verify Ballot</button>
|
||||
<br>
|
||||
<br>
|
||||
<label for="ballot">AES-encrypted ballot from server</label>
|
||||
<pre id="ballot">{{ ballot }}</pre>
|
||||
<label for="ballot-content">Decrypted ballot</label>
|
||||
<pre id="ballot-content"></pre>
|
||||
<label for="ballot">Ballot encoding</label>
|
||||
<pre id="ballot-result"></pre>
|
||||
|
||||
{% endblock %}
|
|
@ -118,7 +118,8 @@ encrypt=function(params,PK, m){
|
|||
|
||||
return{
|
||||
C1:C1,
|
||||
C2:C2
|
||||
C2:C2,
|
||||
r:r
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -80,23 +80,22 @@ function isVotingInputValid() {
|
|||
return valid;
|
||||
}
|
||||
|
||||
// Generates a blank vote as a string using the binary encoding scheme
|
||||
function genBlankVote() {
|
||||
var vote = "";
|
||||
|
||||
for(var i = 0; i < OPTION_COUNT; i++) {
|
||||
vote += "0";
|
||||
|
||||
if (i !== (OPTION_COUNT - 1)) {
|
||||
vote += ",";
|
||||
}
|
||||
}
|
||||
|
||||
return vote;
|
||||
}
|
||||
|
||||
var progressBar = document.getElementById("progress-bar");
|
||||
|
||||
$('#gen-ballots-btn').click(function() {
|
||||
// Ensure that the user selections are valid
|
||||
if(isVotingInputValid()) {
|
||||
// Hide the button
|
||||
$(this).toggleClass('hidden');
|
||||
|
||||
// Inject the description progress bar which can then be updated by the encrypt btn
|
||||
$('#progress-bar-description').toggleClass('hidden');
|
||||
$('#progress-bar-container').toggleClass('hidden');
|
||||
|
||||
setTimeout(generateBallots, 25);
|
||||
}
|
||||
});
|
||||
|
||||
// Based on the user's vote in the current poll, this generates a ballot which
|
||||
// does not leak information about how many options the user has selected
|
||||
function generateBallot() {
|
||||
|
@ -156,16 +155,20 @@ function generateBallot() {
|
|||
unencryptedVote.split(',').forEach(function(fragment) {
|
||||
var cipher = encrypt(params, pk, parseInt(fragment));
|
||||
|
||||
// Store C1 and C2 from the cipher in the fragment
|
||||
// Store C1, C2 and r from the cipher in the fragment
|
||||
var c1Bytes = [];
|
||||
cipher.C1.toBytes(c1Bytes);
|
||||
|
||||
var c2Bytes = [];
|
||||
cipher.C2.toBytes(c2Bytes);
|
||||
|
||||
var rBytes = [];
|
||||
cipher.r.toBytes(rBytes);
|
||||
|
||||
encFragments.push({
|
||||
C1 : c1Bytes.toString(),
|
||||
C2 : c2Bytes.toString()
|
||||
C2 : c2Bytes.toString(),
|
||||
r : rBytes.toString()
|
||||
});
|
||||
});
|
||||
|
||||
|
@ -180,29 +183,19 @@ function generateBallot() {
|
|||
};
|
||||
}
|
||||
|
||||
$('#gen-ballots-btn').click(function() {
|
||||
// Ensure that the user selections are valid
|
||||
if(isVotingInputValid()) {
|
||||
// Hide the button
|
||||
$(this).toggleClass('hidden');
|
||||
// Generates a blank vote as a string using the binary encoding scheme
|
||||
function genBlankVote() {
|
||||
var vote = "";
|
||||
|
||||
// Inject the description progress bar which can then be updated by the encrypt btn
|
||||
$('#progress-bar-description').toggleClass('hidden');
|
||||
$('#progress-bar-container').toggleClass('hidden');
|
||||
for(var i = 0; i < OPTION_COUNT; i++) {
|
||||
vote += "0";
|
||||
|
||||
setTimeout(generateBallotsAndShowUsr, 25);
|
||||
}
|
||||
});
|
||||
|
||||
function voteSuccessfullyReceived() {
|
||||
let titleTxt = 'Vote Successfully Received';
|
||||
let bodyText = "Thank you for voting!";
|
||||
|
||||
if(POLL_NUM !== POLL_COUNT) {
|
||||
bodyText += " You can vote on the next poll by closing down this dialog and clicking 'Next Poll'.";
|
||||
if (i !== (OPTION_COUNT - 1)) {
|
||||
vote += ",";
|
||||
}
|
||||
}
|
||||
|
||||
showDialogWithText(titleTxt, bodyText);
|
||||
return vote;
|
||||
}
|
||||
|
||||
var CSRF = $( "input[name='csrfmiddlewaretoken']" ).val();
|
||||
|
@ -211,25 +204,6 @@ function csrfSafeMethod(method) {
|
|||
return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
|
||||
}
|
||||
|
||||
function sendBallotToServer(selection, altHash) {
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRFToken", CSRF);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : window.location,
|
||||
data : JSON.stringify({ ballot: selection}),
|
||||
success : function(){
|
||||
onAfterBallotSend(altHash);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var bytestostring = function(b) {
|
||||
var s = "";
|
||||
var len = b.length;
|
||||
|
@ -272,63 +246,24 @@ function SHA256Hash(bytes, toStr) {
|
|||
}
|
||||
}
|
||||
|
||||
// Called once the ballot has been sent to the back-end and dialog has closed
|
||||
function onAfterBallotSend(altHash) {
|
||||
let titleText = 'Vote Successfully Received';
|
||||
let bodyText = "Thank you for voting! This is your copy of your ballot - make sure to save it onto your phone before closing this window.";
|
||||
function generateBallots() {
|
||||
// Generate Ballot A and Ballot B to be displayed to the user
|
||||
// This fn starts the process
|
||||
var ballotA = generateBallot();
|
||||
|
||||
if(POLL_NUM !== POLL_COUNT) {
|
||||
bodyText += " You can vote on the next poll by closing down this dialog and clicking 'Next Poll'.";
|
||||
}
|
||||
// Update the progress bar once the generation has completed
|
||||
progressBar.setAttribute("style", "width: 50%;");
|
||||
|
||||
// With one ballot selected, we can display a QR code of the voter's copy
|
||||
var modalDialog = $('#modalDialog');
|
||||
var title = modalDialog.find('.modal-title');
|
||||
var body = modalDialog.find('.modal-body');
|
||||
title.text(titleText);
|
||||
body.empty();
|
||||
// This delay allows the execution thread to update the above CSS on the progress bar
|
||||
setTimeout(function () {
|
||||
var ballotB = generateBallot();
|
||||
progressBar.setAttribute("style", "width: 100%;");
|
||||
|
||||
var p = document.createElement("p");
|
||||
p.innerHTML = bodyText;
|
||||
body.append(p);
|
||||
|
||||
// Generate the body of the dialog which displays the unselected ballot QR code and hash
|
||||
var choiceGroupDiv = document.createElement('div');
|
||||
choiceGroupDiv.setAttribute('class', 'choice-group');
|
||||
|
||||
var QRCodeImg = document.createElement('img');
|
||||
QRCodeImg.setAttribute('class', 'QR-code');
|
||||
new QRCode(QRCodeImg, altHash);
|
||||
|
||||
choiceGroupDiv.append(QRCodeImg);
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
var hashGroupDiv = document.createElement('div');
|
||||
var br = document.createElement('br');
|
||||
hashGroupDiv.append( br );
|
||||
|
||||
var hash = document.createElement("span");
|
||||
hash.innerHTML = "Hash: " + altHash;
|
||||
hashGroupDiv.append( hash );
|
||||
|
||||
// -----------------------------------------------
|
||||
|
||||
body.append(choiceGroupDiv);
|
||||
body.append(hashGroupDiv);
|
||||
|
||||
modalDialog.modal('show');
|
||||
showFirstQRCode(ballotA, ballotB);
|
||||
}, 150);
|
||||
}
|
||||
|
||||
function processBallotSelection(selection, selectionHash, alt, altHash) {
|
||||
// Dispatch the ballot to the server
|
||||
sendBallotToServer(selection, altHash);
|
||||
|
||||
// Call the successfn currently with the selection hash but this may not be needed
|
||||
//successFn(alt, altHash);
|
||||
}
|
||||
|
||||
function showBallotChoiceDialog(ballotA, ballotB) {
|
||||
function showFirstQRCode(ballotA, ballotB) {
|
||||
var ballots = new Array(ballotA, ballotB);
|
||||
var ballotHashes = new Array(2);
|
||||
|
||||
|
@ -336,28 +271,18 @@ function showBallotChoiceDialog(ballotA, ballotB) {
|
|||
for (let i = 0; i <= 1; i++)
|
||||
ballotHashes[i] = SHA256Hash(stringtobytes(JSON.stringify(ballots[i])), true);
|
||||
|
||||
// With the ballots and their hashes generated, we can display the ballot choice dialog
|
||||
// With the ballots and their hashes generated, we can display the QR code of both hashes
|
||||
var modalDialog = $('#modalDialog');
|
||||
var title = modalDialog.find('.modal-title');
|
||||
var body = modalDialog.find('.modal-body');
|
||||
var footer = modalDialog.find('.modal-footer');
|
||||
|
||||
body.empty();
|
||||
title.text('Please Select a Ballot');
|
||||
title.text('Please Scan this QR Code');
|
||||
|
||||
// Generate the body of the dialog which consists of a button for A and for B as well as their hashes
|
||||
var choiceGroupDiv = document.createElement('div');
|
||||
choiceGroupDiv.setAttribute('class', 'choice-group');
|
||||
|
||||
var btnChoiceA = document.createElement('a');
|
||||
btnChoiceA.setAttribute('id', 'choice-A');
|
||||
btnChoiceA.setAttribute('class', 'btn btn-sq btn-primary');
|
||||
btnChoiceA.innerHTML = 'A';
|
||||
choiceGroupDiv.append(btnChoiceA);
|
||||
|
||||
var btnChoiceB = document.createElement('a');
|
||||
btnChoiceB.setAttribute('id', 'choice-B');
|
||||
btnChoiceB.setAttribute('class', 'btn btn-sq btn-warning choice');
|
||||
btnChoiceB.innerHTML = 'B';
|
||||
choiceGroupDiv.append(btnChoiceB);
|
||||
var QRCodeImg = document.createElement('img');
|
||||
QRCodeImg.setAttribute('class', 'QR-code');
|
||||
new QRCode(QRCodeImg, ballotHashes[0] + ';' + ballotHashes[1]);
|
||||
|
||||
// ----------------------------------------------
|
||||
|
||||
|
@ -378,38 +303,153 @@ function showBallotChoiceDialog(ballotA, ballotB) {
|
|||
|
||||
// -----------------------------------------------
|
||||
|
||||
body.append(choiceGroupDiv);
|
||||
body.append(QRCodeImg);
|
||||
body.append(hashGroupDiv);
|
||||
|
||||
var closeButton = $('close-button');
|
||||
closeButton.removeClass('btn-success');
|
||||
closeButton.addClass('btn-danger');
|
||||
closeButton.text("Close without submitting vote");
|
||||
|
||||
var nextButton = document.createElement('button');
|
||||
nextButton.setAttribute('type', 'button');
|
||||
nextButton.setAttribute('id', 'next-button');
|
||||
nextButton.setAttribute('class', 'btn btn-default');
|
||||
nextButton.innerHTML = "Next";
|
||||
|
||||
footer.prepend(nextButton);
|
||||
|
||||
|
||||
modalDialog.modal('show');
|
||||
|
||||
$('#next-button').click(function(e) {
|
||||
showBallotChoiceDialog(ballots);
|
||||
});
|
||||
}
|
||||
|
||||
function showBallotChoiceDialog(ballots) {
|
||||
// Display the ballot choice dialog
|
||||
var modalDialog = $('#modalDialog');
|
||||
var title = modalDialog.find('.modal-title');
|
||||
var body = modalDialog.find('.modal-body');
|
||||
|
||||
body.empty();
|
||||
title.text('Please Select a Ballot');
|
||||
|
||||
// Generate the body of the dialog which consists of a button for A and for B
|
||||
var choiceGroupDiv = document.createElement('div');
|
||||
choiceGroupDiv.setAttribute('class', 'choice-group');
|
||||
|
||||
var btnChoiceA = document.createElement('a');
|
||||
btnChoiceA.setAttribute('id', 'choice-A');
|
||||
btnChoiceA.setAttribute('class', 'btn btn-sq btn-primary');
|
||||
btnChoiceA.innerHTML = 'A';
|
||||
choiceGroupDiv.append(btnChoiceA);
|
||||
|
||||
var btnChoiceB = document.createElement('a');
|
||||
btnChoiceB.setAttribute('id', 'choice-B');
|
||||
btnChoiceB.setAttribute('class', 'btn btn-sq btn-warning choice');
|
||||
btnChoiceB.innerHTML = 'B';
|
||||
choiceGroupDiv.append(btnChoiceB);
|
||||
|
||||
body.append(choiceGroupDiv);
|
||||
|
||||
modalDialog.modal('show');
|
||||
|
||||
// Register callback functions for the selection of either A or B
|
||||
$('#choice-A').click(function(e) {
|
||||
processBallotSelection(ballots[0], ballotHashes[0], ballots[1], ballotHashes[1]);
|
||||
sendBallotsToServer(ballots[0], ballots[1]);
|
||||
});
|
||||
|
||||
$('#choice-B').click(function(e) {
|
||||
processBallotSelection(ballots[1], ballotHashes[1], ballots[0], ballotHashes[0]);
|
||||
sendBallotsToServer(ballots[1], ballots[0]);
|
||||
});
|
||||
}
|
||||
|
||||
function generateBallotB(ballotA) {
|
||||
var ballotB = generateBallot();
|
||||
progressBar.setAttribute("style", "width: 100%;");
|
||||
function sendBallotsToServer(selection, alt) {
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(xhr, settings) {
|
||||
if (!csrfSafeMethod(settings.type) && !this.crossDomain) {
|
||||
xhr.setRequestHeader("X-CSRFToken", CSRF);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
showBallotChoiceDialog(ballotA, ballotB);
|
||||
// Elliptic curve cryptography params used for encryption of encrypted vote
|
||||
// fragments
|
||||
var ctx = new CTX("BN254CX");
|
||||
var n = new ctx.BIG();
|
||||
var g1 = new ctx.ECP();
|
||||
var g2 = new ctx.ECP2();
|
||||
|
||||
var parameter = $('#event-param').val();
|
||||
var tempParams = JSON.parse(JSON.parse(parameter).crypto);
|
||||
|
||||
//copying the values
|
||||
n.copy(tempParams.n);
|
||||
g1.copy(tempParams.g1);
|
||||
g2.copy(tempParams.g2);
|
||||
|
||||
var params = {
|
||||
n:n,
|
||||
g1:g1,
|
||||
g2:g2
|
||||
};
|
||||
|
||||
var tempPK = JSON.parse($('#comb_pk').val());
|
||||
var pk = new ctx.ECP(0);
|
||||
pk.copy(tempPK.PK);
|
||||
|
||||
var voterID = window.location.search.slice(1).split(/=(.+)/)[1];//.slice(0, -2);
|
||||
var eventID = window.location.href.split('/')[4];
|
||||
var pollNum = $('#poll-num').text();
|
||||
var ballotID = encodeURIComponent(btoa(JSON.stringify({voterID: voterID, eventID: eventID, pollNum: pollNum})));
|
||||
|
||||
var SK = "temporary";
|
||||
var encAlt = sjcl.encrypt(SK, JSON.stringify(alt));
|
||||
selection = JSON.stringify(selection);
|
||||
|
||||
$.ajax({
|
||||
type : "POST",
|
||||
url : window.location,
|
||||
data : { handle: ballotID, encBallot: encAlt, ballot: selection },
|
||||
success : function(){
|
||||
onAfterBallotSend(ballotID, SK);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function generateBallotsAndShowUsr() {
|
||||
// Generate Ballot A and Ballot B to be displayed to the user
|
||||
// This fn starts the process
|
||||
var ballotA = generateBallot();
|
||||
// Called once the ballot has been sent to the back-end and dialog has closed
|
||||
function onAfterBallotSend(ballotID, SK) {
|
||||
let titleText = 'Vote Successfully Received';
|
||||
let bodyText = "Thank you for voting! Your secret key is '"+SK+"'. Make sure to scan this QR code with your phone before closing this window.";
|
||||
|
||||
// Update the progress bar once the generation has completed
|
||||
progressBar.setAttribute("style", "width: 50%;");
|
||||
if(POLL_NUM !== POLL_COUNT) {
|
||||
bodyText += " You can vote on the next poll by closing down this dialog and clicking 'Next Poll'.";
|
||||
}
|
||||
|
||||
// This delay allows the execution thread to update the above CSS on the progress bar
|
||||
setTimeout(function () {
|
||||
generateBallotB(ballotA);
|
||||
}, 150);
|
||||
// With one ballot selected, we can display a QR code of the ballot ID
|
||||
var modalDialog = $('#modalDialog');
|
||||
var title = modalDialog.find('.modal-title');
|
||||
var body = modalDialog.find('.modal-body');
|
||||
title.text(titleText);
|
||||
body.empty();
|
||||
|
||||
var p = document.createElement("p");
|
||||
p.innerHTML = bodyText;
|
||||
body.append(p);
|
||||
|
||||
// Generate the body of the dialog which displays the unselected ballot QR code
|
||||
var QRCodeImg = document.createElement('img');
|
||||
QRCodeImg.setAttribute('class', 'QR-code');
|
||||
new QRCode(QRCodeImg, ballotID);
|
||||
|
||||
body.append(QRCodeImg);
|
||||
|
||||
var closeButton = $('#close-button');
|
||||
closeButton.removeClass('btn-danger');
|
||||
closeButton.addClass('btn-success');
|
||||
closeButton.text("Close");
|
||||
|
||||
modalDialog.modal('show');
|
||||
}
|
17
static/js/vote_audit.js
Normal file
17
static/js/vote_audit.js
Normal file
|
@ -0,0 +1,17 @@
|
|||
$('#begin-test').click(function() {
|
||||
var ballot = JSON.parse(sjcl.decrypt($('#SK').val(), $('#ballot').text()));
|
||||
var votes = ballot['encryptedVotes'][0]['fragments'];
|
||||
$('#ballot-content').text(JSON.stringify(votes));
|
||||
|
||||
var option = 0;
|
||||
votes.forEach(function(cT) {
|
||||
option++;
|
||||
var encoding = "";
|
||||
for (var i = 0; i < cT['C1'].length; i++) {
|
||||
cipherText = "("+cT['C1']+","+cT['C2']+")";
|
||||
var m = cT['C2'][i] / Math.pow(cT['C1'][i], cT['r'][i]);
|
||||
encoding += (m) ? "1" : "0";
|
||||
}
|
||||
$('#ballot-result').text($('#ballot-result').text() + "\n\nOption "+option+": "+encoding);
|
||||
})
|
||||
});
|
Reference in a new issue