From 7640eab9aa9269cf2ad2785563d1dc343d748c9a Mon Sep 17 00:00:00 2001 From: Ben Adida Date: Sun, 4 Jan 2009 23:21:32 -0800 Subject: [PATCH] fixed python verification and added support for min and max, added some debugging --- client/heliosclient.py | 10 ++++--- crypto/electionalgs.py | 53 +++++++++++++++++++++++++++++++------ helios/templates/index.html | 4 +-- tests/heliosclient.py | 9 ++++--- 4 files changed, 60 insertions(+), 16 deletions(-) diff --git a/client/heliosclient.py b/client/heliosclient.py index 705df33..9c340e6 100644 --- a/client/heliosclient.py +++ b/client/heliosclient.py @@ -10,19 +10,23 @@ from crypto import algs, electionalgs class HeliosClient(object): - def __init__(self, auth_info, host, port): + def __init__(self, auth_info, host, port, prefix=""): """ auth_info is consumer_key, .... """ self.consumer = oauth.OAuthConsumer(auth_info['consumer_key'],auth_info['consumer_secret']) self.token = oauth.OAuthToken(auth_info['consumer_key'],auth_info['consumer_secret']) self.client = oauthclient.MachineOAuthClient(self.consumer, self.token, host, port) + self.prefix = prefix def get(self, url, parameters = None): - return self.client.access_resource("GET", url, parameters= parameters) + print "getting " + self.prefix + url + return self.client.access_resource("GET", self.prefix + url, parameters= parameters) def post(self, url, parameters = None): - return self.client.access_resource("POST", url, parameters= parameters) + print "posting " + self.prefix + url + result = self.client.access_resource("POST", self.prefix + url, parameters= parameters) + return result def params(self): params_json = self.get("/elections/params") diff --git a/crypto/electionalgs.py b/crypto/electionalgs.py index ceae2a6..323d689 100644 --- a/crypto/electionalgs.py +++ b/crypto/electionalgs.py @@ -20,10 +20,27 @@ def __init__(self, choices=None, individual_proofs=None, overall_proof=None, ran self.overall_proof = overall_proof self.randomness = randomness - def verify(self, pk): - possible_plaintexts = [algs.EGPlaintext(1, pk), algs.EGPlaintext(pk.g, pk)] - homomorphic_sum = 0 + @classmethod + def generate_plaintexts(cls, pk, min=0, max=1): + plaintexts = [] + running_product = 1 + + # run the product up to the min + for i in range(max+1): + # if we're in the range, add it to the array + if i >= min: + plaintexts.append(algs.EGPlaintext(running_product, pk)) + + # next value in running product + running_product = (running_product * pk.g) % pk.p + + return plaintexts + + def verify(self, pk, min=0, max=1): + possible_plaintexts = self.generate_plaintexts(pk) + homomorphic_sum = 0 + for choice_num in range(len(self.choices)): choice = self.choices[choice_num] choice.pk = pk @@ -36,8 +53,11 @@ def verify(self, pk): # compute homomorphic sum homomorphic_sum = choice * homomorphic_sum + # determine possible plaintexts for the sum + sum_possible_plaintexts = self.generate_plaintexts(pk, min=min, max=max) + # verify the sum - return homomorphic_sum.verify_disjunctive_encryption_proof(possible_plaintexts, self.overall_proof, algs.EG_disjunctive_challenge_generator) + return homomorphic_sum.verify_disjunctive_encryption_proof(sum_possible_plaintexts, self.overall_proof, algs.EG_disjunctive_challenge_generator) def toJSONDict(self): return { @@ -78,7 +98,7 @@ def fromElectionAndAnswer(cls, election, question_num, answer_indexes): randomness = [None for a in range(len(answers))] # possible plaintexts [0, 1] - plaintexts = [algs.EGPlaintext(1, pk), algs.EGPlaintext(pk.g, pk)] + plaintexts = cls.generate_plaintexts(pk) # keep track of number of options selected. num_selected_answers = 0; @@ -110,7 +130,18 @@ def fromElectionAndAnswer(cls, election, question_num, answer_indexes): # prove that the sum is 0 or 1 (can be "blank vote" for this answer) # num_selected_answers is 0 or 1, which is the index into the plaintext that is actually encoded - overall_proof = homomorphic_sum.generate_disjunctive_encryption_proof(plaintexts, num_selected_answers, randomness_sum, algs.EG_disjunctive_challenge_generator); + min_answers = 0 + if question.has_key('min'): + min_answers = question['min'] + max_answers = question['max'] + + if num_selected_answers < min_answers: + raise Exception("Need to select at least %s answer(s)" % min_answers) + + sum_plaintexts = cls.generate_plaintexts(pk, min=min_answers, max=max_answers) + + # need to subtract the min from the offset + overall_proof = homomorphic_sum.generate_disjunctive_encryption_proof(sum_plaintexts, num_selected_answers - min_answers, randomness_sum, algs.EG_disjunctive_challenge_generator); return cls(choices, individual_proofs, overall_proof, randomness) @@ -138,8 +169,14 @@ def verify(self, election): return False # check proofs on all of answers - for ea in self.encrypted_answers: - if not ea.verify(election.pk): + for question_num in range(len(election.questions)): + ea = self.encrypted_answers[question_num] + question = election.questions[question_num] + min_answers = 0 + if question.has_key('min'): + min_answers = question['min'] + + if not ea.verify(election.pk, min=min_answers, max=question['max']): return False return True diff --git a/helios/templates/index.html b/helios/templates/index.html index 23296c9..9992ba6 100644 --- a/helios/templates/index.html +++ b/helios/templates/index.html @@ -17,12 +17,12 @@

- Check out our Frequently Asked Questions. + Check out our Frequently Asked Questions.



-Create an Open-Audit Election

+Create an Open-Audit Election

{% endblock %} \ No newline at end of file diff --git a/tests/heliosclient.py b/tests/heliosclient.py index 4f68d2e..8e9c587 100644 --- a/tests/heliosclient.py +++ b/tests/heliosclient.py @@ -16,7 +16,10 @@ # modify variables here helios = heliosclient.HeliosClient({'consumer_key': 'test', 'consumer_secret': '123'}, host = '174.129.241.146', - port = 80) +# host = "localhost", + port = 80, + prefix = "/helios" + ) # get the El Gamal Parameters params = helios.params() @@ -33,7 +36,7 @@ helios.election_set_reg(election_id, open_reg= True) # set questions -questions = [{"answers": ["ice-cream", "cake"], "max": 1, "question": "ice-cream or cake?", "short_name": "dessert"}] +questions = [{"answers": ["ice-cream", "cake"], "min": 1, "max": 1, "question": "ice-cream or cake?", "short_name": "dessert"}] helios.election_questions_save(election_id, questions) # freeze it @@ -48,7 +51,7 @@ # create three ballots ballot_1 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) ballot_2 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) -ballot_3 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[0]]) +ballot_3 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[]]) print "created 3 ballots"