Skip to content

Commit

Permalink
removed election_type, added ballot_type and tally_type and added way…
Browse files Browse the repository at this point in the history
…s to create such elections and checks to ensure verification is of the right type.
  • Loading branch information
benadida committed Jan 7, 2009
1 parent a515c97 commit 9972628
Show file tree
Hide file tree
Showing 11 changed files with 83 additions and 24 deletions.
4 changes: 2 additions & 2 deletions client/heliosclient.py
Expand Up @@ -35,8 +35,8 @@ def params(self):
params_json = self.get("/elections/params")
return algs.ElGamal.fromJSONDict(utils.from_json(params_json))

def election_new(self, name, public_key):
election_id = self.post("/elections/new_3", {"name" : name, "public_key" : utils.to_json(public_key.toJSONDict())})
def election_new(self, name, public_key, ballot_type = 'homomorphic', tally_type = 'homomorphic'):
election_id = self.post("/elections/new_3", {"name" : name, "public_key" : utils.to_json(public_key.toJSONDict()), "ballot_type": ballot_type, "tally_type": tally_type})
return election_id

def election_get(self, election_id):
Expand Down
6 changes: 6 additions & 0 deletions crypto/electionalgs.py
Expand Up @@ -220,6 +220,8 @@ def __init__(self):
self.voting_starts_at = None
self.voting_ends_at = None
self.openreg = False
self.ballot_type = False
self.tally_type = False

def init_tally(self):
return Tally(self)
Expand All @@ -231,10 +233,12 @@ def get_hash(self):

def toJSONDict(self):
return_value = {
'ballot_type' : self.ballot_type,
'election_id' : self.election_id,
'name' : self.name,
'public_key' : self.pk.toJSONDict(),
'questions' : self.questions,
'tally_type' : self.tally_type,
'voting_starts_at' : self.voting_starts_at,
'voting_ends_at' : self.voting_ends_at
}
Expand All @@ -256,6 +260,8 @@ def fromJSONDict(cls, d):
el.voting_starts_at = d['voting_starts_at']
el.voting_ends_at = d['voting_ends_at']
el.questions = d['questions']
el.ballot_type = d['ballot_type']
el.tally_type = d['tally_type']

if d['public_key']:
el.pk = algs.EGPublicKey.fromJSONDict(d['public_key'])
Expand Down
2 changes: 1 addition & 1 deletion helios/json.py
Expand Up @@ -130,4 +130,4 @@ def toJSONRecurse(item):

def toJSON(self):
# FIXME: factor in the JSON_FIELDS for the class
return json.dumps(self.toJSONDict())
return dumps(self.toJSONDict())
7 changes: 4 additions & 3 deletions helios/models.py
Expand Up @@ -17,7 +17,7 @@

class Election(models.Model, JSONObject):
# when JSON'ified
JSON_FIELDS = ['election_id', 'name', 'public_key', 'questions', 'voters_hash', 'openreg', 'voting_starts_at', 'voting_ends_at']
JSON_FIELDS = ['ballot_type', 'election_id', 'name', 'public_key', 'questions', 'tally_type', 'voters_hash', 'openreg', 'voting_starts_at', 'voting_ends_at']

election_id = models.AutoField(primary_key=True)

Expand Down Expand Up @@ -52,8 +52,9 @@ class Election(models.Model, JSONObject):
# decryption proof, a JSON object
decryption_proof = JSONField(null=True)

# type of election (homomorphic, mixnet, possibly with more detail)
election_type = models.CharField(max_length=300, default='homomorphic')
# type of election
ballot_type = models.CharField(max_length=300, default='homomorphic')
tally_type = models.CharField(max_length=300, default='homomorphic')

def toJSONDict(self):
# JSON fields, no need!
Expand Down
9 changes: 7 additions & 2 deletions helios/templates/ballot_verifier.html
Expand Up @@ -34,12 +34,17 @@
var encrypted_vote_json = jQuery.secureEvalJSON(audit_trail);

// go get the election
Helios.get_election({'election_id' : encrypted_vote_json.election_id}, function(election_json) {
Helios.get_election({'election_id' : encrypted_vote_json.election_id}, function(election_json, election_raw_json) {
// display election fingerprint
var election = HELIOS.Election.fromJSONObject(election_json);
var election = HELIOS.Election.fromJSONString(election_raw_json);
var election_hash = election.get_hash();
result_append("election fingerprint is " + election_hash);

// check if the election ballot_type is homomorphic
if (election.ballot_type != "homomorphic") {
result_append("WARNING: the ballot type for this election is not homomorphic. Verification may fail because this verifier is only set up to handle homomorphic ballots.");
}

// display ballot fingerprint
encrypted_vote = HELIOS.EncryptedVote.fromJSONObject(encrypted_vote_json, election);
result_append("ballot fingerprint is " + encrypted_vote.get_hash());
Expand Down
13 changes: 13 additions & 0 deletions helios/templates/election_view.html
Expand Up @@ -40,9 +40,17 @@ <h3>Administration</h3>
{% else %}
{% if election.in_progress_p %}
{% if election.get_sk %}
{% ifequal election.tally_type "homomorphic" %}
<li> <a href="{% url helios.views.one_election_drive_tally_chunk election_id=election.election_id %}">compute tally</a></li>
{% else %}
<li> custom tally</li>
{% endifequal %}
{% else %}
{% ifequal election.tally_type "homomorphic" %}
<li> <a href="{% url helios.views.one_election_drive_tally election_id=election.election_id %}">compute tally</a></li>
{% else %}
<li> custom tally</li>
{% endifequal %}
{% endif %}
{% endif %}
{% endif %}
Expand Down Expand Up @@ -101,7 +109,12 @@ <h2>Tally</h2>
</ul>
{% endfor %}

{% ifequal election.tally_type "homomorphic" %}
<a style="font-size: 14pt;" target="_blank" href="{% url helios.views.election_verifier %}">Audit the Election Tally</a><br />
{% else %}
<b>This election uses a custom tallying mechanism, which must be audited by the custom code.</b>
{% endifequal %}

<br /><br />
{% endif %}

Expand Down
9 changes: 7 additions & 2 deletions helios/templates/tally_verifier.html
Expand Up @@ -40,11 +40,16 @@
VOTER_LIST = [];

// get the election data
Helios.get_election({'election_id' : election_id}, function(election_json) {
var election = HELIOS.Election.fromJSONObject(election_json);
Helios.get_election({'election_id' : election_id}, function(election_json, election_raw_json) {
var election = HELIOS.Election.fromJSONString(election_raw_json);
ELECTION = election;
result_append("Election: " + election.name);

if (election.tally_type != "homomorphic") {
result_append("PROBLEM: this election is not a straight-forward homomorphic-tally election. As a result, Helios cannot currently verify it.");
return;
}

// hash it
var election_hash = election.get_hash();
result_append("Fingerprint: " + election_hash);
Expand Down
7 changes: 3 additions & 4 deletions helios/templates/vote.html
Expand Up @@ -51,10 +51,9 @@ <h3>Fingerprint: <span id="election_hash"></span></h3>
};

BOOTH.setup_election = function(election, raw_json) {
BOOTH.election = HELIOS.Election.fromJSONObject(election);

// compute the hash from the raw JSON
BOOTH.election_hash = b64_sha1(raw_json);
// use the raw JSON for safer hash computation
BOOTH.election = HELIOS.Election.fromJSONString(raw_json);
BOOTH.election_hash = BOOTH.election.get_hash();

$('#election_hash').html(BOOTH.election_hash);

Expand Down
14 changes: 12 additions & 2 deletions helios/views.py
Expand Up @@ -105,6 +105,11 @@ def election_new_3(request):
voting_starts_at = request.POST.get('voting_starts_at', None)
voting_ends_at = request.POST.get('voting_ends_at', None)

# election type is homomorphic. The type of the election determines
# how votes are tallied and verified.
ballot_type = request.POST.get('ballot_type', 'homomorphic')
tally_type = request.POST.get('tally_type', 'homomorphic')

# we need a list of admins, or at least a public key
if len(trustee) == 0 and not public_key:
return HttpResponseServerError('Need a list of trustees or a public key')
Expand All @@ -120,7 +125,7 @@ def election_new_3(request):
else:
sk = None

election = Election.objects.create(election_type = 'homomorphic', name = name,
election = Election.objects.create(ballot_type = ballot_type, tally_type = tally_type, name = name,
admin = get_user(request), api_client= get_api_client(request),
# voting_starts_at = utils.string_to_datetime(voting_starts_at),
# voting_ends_at = utils.string_to_datetime(voting_ends_at),
Expand Down Expand Up @@ -509,13 +514,19 @@ def one_election_email_trustees(request, election):

@election_admin(frozen=True)
def one_election_compute_tally(request, election):
if election.tally_type != "homomorphic":
return HttpResponseRedirect(reverse(one_election_view,args=[election.election_id]))

return HttpResponse("election compute tally %s" % election.election_id)

@election_admin(frozen=True)
def one_election_drive_tally(request, election):
"""
JavaScript-based driver for the entire tallying process, now done in JavaScript.
"""
if election.tally_type != "homomorphic":
return HttpResponseRedirect(reverse(one_election_view,args=[election.election_id]))

election_pk = election.public_key
election_pk_json = utils.to_json(election_pk.toJSONDict())

Expand Down Expand Up @@ -586,7 +597,6 @@ def one_voter_delete(request, election, voter_id):

@election_view(frozen=True)
def one_voter_submit(request, election, voter_id):
import pdb; pdb.set_trace()
election_obj = election.toElection()

# this will raise an exception if the voter is bad
Expand Down
28 changes: 24 additions & 4 deletions static/helios.js
Expand Up @@ -72,18 +72,24 @@ HELIOS.Election = Class.extend({
// in terms of ordering the keys. FIXME: get a JSON library that orders keys properly.
if (this.openreg) {
return {
election_id : this.election_id, name : this.name, openreg: true, public_key: this.pk.toJSONObject(), questions : this.questions,
voting_ends_at : this.voting_ends_at, voting_starts_at : this.voting_starts_at
ballot_type: this.ballot_type, election_id : this.election_id,
name : this.name, openreg: true, public_key: this.pk.toJSONObject(), questions : this.questions,
tally_type: this.tally_type, voting_ends_at : this.voting_ends_at, voting_starts_at : this.voting_starts_at
};
} else {
return {
election_id : this.election_id, name : this.name, public_key: this.pk.toJSONObject(), questions : this.questions,
voters_hash : this.voters_hash, voting_ends_at : this.voting_ends_at, voting_starts_at : this.voting_starts_at
ballot_type: this.ballot_type, election_id : this.election_id,
name : this.name, public_key: this.pk.toJSONObject(), questions : this.questions,
tally_type: this.tally_type, voters_hash : this.voters_hash, voting_ends_at : this.voting_ends_at, voting_starts_at : this.voting_starts_at
};
}
},

get_hash: function() {
if (this.election_hash)
return this.election_hash;

// otherwise
return b64_sha1(this.toJSON());
},

Expand All @@ -93,12 +99,26 @@ HELIOS.Election = Class.extend({
}
});

HELIOS.Election.fromJSONString = function(raw_json) {
var json_object = $.secureEvalJSON(raw_json);

// hash fix for the issue with re-json'ifying unicode chars
var election = HELIOS.Election.fromJSONObject(json_object);
election.election_hash = b64_sha1(raw_json);

return election;
};

HELIOS.Election.fromJSONObject = function(d) {
var el = new HELIOS.Election();
el.election_id = d.election_id;
el.name = d.name; el.voters_hash = d.voters_hash; el.voting_starts_at = d.voting_starts_at; el.voting_ends_at = d.voting_ends_at;
el.questions = d.questions;

// stuff about the election
el.ballot_type = d.ballot_type;
el.tally_type = d.tally_type;

// empty questions
if (!el.questions)
el.questions = [];
Expand Down
8 changes: 4 additions & 4 deletions tests/heliosclient.py
Expand Up @@ -15,10 +15,10 @@
# instantiate the client
# modify variables here
helios = heliosclient.HeliosClient({'consumer_key': 'test', 'consumer_secret': '123'},
host = '174.129.241.146',
# host = "localhost",
port = 80,
prefix = "/helios"
# host = '174.129.241.146',
host = "localhost",
port = 8000,
# prefix = "/helios"
)

print "headers:\n"
Expand Down

0 comments on commit 9972628

Please sign in to comment.