Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
657 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
{% extends "base.html" %} | ||
{% block content %} | ||
<script> | ||
function send_email() { | ||
var form = document.forms['email_form']; | ||
|
||
$.post("{% url helios.views.one_election_email_trustees election_id=election.election_id %}", {'body' : form.body.value}, function(data) { | ||
// decide whether or not to keep going | ||
if (data != "DONE") { | ||
alert('oy unexpected: ' + data); | ||
} else { | ||
alert('done!'); | ||
document.location = "./view"; | ||
} | ||
}); | ||
} | ||
</script> | ||
|
||
<h2>{{election.name}}: Email Voters — Email Trustees</h2> | ||
|
||
<p> | ||
You are about to email the trustees in this election: | ||
</p> | ||
|
||
<ul> | ||
{% for keyshare in keyshares %} | ||
<li> <tt>{{keyshare.email}}</tt></li> | ||
{% endfor %} | ||
</ul> | ||
|
||
<blockquote> | ||
<form name="email_form" method="post" onsubmit="try {send_email();} catch(e) {alert(e);} return false;"> | ||
|
||
<pre> | ||
Dear [TRUSTEE_NAME], | ||
</pre> | ||
|
||
<textarea name="body" cols="60" rows="10" wrap="soft" class="pretty"> | ||
</textarea> | ||
<pre> | ||
Your Trustee homepage for election {{election.name}} is: | ||
[TRUSTEE_HOMEPAGE] | ||
|
||
Your password is: | ||
[TRUSTEE_PASSWORD] | ||
</pre> | ||
|
||
</blockquote> | ||
|
||
<br /> | ||
<br /><br /> | ||
<input type="submit" value="send now!" class="pretty" /> | ||
</form> | ||
|
||
</div> | ||
<!-- end #content --> | ||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,48 @@ | ||
{% extends "base.html" %} | ||
{% block content %} | ||
<script language="javascript"> | ||
function combine_keys() { | ||
// go fetch keyshares | ||
Helios.get_election_trustees({'election_id' : '{{election.election_id}}'}, function(result) { | ||
// we have the list of keyshares | ||
// loop through them and combine them | ||
var combined_key = 1; | ||
$(result).each(function(i, keyshare) { | ||
// FIXME: verify proof | ||
var one_pk = ElGamal.PublicKey.fromJSONObject(keyshare.public_key); | ||
combined_key = one_pk.multiply(combined_key); | ||
}); | ||
|
||
// submit the combined_pk | ||
$.post("set_pk", {'public_key_json': jQuery.toJSON(combined_key)}, function(result) { | ||
if (result != "SUCCESS") | ||
alert('public key not set, probably because it was already set.'); | ||
|
||
document.location = "./view"; | ||
}); | ||
}); | ||
} | ||
</script> | ||
|
||
<h2 class="title">{{election.name}} — Key Shares <span style="font-size:0.7em;">[<a href="./view">done</a>]</span></h2> | ||
|
||
<ul> | ||
{% for keyshare in keyshares %} | ||
<li> <tt>{{keyshare.email}}</tt> — | ||
{% if keyshare.public_key %} | ||
public key submitted | ||
{% else %} | ||
waiting for public key | ||
{% endif %} | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
|
||
{% if ready_p %} | ||
Ready to combine into one public key.<br /><br /> | ||
<button onclick="combine_keys(); return false;">Combine Keys</button> | ||
{% else %} | ||
Not ready. | ||
{% endif %} | ||
|
||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,177 @@ | ||
{% extends "base.html" %} | ||
{% block content %} | ||
<script language="javascript"> | ||
Helios.setup(); | ||
|
||
ELECTION_PK = ElGamal.PublicKey.fromJSONObject({{election_pk_json|safe}}); | ||
|
||
function load_election_and_ballots(election_id) { | ||
// BALLOTS by voter key | ||
ELECTION = null; | ||
ELECTION_ID = election_id; | ||
BALLOTS = {}; | ||
BALLOTS_LOADED = {}; | ||
VOTER_LIST = []; | ||
TRUSTEES = null; | ||
|
||
// get the election data | ||
Helios.get_election({'election_id' : election_id}, function(election_json) { | ||
var election = HELIOS.Election.fromJSONObject(election_json); | ||
ELECTION = election; | ||
|
||
// get the trustees | ||
Helios.get_election_trustees({'election_id' : election_id}, function(trustees) { | ||
TRUSTEES= trustees; | ||
|
||
// get the voters | ||
Helios.get_election_voters({'election_id' : election_id}, function(voters) { | ||
VOTER_LIST = voters; | ||
$(voters).each(function(v_num, v) { | ||
// download each voter's data, stuffing into BALLOTS | ||
Helios.get_election_voter({'election_id' : election_id, 'voter_id' : v.voter_id}, function(voter) { | ||
BALLOTS[voter.voter_id] = HELIOS.EncryptedVote.fromJSONObject(voter.vote, ELECTION); | ||
BALLOTS_LOADED[voter.voter_id] = true; | ||
}); | ||
}); | ||
|
||
when_ready_verify_ballots_and_tally(); | ||
}); | ||
}) | ||
}); | ||
} | ||
|
||
function when_ready_verify_ballots_and_tally() { | ||
var tally = verify_ballots_and_tally(); | ||
|
||
if (!tally) { | ||
setTimeout('when_ready_verify_ballots_and_tally()', 2000); | ||
} else { | ||
// store the tally | ||
$.post('/elections/{{election.election_id}}/set_tally', {tally: jQuery.toJSON(tally)}, function(result) { | ||
if (result == "SUCCESS") { | ||
alert('tally computed and uploaded'); | ||
document.location = "./view" | ||
} | ||
}); | ||
} | ||
} | ||
|
||
var NUM_VOTES = 0; | ||
|
||
function increment_vote_tally_count() { | ||
NUM_VOTES += 1; | ||
$('#num_votes').html(NUM_VOTES); | ||
} | ||
|
||
function verify_ballots_and_tally() { | ||
// check that ballots are here | ||
for (var i=0; i<VOTER_LIST.length; i++) { | ||
if (BALLOTS_LOADED[VOTER_LIST[i].voter_id] == null) { | ||
// not all ballots have been downloaded | ||
return false; | ||
} | ||
} | ||
|
||
// initialize the tallies | ||
var TALLY = []; | ||
$(ELECTION.questions).each(function(qnum, q) { | ||
TALLY[qnum] = $(q.answers).map(function(anum, a) { | ||
return 1; | ||
}); | ||
}); | ||
|
||
// voter hashes | ||
var voters = []; | ||
|
||
var VALID_P = true; | ||
|
||
// we need to keep track of the values of g^{voter_num} for decryption | ||
var DISCRETE_LOGS = {}; | ||
var CURRENT_EXP = 0; | ||
var CURRENT_RESULT = BigInt.ONE; | ||
DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP; | ||
|
||
// all ballots are here | ||
$(VOTER_LIST).each(function(vnum, voter) { | ||
var ballot = BALLOTS[voter.voter_id]; | ||
|
||
// non-voter? | ||
if (ballot == null) { | ||
return; | ||
} | ||
|
||
// this ballot will count, so let's increment the discrete log pre-computation mapping. | ||
CURRENT_EXP += 1; | ||
CURRENT_RESULT = CURRENT_RESULT.multiply(ELECTION.pk.g).mod(ELECTION.pk.p); | ||
DISCRETE_LOGS[CURRENT_RESULT.toString()] = CURRENT_EXP; | ||
|
||
var voter_hash = ballot.get_hash(); | ||
|
||
// verify the ballot | ||
var this_vote_result = ballot.verifyProofs(ELECTION.pk, function(answer_num, choice_num, result, choice) { | ||
if (choice_num != null) { | ||
// keep track of tally | ||
TALLY[answer_num][choice_num] = choice.multiply(TALLY[answer_num][choice_num]); | ||
} | ||
}); | ||
|
||
VALID_P = VALID_P && this_vote_result; | ||
|
||
increment_vote_tally_count(); | ||
}); | ||
|
||
// are we okay? | ||
if (!VALID_P) | ||
return false; | ||
|
||
var result= []; | ||
|
||
// apply the decryption factors | ||
$(TALLY).each(function(q_num, q_tally) { | ||
result[q_num] = []; | ||
$(q_tally).each(function(choice_num, choice_tally) { | ||
var decryption_factors = []; | ||
$(TRUSTEES).each(function(i, trustee) { | ||
decryption_factors.push(BigInt.fromJSONObject(trustee.decryption_factors[q_num][choice_num])); | ||
}); | ||
|
||
// apply the keyshares decryption factors | ||
var one_choice_result = choice_tally.decrypt(decryption_factors); | ||
|
||
result[q_num][choice_num] = DISCRETE_LOGS[one_choice_result.getM().toString()]; | ||
}); | ||
}); | ||
|
||
return {'result': result, 'result_proof' : null}; | ||
} | ||
|
||
function do_tally() { | ||
load_election_and_ballots('{{election.election_id}}'); | ||
} | ||
</script> | ||
|
||
<h2 class="title">{{election.name}} — Trustee Tallying <span style="font-size:0.7em;">[<a href="./view">done</a>]</span></h2> | ||
|
||
<ul> | ||
{% for keyshare in keyshares %} | ||
<li> <tt>{{keyshare.email}}</tt> — | ||
{% if keyshare.decryption_factors %} | ||
decryption factors submitted | ||
{% else %} | ||
waiting for decryption factors | ||
{% endif %} | ||
</li> | ||
{% endfor %} | ||
</ul> | ||
|
||
{% if ready_p %} | ||
Ready to combine decryption factors and compute tally.<br /><br /> | ||
<p align="center" style="font-size:16pt;"> | ||
<span id="num_votes">0</span> tallied. | ||
</p> | ||
<button onclick="do_tally(); return false;">Compute Tally</button> | ||
{% else %} | ||
Not ready for tallying. | ||
{% endif %} | ||
|
||
{% endblock %} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.