Implemented full end-to-end encryption and decryption of an event using trustee public and secret keys. This required modification of the NodeJS crypto server to receive post data from the crypto_rpc py methods and for combining SKs together. Additionally, the new binary voting encoding scheme has been implemented for encryption and decryption of the event. General UI improvements have been made and as well as some other bug fixes
This commit is contained in:
parent
0c354cd542
commit
e33b91f852
23 changed files with 809 additions and 446 deletions
|
@ -14,7 +14,7 @@
|
|||
<hr>
|
||||
|
||||
<div class="row">
|
||||
|
||||
{% bootstrap_messages %}
|
||||
{% if socialaccount_providers %}
|
||||
<div class="col-md-5 col-lg-5">
|
||||
{% include "allauth/account/provider_panel.html" with process="login" %}
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
crossorigin="anonymous"></script>
|
||||
<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/encrypt.js' %}" type="text/javascript"></script>
|
||||
|
||||
<script type="text/javascript" src="{% static 'js/core/rand.js' %}"></script>
|
||||
|
@ -74,15 +75,19 @@
|
|||
|
||||
//new function
|
||||
demosEncrypt.encryptAndSubmit = function() {
|
||||
var ctx = new CTX("BN254CX"); //new context we can use
|
||||
// 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 param = $('#event-param').val();
|
||||
//console.log(param);
|
||||
var parameter = $('#event-param').val();
|
||||
var tempParams = JSON.parse(JSON.parse(parameter).crypto);
|
||||
|
||||
var tempParams = JSON.parse(param);
|
||||
//copying the values
|
||||
n.copy(tempParams.n);
|
||||
g1.copy(tempParams.g1);
|
||||
|
@ -92,26 +97,55 @@
|
|||
n:n,
|
||||
g1:g1,
|
||||
g2:g2
|
||||
}
|
||||
|
||||
var tempPK = JSON.parse($('#comb_pk').val());
|
||||
};
|
||||
|
||||
var tempPK = JSON.parse($('#comb_pk').val());
|
||||
var pk = new ctx.ECP(0);
|
||||
pk.copy(tempPK.PK);
|
||||
var answer = $('#poll-options').val();
|
||||
console.log(answer);
|
||||
var cipher = encrypt(params, pk, answer);
|
||||
|
||||
var c1Bytes = [];
|
||||
cipher.C1.toBytes(c1Bytes);
|
||||
var c2Bytes = [];
|
||||
cipher.C2.toBytes(c2Bytes);
|
||||
|
||||
$('#id_cipher_text_c1').val(c1Bytes.toString());
|
||||
$('#id_cipher_text_c2').val(c2Bytes.toString());
|
||||
// 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();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
//new function
|
||||
|
@ -149,7 +183,7 @@
|
|||
|
||||
//new function
|
||||
demosEncrypt.generateKeys = function() {
|
||||
parameter = $("#event-param").val();
|
||||
var parameter = $("#event-param").val();
|
||||
var tempParams = JSON.parse(JSON.parse(parameter).crypto);
|
||||
//the full objects need to be initalised as per the library, then copy the values we need into it
|
||||
//I follow Bingsheng's code as to what objects are used in the parameter object
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
|
||||
<title>{% block title %}dẽmos 2{% endblock %}</title>
|
||||
<title>{% block title %}DĒMOS 2{% endblock %}</title>
|
||||
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap-theme.min.css">
|
||||
|
|
|
@ -7,24 +7,24 @@
|
|||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<h1>Event: {{event.title}}</h1>
|
||||
<h2>Trustee Decrypt</h2>
|
||||
<h2>Trustee Event Decryption for Event '{{ event.title }}'</h2>
|
||||
<hr/>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Secret Key</div>
|
||||
<div class="panel-heading"><strong>Submit your Secret Key as '{{ user_email }}'</strong></div>
|
||||
<div class="panel panel-body">
|
||||
<input id="secret-key" class="textinput textInput form-control" type="text"></input>
|
||||
<p>Use your secret key to generate a decrypted cipher</p>
|
||||
<button id="keygen-btn" onclick="demosEncrypt.decryptCipher()" class="btn btn-default">Decrypt</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Encrypted Ciphers</div>
|
||||
<div class="panel panel-body">
|
||||
{% load crispy_forms_tags %}
|
||||
<form method="post" action="" class="">
|
||||
{% crispy formset helper %}
|
||||
<input class="btn btn-default" type="submit" value="Submit" disabled>
|
||||
</form>
|
||||
<form id="sk-form" method="POST">
|
||||
{% csrf_token %}
|
||||
<input id="secret-key" name="secret-key" class="textinput textInput form-control" type="text"/>
|
||||
<div class="alert alert-info" role="alert" style="margin-top: 0.75em;">
|
||||
Your secret key will be used to decrypt the event and get a vote tally for every poll.
|
||||
</div>
|
||||
<label for="files_sk_upload" class="btn btn-primary">
|
||||
<span class="glyphicon glyphicon-cloud-upload"></span>
|
||||
Upload Key
|
||||
</label>
|
||||
<input type="file" id="files_sk_upload" name="file" class="btn-info">
|
||||
<input type="submit" value="Submit" class="btn btn-success"/>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -9,12 +9,22 @@
|
|||
{% if is_organiser %}
|
||||
<div>
|
||||
<!-- Heading -->
|
||||
<div class="col-xs-7 col-sm-9 col-md-10">
|
||||
<div class="col-xs-7 col-sm-9 col-md-9">
|
||||
<h2>Event: {{object.title}}</h2>
|
||||
</div>
|
||||
<!-- Edit Button -->
|
||||
<div class="col-xs-5 col-sm-3 col-md-2 marginTopEditButton">
|
||||
<a href="{% url 'polls:edit-event' event.id %}" class="btn btn-primary" style="float: right;">
|
||||
<div class="col-xs-5 col-sm-3 col-md-3 marginTopEditButton">
|
||||
{% if object.has_received_votes and object.ended == False %}
|
||||
<a href="{% url 'polls:end-event' event.id %}" class="btn btn-danger" style="float: right;">
|
||||
<span class="glyphicon glyphicon-stop"></span> End
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if decrypted == True and object.ended == True %}
|
||||
<a href="{% url 'polls:event-results' event.id %}" class="btn btn-success" style="float: right;">
|
||||
<span class="glyphicon glyphicon-stats"></span> Results
|
||||
</a>
|
||||
{% endif %}
|
||||
<a href="{% url 'polls:edit-event' event.id %}" class="btn btn-primary" style="float: right; margin-right: 0.4em;">
|
||||
<span class="fa fa-pencil"></span> Edit
|
||||
</a>
|
||||
</div>
|
||||
|
@ -40,11 +50,11 @@
|
|||
<a href="{% url 'polls:event-polls' event.id %}"><strong>Polls ({{ object.polls.count }})</strong></a>
|
||||
</li>
|
||||
<li class="{% block event_nav_organisers %}{% endblock %}">
|
||||
<a href="{% url 'polls:event-organisers' event.id %}"><strong>Entities</strong></a>
|
||||
<a href="{% url 'polls:event-entities' event.id %}"><strong>Entities</strong></a>
|
||||
</li>
|
||||
{% if is_organiser %}
|
||||
<li class="{% block event_nav_launch %}{% endblock %}">
|
||||
<a href="{% url 'polls:launch-event' event.id %}"><strong>Advanced</strong></a>
|
||||
<a href="{% url 'polls:event-advanced' event.id %}"><strong>Advanced</strong></a>
|
||||
</li>
|
||||
{% endif %}
|
||||
</ul>
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
{% block event_content %}
|
||||
{% if object.polls.all %}
|
||||
{% for poll in object.polls.all %}
|
||||
<h3>Poll: {{ poll.question_text }} (<a href="{% url 'polls:view-poll' event_id=event.id poll_num=forloop.counter %}">Edit</a>)</h3>
|
||||
<h3>Poll: {{ poll.question_text }} (<a href="{% url 'polls:edit-poll' event_id=event.id poll_num=forloop.counter %}">Edit</a>)</h3>
|
||||
<br/>
|
||||
<h4>Poll Options:</h4>
|
||||
<ul class="list-group">
|
||||
|
|
|
@ -46,9 +46,13 @@
|
|||
</td>
|
||||
<td class="text-center">
|
||||
<div class="btn statusBtn
|
||||
{% if event.status == 'Expired' %}btn-danger{% endif %}
|
||||
{% if event.status == 'Future' %}btn-info{% endif %}
|
||||
{% if event.status == 'Prepared' %}btn-info{% endif %}
|
||||
{% if event.status == 'Active' %}btn-success{% endif %}
|
||||
{% if event.status == 'Future' %}btn-info{% endif %}">
|
||||
{% if event.status == 'Expired' %}btn-danger{% endif %}
|
||||
{% if event.status == 'Ended' %}btn-danger{% endif %}
|
||||
{% if event.status == 'Decrypted' %}btn-primary{% endif %}
|
||||
">
|
||||
{{ event.status }}
|
||||
</div>
|
||||
</td>
|
||||
|
|
|
@ -9,6 +9,8 @@
|
|||
<div class="container">
|
||||
<h2>Trustee Event Setup for Event '{{ event.title }}'</h2>
|
||||
<hr/>
|
||||
<h4>Key Generation For: {{ user_email }}</h4>
|
||||
<br/>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><strong>Step 1: Generate Your Secret Key</strong></div>
|
||||
<div class="panel panel-body">
|
||||
|
|
81
allauthdemo/templates/polls/event_vote.html
Executable file
81
allauthdemo/templates/polls/event_vote.html
Executable file
|
@ -0,0 +1,81 @@
|
|||
{% extends "bases/bootstrap-with-nav.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block app_js_vars %}
|
||||
var option_count = {{ object.options.count }};
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<input id="event-param" type="text" value="{{event.EID}}" hidden/>
|
||||
<input id="comb_pk" type="text" value="{{event.public_key}}" hidden/>
|
||||
|
||||
<!-- TODO: Add warning not to share the URL-->
|
||||
<h2>Event Voting Page for the Event '{{ object.event.title }}'</h2>
|
||||
<div class="alert alert-warning" role="alert" style="margin-top: 1em;">
|
||||
You are voting as: <strong>{{ voter_email }}</strong> - Ensure this is correct and don't share this URL!
|
||||
</div>
|
||||
<span><strong>Voting status:</strong>
|
||||
{% if has_voted %}
|
||||
Voted - Re-Submitting will Change your Vote
|
||||
{% else %}
|
||||
Not Voted
|
||||
{% endif %}
|
||||
</span>
|
||||
<br/>
|
||||
<span><strong>Number of polls for this event:</strong> {{ poll_count }}</span>
|
||||
<br/>
|
||||
<br/>
|
||||
<span><strong>Instructions:</strong>
|
||||
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 }}. Please make your choice below.
|
||||
</span>
|
||||
<div class="panel panel-body">
|
||||
{% if prev_index %}
|
||||
<a href="{% url 'polls:event-vote' event_id=object.event.id poll_num=prev_index %}" class="btn" role="button">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if next_index %}
|
||||
<a href="{% url 'polls:event-vote' event_id=object.event.id poll_num=next_index %}" class="btn" role="button">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% if object.options.all %}
|
||||
<h3>Poll {{ poll_num }} of {{ poll_count }}: {{object.question_text}}</h3>
|
||||
{% if can_vote %}
|
||||
{% load crispy_forms_tags %}
|
||||
<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">
|
||||
{% 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>
|
||||
<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>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>You don't have permission to vote in this event.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>No options are available.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
{% endblock %}
|
|
@ -1,85 +0,0 @@
|
|||
{% extends "bases/bootstrap-with-nav.html" %}
|
||||
{% load staticfiles %}
|
||||
{% load bootstrap3 %}
|
||||
|
||||
{% block app_js_vars %}
|
||||
|
||||
|
||||
var option_count = {{ object.options.count }};
|
||||
{% endblock %}
|
||||
|
||||
{% block content %}
|
||||
|
||||
<div class="container">
|
||||
<input id="event-param" type="text" value="{{event.EID}}" hidden></input>
|
||||
<input id="comb_pk" type="text" value="{{event.public_key}}" hidden></input>
|
||||
|
||||
<h1>Poll: {{object.question_text}}</h1>
|
||||
<span>Poll {{ poll_num }} of {{ poll_count }} in Event: <a href="{% url 'polls:view-event' object.event.id %}">{{ object.event.title }}</a></span>
|
||||
<div class="panel panel-body">
|
||||
{% if prev_index %}
|
||||
<a href="{% url 'polls:view-poll' event_id=object.event.id poll_num=prev_index %}" class="btn" role="button">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if next_index %}
|
||||
<a href="{% url 'polls:view-poll' event_id=object.event.id poll_num=next_index %}" class="btn" role="button">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
<a href="{% url 'polls:edit-poll' event_id=object.event.id poll_num=poll_num %}"><span class="fa fa-pencil"></span> Edit Poll</a>
|
||||
{% if object.options.all %}
|
||||
<h3>Options</h3>
|
||||
<p> {{ vote_count }} vote(s) have been cast</p>
|
||||
{% if can_vote %}
|
||||
{% if has_voted %}
|
||||
<p>You have already voted in this poll. Resubmitting the form will change your vote.</p>
|
||||
{% endif %}
|
||||
<p>Voting as {{ voter_email }} -- Do NOT share this url</p>
|
||||
{% load crispy_forms_tags %}
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">Options</div>
|
||||
<div class="panel panel-body">
|
||||
<select class="radio-inline select form-control" id="poll-options" name="options">
|
||||
{% load custom_filters_tags %}
|
||||
{% for option in object.options.all %}
|
||||
<option value="{{forloop.counter|get_ballot_value}}">{{ option.choice_text }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
|
||||
<button id="keygen-btn" onclick="demosEncrypt.encryptAndSubmit()" class="btn btn-default">Encrypt & Submit</button>
|
||||
<form id="cipher-form" method="post" action="" class="">
|
||||
{% crispy form %}
|
||||
{% csrf_token %}
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{% else %}
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<p>You do not have permission to vote in this Event.</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
<p>No options are available.</p>
|
||||
{% endif %}
|
||||
</div>
|
||||
<br>
|
||||
<br>
|
||||
POLL ENC {{ object.enc }}
|
||||
|
||||
{% if form.errors %}
|
||||
{% for field in form %}
|
||||
{% for error in field.errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endfor %}
|
||||
{% for error in form.non_field_errors %}
|
||||
<div class="alert alert-danger">
|
||||
<strong>{{ error|escape }}</strong>
|
||||
</div>
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
Reference in a new issue