Skip to content

Commit

Permalink
added trustee support back
Browse files Browse the repository at this point in the history
  • Loading branch information
benadida committed Jan 6, 2009
1 parent 7640eab commit e31d58b
Show file tree
Hide file tree
Showing 11 changed files with 657 additions and 25 deletions.
2 changes: 1 addition & 1 deletion helios/election_urls.py
Expand Up @@ -27,7 +27,7 @@
(r'^bboard$', one_election_bboard),

# construct election
# (r'^set_pk$', one_election_set_pk),
(r'^set_pk$', one_election_set_pk),
(r'^voters_manage$', one_election_voters_manage),
(r'^voters_bulk_upload$', one_election_voters_bulk_upload),
(r'^voters_delete$', one_election_voters_delete),
Expand Down
6 changes: 3 additions & 3 deletions helios/models.py
Expand Up @@ -444,13 +444,13 @@ def get_by_consumer_key(cls, consumer_key):
## Distributed Decryption
##

class KeyShare(models.Model):
JSON_FIELDS = ['email','pk','pok', 'decryption_factors', 'decryption_proofs']
class KeyShare(models.Model, JSONObject):
JSON_FIELDS = ['email','public_key','pok', 'decryption_factors', 'decryption_proofs']

keyshare_id = models.AutoField(primary_key = True)

election = models.ForeignKey(Election)
pk = JSONField(null=True)
public_key = JSONField(json_obj_class = algs.EGPublicKey, null=True)
pok = JSONField(null=True)
email = models.EmailField()
password = models.CharField(max_length=50, null=True)
Expand Down
2 changes: 1 addition & 1 deletion helios/templates/election_new_2.html
Expand Up @@ -39,7 +39,7 @@
}

$(document).ready(function() {
{% ifnotequal election_tpe "multiple" %}
{% ifnotequal election_type "multiple" %}
$('#submit').hide();
{% endifnotequal %}
$('#sk_form').hide();
Expand Down
57 changes: 57 additions & 0 deletions helios/templates/email_trustees.html
@@ -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 &mdash; 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 %}
48 changes: 48 additions & 0 deletions helios/templates/keyshares_manage.html
@@ -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}} &mdash; 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> &mdash;
{% 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 %}
177 changes: 177 additions & 0 deletions helios/templates/keyshares_tally_manage.html
@@ -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}} &mdash; 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> &mdash;
{% 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 %}
6 changes: 3 additions & 3 deletions helios/templates/tally_verifier.html
Expand Up @@ -159,13 +159,13 @@

// verify the keys
$(trustees).each(function(i, trustee) {
if (trustee.pk.verifyKnowledgeOfSecretKey(trustee.pok, ElGamal.fiatshamir_dlog_challenge_generator)) {
if (trustee.public_key.verifyKnowledgeOfSecretKey(trustee.pok, ElGamal.fiatshamir_dlog_challenge_generator)) {
result_append("Trustee PK for " + trustee.email + " VERIFIED.");
} else {
result_append("==== ERROR for PK of trustee " + trustee.email);
}

combined_key = trustee.pk.multiply(combined_key);
combined_key = trustee.public_key.multiply(combined_key);
});

// verify the combination of the keys into the final public key
Expand All @@ -184,7 +184,7 @@
var decryption_factors = [];
// go through the trustees' decryption factors
$(trustees).each(function(t_num, trustee) {
if (trustee.pk.verifyDecryptionFactor(a, trustee.decryption_factors[q_num][a_num],
if (trustee.public_key.verifyDecryptionFactor(a, trustee.decryption_factors[q_num][a_num],
trustee.decryption_proofs[q_num][a_num], ElGamal.fiatshamir_challenge_generator)) {
result_append("-- Trustee " + trustee.email + " decryption factor verifies");
} else {
Expand Down

0 comments on commit e31d58b

Please sign in to comment.