Updated the voting and event decryption pages. On the voting page, added the ability to vote by selecting checkboxes instead of a drop down select menu. This adds flexibility at event creation to specify a wide range of min and max option selections for polls. On the event decryption page, SK validation was added based on the stored trustee PK as well as a dialog to display any validation errors. Most of the updates took place behind the scenes at the backend.
This commit is contained in:
parent
3fd9173666
commit
745fdf06b1
10 changed files with 503 additions and 152 deletions
|
@ -19,6 +19,7 @@
|
|||
<script src="{% static 'js/papaparse.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/encrypt.js' %}" type="text/javascript"></script>
|
||||
|
||||
<script type="text/javascript" src="{% static 'js/core/rand.js' %}"></script>
|
||||
|
@ -64,113 +65,6 @@
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
Code written with "New function" comments have
|
||||
been totally or mostly re-implemented by Thomas Smith
|
||||
|
||||
|
||||
*/
|
||||
|
||||
dropDownFragsNotZero = function(frags) {
|
||||
var valid = false;
|
||||
|
||||
for(var i = 0; i < frags.length; i++) {
|
||||
var frag = frags[i];
|
||||
|
||||
if(frag !== "0") {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return valid;
|
||||
};
|
||||
|
||||
//new function
|
||||
demosEncrypt.encryptAndSubmit = function() {
|
||||
// Drop down option selection validation
|
||||
if(min_selections === 1 && max_selections === 1) {
|
||||
var fragments = $('#poll-options').val().split(",");
|
||||
|
||||
if(!dropDownFragsNotZero(fragments)) {
|
||||
alert("You have to select an option in order to vote.");
|
||||
return;
|
||||
}
|
||||
} // TODO: Checkbox validation goes here
|
||||
|
||||
// Disable the enc and submit button to prevent fn from being called twice
|
||||
$('#keygen-btn').prop("disabled", true);
|
||||
|
||||
// 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);
|
||||
|
||||
// Obtain the user's selection (their vote) and encrypt the fragments of the binary encoding
|
||||
const selection = $('#poll-options').val();
|
||||
const selectionFragments = selection.split(',');
|
||||
|
||||
var cipherForm = document.getElementById("cipher-form");
|
||||
|
||||
for(var i = 0; i < selectionFragments.length; i++) {
|
||||
// Encrypt this fragment for the selection
|
||||
var cipher = encrypt(params, pk, parseInt(selectionFragments[i]));
|
||||
|
||||
// Store C1 and C2 from the cipher in 2 arrays
|
||||
var c1Bytes = [];
|
||||
cipher.C1.toBytes(c1Bytes);
|
||||
|
||||
var c2Bytes = [];
|
||||
cipher.C2.toBytes(c2Bytes);
|
||||
|
||||
// Inject hidden input controls into the form that represents a single ballot
|
||||
var c1Input = document.createElement("input");
|
||||
c1Input.setAttribute("type", "hidden");
|
||||
c1Input.setAttribute("name", "cipher_c1_frag_" + i);
|
||||
c1Input.setAttribute("value", c1Bytes.toString());
|
||||
|
||||
var c2Input = document.createElement("input");
|
||||
c2Input.setAttribute("type", "hidden");
|
||||
c2Input.setAttribute("name", "cipher_c2_frag_" + i);
|
||||
c2Input.setAttribute("value", c2Bytes.toString());
|
||||
|
||||
cipherForm.appendChild(c1Input);
|
||||
cipherForm.appendChild(c2Input);
|
||||
}
|
||||
|
||||
// Inject a final input control into the form which specifies the number of fragments
|
||||
// That make up an encrypted vote
|
||||
var fragCountInput = document.createElement("input");
|
||||
fragCountInput.setAttribute("type", "hidden");
|
||||
fragCountInput.setAttribute("name", "vote_frag_count");
|
||||
fragCountInput.setAttribute("value", "" + selectionFragments.length);
|
||||
cipherForm.appendChild(fragCountInput);
|
||||
|
||||
// Submit the encrypted vote to the server
|
||||
$('#cipher-form').submit();
|
||||
};
|
||||
|
||||
function getBytes(arr) {
|
||||
for(var i = 0; i < arr.length; i++) {
|
||||
arr[i] = parseInt(arr[i]);
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
{% if not forloop.first %},{% endif %}
|
||||
{
|
||||
title: "{{ event.title }}",
|
||||
slug: "{{ event.EID }}"
|
||||
slug: "{{ event.EID_hr }}"
|
||||
}
|
||||
{% endfor %}
|
||||
];
|
||||
|
@ -34,6 +34,7 @@
|
|||
<!-- The DEMOS1 repository can be found at: https://github.com/mlevogiannis/demos-voting -->
|
||||
<!-- TODO: look into i18n translations as this was a feature implemented in DEMOS1 to enable automatic translations -->
|
||||
<div class="container">
|
||||
|
||||
<div class="page-header">
|
||||
<h2>Create New Event with Polls</h2>
|
||||
</div>
|
||||
|
|
|
@ -4,6 +4,13 @@
|
|||
{% block sk-file-name %}{{ event.title|safe }}{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
<script type="text/javascript">
|
||||
// This is what we expect the SK supplied by the trustee to generate
|
||||
var trustee_pk = "{{ trustee_pk }}";
|
||||
|
||||
var tempParams = "{{ event.EID_crypto|escapejs }}";
|
||||
tempParams = JSON.parse(tempParams);
|
||||
</script>
|
||||
|
||||
<div class="container">
|
||||
<h2>Trustee Event Decryption for Event '{{ event.title }}'</h2>
|
||||
|
@ -49,4 +56,24 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Information Dialog called upon request -->
|
||||
<div class="modal fade" id="modalDialog" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
|
||||
<!-- Dialog content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title" style="text-align: center"><strong>Thank You</strong></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% endblock %}
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
{% load bootstrap3 %}
|
||||
|
||||
{% block app_js_vars %}
|
||||
var option_count = {{ object.options.count }};
|
||||
var min_selections = {{ min_selection }};
|
||||
var max_selections = {{ max_selection }};
|
||||
const OPTION_COUNT = {{ object.options.count }};
|
||||
const MIN_SELECTIONS = {{ min_selection }};
|
||||
const MAX_SELECTIONS = {{ max_selection }};
|
||||
var selectedCount = 0;
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
@ -13,6 +14,7 @@
|
|||
<div class="container">
|
||||
{% if can_vote %}
|
||||
<!-- Hidden fields -->
|
||||
{% csrf_token %}
|
||||
<input id="event-param" type="text" value="{{event.EID}}" hidden/>
|
||||
<input id="comb_pk" type="text" value="{{event.public_key}}" hidden/>
|
||||
|
||||
|
@ -37,7 +39,15 @@
|
|||
You will be shown each poll for this event one by one where you will need to make a selection for the current
|
||||
poll before moving onto the next poll. <strong>For this specific poll</strong> you need to make a <strong>
|
||||
minimum</strong> of {{ min_selection }} option selection(s) and a <strong>maximum</strong> of
|
||||
{{ max_selection }}. <br/><br/>Please make your choice below.
|
||||
{{ max_selection }}.
|
||||
|
||||
{% if min_selection == 0 %}
|
||||
<br/><br/>Due to the fact that you are permitted to select nothing, simply hitting submit will submit a
|
||||
'blank' vote so please be aware of this. You can always re-visit this page before the event ends if you
|
||||
change your mind.
|
||||
{% endif %}
|
||||
|
||||
<br/><br/>Please make your choice below.
|
||||
</span>
|
||||
|
||||
<!-- Poll Voting Section -->
|
||||
|
@ -48,18 +58,30 @@
|
|||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Options</strong></div>
|
||||
<div class="panel panel-body">
|
||||
<select class="radio-inline select form-control" id="poll-options" name="options">
|
||||
{% comment %}<select class="radio-inline select form-control" id="poll-options" name="options">
|
||||
{% load custom_filters_tags %}
|
||||
<option value="{{ -1|get_ballot_value:object.options.all.count }}">Please Select...</option>
|
||||
{% for option in object.options.all %}
|
||||
<option value="{{forloop.counter|get_ballot_value:object.options.all.count}}">{{ option.choice_text }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</select>{% endcomment %}
|
||||
{% for option in object.options.all %}
|
||||
<div class="checkbox">
|
||||
{% load custom_filters_tags %}
|
||||
<label><input type="checkbox" value="{{forloop.counter|get_ballot_value:object.options.all.count}}">{{ option.choice_text }}</label>
|
||||
</div>
|
||||
{% endfor %}
|
||||
<hr/>
|
||||
<button id="keygen-btn" onclick="demosEncrypt.encryptAndSubmit()" class="btn btn-primary">Submit</button>
|
||||
<form id="cipher-form" method="post" action="" class="">
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
<div id="ballot-gen-progress-area">
|
||||
<button id="gen-ballots-btn" class="btn btn-primary">Generate Ballots</button>
|
||||
<!-- Progress bar which is used during encryption -->
|
||||
<h4 id="progress-bar-description" class="hidden">Generating Ballots...</h4>
|
||||
<div id="progress-bar-container" class="progress hidden">
|
||||
<div id="progress-bar" class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 0%;">
|
||||
<span class="sr-only">70% Complete</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -78,6 +100,27 @@
|
|||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
|
||||
<!-- Information Dialog called upon request -->
|
||||
<div class="modal fade" id="modalDialog" role="dialog">
|
||||
<div class="modal-dialog">
|
||||
|
||||
<!-- Dialog content-->
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal">×</button>
|
||||
<h4 class="modal-title" style="text-align: center"><strong>Ballot</strong></h4>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% else %} <!-- for: { if can_vote %} -->
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>{{ cant_vote_reason }}</p>
|
||||
|
|
Reference in a new issue