def public_key_form(request): if request.method == "POST": # get the public key and the hash, and add it key = Key() key.name = request.POST['name'] key.email = request.POST['email'] public_key_and_proof_enc = utils.from_json( request.POST['public_key_json_enc']) public_key_enc = algs.EGPublicKey.fromJSONDict( public_key_and_proof_enc['public_key']) pok_enc = algs.DLogProof.fromJSONDict(public_key_and_proof_enc['pok']) # verify the pok if not public_key_enc.verify_sk_proof(pok_enc, algs.DLog_challenge_generator): raise Exception("bad pok for public key encrypting") key.public_key_encrypt = utils.to_json(public_key_enc.to_dict()) key.pok_encrypt = utils.to_json(pok_enc.to_dict()) key.public_key_encrypt_hash = cryptoutils.hash_b64( key.public_key_encrypt) public_key_and_proof_sign = utils.from_json( request.POST['public_key_json_sign']) public_key_sign = algs.EGPublicKey.fromJSONDict( public_key_and_proof_sign['public_key']) pok_sign = algs.DLogProof.fromJSONDict( public_key_and_proof_sign['pok']) # verify the pok if not public_key_sign.verify_sk_proof(pok_sign, algs.DLog_challenge_generator): raise Exception("bad pok for public key signing") key.public_key_signing = utils.to_json(public_key_sign.to_dict()) key.pok_signing = utils.to_json(pok_sign.to_dict()) key.public_key_signing_hash = cryptoutils.hash_b64( key.public_key_signing) key.save() # send a note to admin try: election.admin.send_message( "pk upload, " + "%s uploaded a pk for communication." % (key.name)) except: # oh well, no message sent pass return HttpResponseRedirect('/bulletin_board/') """ A key generator with the current params, like the trustee home but without a specific election. """ eg_params_json = utils.to_json(ELGAMAL_PARAMS_LD_OBJECT.toJSONDict()) return render_template(request, "election_publickeygenerator", {'eg_params_json': eg_params_json})
def download_data(request, election_id, receiver_id): election = Election.objects.get(id=election_id) scheme = Thresholdscheme.objects.get(election=election) n = scheme.n k = scheme.k shares_list = Signed_Encrypted_Share.objects.filter( election_id=election_id).filter(receiver_id=receiver_id).order_by('signer_id') trustees = Trustee.objects.filter(election=election) if (len(trustees) == scheme.n): pk_list_string = [] for i in range(len(trustees)): pk_list_string.append(trustees[i].key) else: pk_list_string = None pk_list = [] pk_id_list = [] for i in range(len(pk_list_string)): pk_list.append(elgamal.PublicKey.from_dict( utils.from_json(pk_list_string[i].public_key_signing))) pk_id_list.append(pk_list_string[i].id) string = '' string = string + utils.to_json({'p': p, 'q': q, 'g': g, 'ground_1': scheme.ground_1, 'ground_2': scheme.ground_2, 'k': scheme.k, 'n': n}) + '\n' for i in range(len(pk_list)): string = string + str(pk_id_list[i]) + '\n' string = string + utils.to_json(pk_list[i].to_dict()) + '\n' for i in range(len(shares_list)): share = shares_list[i] string = string + utils.to_json({'share': share.share, 'election_id': share.election_id, 'signer': share.signer, 'signer_id': share.signer_id, 'receiver': share.receiver, 'receiver_id': share.receiver_id}) string = string + '\n' file = open( 'bulletin_board/files/data_receiver_' + str(receiver_id) + '.txt', "w") file.write(string) file.close() file = open( 'bulletin_board/files/data_receiver_' + str(receiver_id) + '.txt', "r") mimetype = mimetypes.guess_type( 'data_receiver_' + str(receiver_id) + '.txt')[0] if not mimetype: mimetype = "application/octet-stream" response = HttpResponse(file.read(), mimetype=mimetype) response[ "Content-Disposition"] = "attachment; filename=%s" % os.path.split('data_receiver.txt')[1] return response
def trustee_upload_pk(request, election, trustee): if request.method == "POST": # get the public key and the hash, and add it public_key_and_proof = utils.from_json(request.POST['public_key_json']) trustee.public_key = algs.EGPublicKey.fromJSONDict( public_key_and_proof['public_key']) trustee.pok = algs.DLogProof.fromJSONDict(public_key_and_proof['pok']) # verify the pok if not trustee.public_key.verify_sk_proof(trustee.pok, algs.DLog_challenge_generator): raise Exception("bad pok for this public key") trustee.public_key_hash = utils.hash_b64( utils.to_json(trustee.public_key.toJSONDict())) trustee.save() # send a note to admin try: election.admin.send_message( "%s - trustee pk upload" % election.name, "trustee %s (%s) uploaded a pk." % (trustee.name, trustee.email)) except: # oh well, no message sent pass return HttpResponseRedirect(reverse(trustee_home, args=[election.uuid, trustee.uuid]))
def convert_to_json(self, *args, **kwargs): return_val = func(self, *args, **kwargs) try: return render_json(utils.to_json(return_val)) except Exception, e: import logging logging.error( "problem with serialization: " + str(return_val) + " / " + str(e)) raise e
def election_new(self, name, public_key=None, ballot_type = 'homomorphic', tally_type = 'homomorphic', trustee_list=None): args = {"name" : name, "ballot_type": ballot_type, "tally_type": tally_type} if public_key: args['public_key'] = utils.to_json(public_key.toJSONDict()) if trustee_list: args['trustee_list'] = ",".join(trustee_list) election_id = self.post("/elections/new_3", args) return election_id
def add_encrypted_shares_js(request, election_id, signer_id): election = Election.objects.get(id=election_id) trustees = Trustee.objects.filter(election=election) scheme = Thresholdscheme.objects.get(election=election) SCHEME_PARAMS_LD_OBJECT = datatypes.LDObject.instantiate( scheme, datatype='legacy/Thresholdscheme') scheme_params_json = utils.to_json(SCHEME_PARAMS_LD_OBJECT.toJSONDict()) # if request.method == 'POST': # Create dictionary with all public_keys eg_params_json = utils.to_json(ELGAMAL_PARAMS_LD_OBJECT.toJSONDict()) pk_encrypt_dict = {} pk_signing_dict = {} name_dict = {} id_dict = {} trustee_ids_dict = {} email_dict = {} pok_encrypt_dict = {} pok_signing_dict = {} pk_encrypt_hash_dict = {} pk_signing_hash_dict = {} for i in range(len(trustees)): key = Key.objects.get(id=trustees[i].key_id) id_dict[str(i)] = key.id corresponding_trustee = Trustee.objects.filter(key=key)[0] trustee_ids_dict[str(i)] = corresponding_trustee.id name_dict[str(i)] = key.name email_dict[str(i)] = key.email pok_encrypt_dict[str(i)] = key.pok_encrypt pok_signing_dict[str(i)] = key.pok_signing pk_encrypt_hash_dict[str(i)] = key.public_key_encrypt_hash pk_signing_hash_dict[str(i)] = key.public_key_signing_hash pk_encrypt_dict[str(i)] = key.public_key_encrypt pk_signing_dict[str(i)] = key.public_key_signing return render_template_threshold(request, '../create_encrypted_shares', {"election_id": election_id, "signer_id": signer_id, "election": election, "trustees": trustees, "trustee_ids_dict": trustee_ids_dict, "scheme_params_json": scheme_params_json, "id_dict": id_dict, "name_dict": utils.to_json(name_dict), "email_dict": utils.to_json(email_dict), "pok_encrypt_dict": utils.to_json(pok_encrypt_dict), "pok_signing_dict": utils.to_json(pok_signing_dict), "pk_encrypt_hash_dict": utils.to_json(pk_encrypt_hash_dict), "pk_signing_hash_dict": utils.to_json(pk_signing_hash_dict), "pk_encrypt_dict": utils.to_json(pk_encrypt_dict), "pk_signing_dict": utils.to_json(pk_signing_dict), "eg_params_json": eg_params_json})
def generate_voters_hash(self): """ look up the list of voters, make a big file, and hash it """ # FIXME: for now we don't generate this voters hash: return if self.openreg: self.voters_hash = None else: voters = Voter.get_by_election(self) voters_json = utils.to_json([v.toJSONDict() for v in voters]) self.voters_hash = hash_b64(voters_json)
def _cast_vote(self, election, voter, answers): answers = [answers] self._setup_voter_login(voter) response = self.app.post("/helios/elections/%s/encrypt-ballot" % election.uuid, { 'answers_json': utils.to_json(answers)}) self.assertContains(response, "answers") # parse it as an encrypted vote with randomness, and make sure randomness is there the_ballot = utils.from_json(response.testbody) assert the_ballot['answers'][0].has_key('randomness'), "no randomness" # parse it as an encrypted vote, and re-serialize it ballot = datatypes.LDObject.fromDict(utils.from_json(response.testbody), 'phoebus/EncryptedVote') encrypted_vote = ballot.serialize() response = self.app.post("/helios/elections/%s/cast" % election.uuid, { 'encrypted_vote': encrypted_vote}) response = self.app.get("/helios/elections/%s/cast_confirm" % election.uuid) response.form.submit() response = self.app.get("/helios/elections/%s/cast_done" % election.uuid)
def _cast_vote(self, election, voter, answers): answers = [answers] self._setup_voter_login(voter) response = self.app.post( "/helios/elections/%s/encrypt-ballot" % election.uuid, {'answers_json': utils.to_json(answers)}) self.assertContains(response, "answers") # parse it as an encrypted vote with randomness, and make sure randomness is there the_ballot = utils.from_json(response.testbody) assert the_ballot['answers'][0].has_key('randomness'), "no randomness" # parse it as an encrypted vote, and re-serialize it ballot = datatypes.LDObject.fromDict( utils.from_json(response.testbody), 'phoebus/EncryptedVote') encrypted_vote = ballot.serialize() response = self.app.post("/helios/elections/%s/cast" % election.uuid, {'encrypted_vote': encrypted_vote}) response = self.app.get("/helios/elections/%s/cast_confirm" % election.uuid) response.form.submit() response = self.app.get("/helios/elections/%s/cast_done" % election.uuid)
for i in range(100): # random choice for the ballot choice = algs.Utils.random_mpz_lt(1000) % 2 ballot = electionalgs.EncryptedVote.fromElectionAndAnswers( election, [[choice]]) # count the plaintexts plaintext_choices[choice] += 1 print "one ballot" print "ballot hash: %s" % ballot.get_hash() # open submit it print "ballot #" + str(i) + " id: %s" % helios.open_submit( election_id, utils.to_json( ballot.toJSONDict()), 'ben' + str(i) + '@adida.net', None, 'Ben Adida - ' + str(i), 'Category ' + str(i % 3 + 1)) all_votes.append(ballot) # the secret key sk = kp.sk # start tallying tally = election.init_tally() print "adding all votes" tally.add_vote_batch(all_votes) print "decrypting and proving"
def election_set_trustee_pk(self, election_id, trustee, public_key, pok): return self.post("/elections/%s/trustees/%s/upload_pk" % (election_id, trustee), {'public_key' : utils.to_json(public_key.toJSONDict()), 'pok': utils.to_json(pok.toJSONDict())})
# create the election remotely election_id = helios.election_new("Remote Test", kp.pk) print "election id is: " + election_id # set open reg helios.election_set_reg(election_id, open_reg= True) # set questions 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 helios.election_freeze(election_id) print "election questions set and frozen" # get the election election = helios.election_get(election_id) print "election hash is %s" % election.hash ballot = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "ballot hash: %s" % ballot.get_hash() # open submit it print helios.open_submit(election_id, utils.to_json(ballot.toJSONDict()), '*****@*****.**', None, 'Ben Adida', '') # open submit clear it print helios.open_submit(election_id, 'null', '*****@*****.**', None, 'Ben Adida', '')
def add_encrypted_shares(request, election_id, signature=None): ELGAMAL_PARAMS = algs.ElGamal() ELGAMAL_PARAMS.p = p ELGAMAL_PARAMS.q = q ELGAMAL_PARAMS.g = g election = Election.objects.filter(id=election_id)[0] trustees = Trustee.objects.filter(election=election).order_by('id') scheme = Thresholdscheme.objects.filter(election=election)[0] n = scheme.n pk_list = [] for i in range(len(trustees)): pk_list.append(trustees[i].key) if len(pk_list) != n: return HttpResponse('The number of public keys for communication must equal: ' + str(n)) # If the form has been submitted... if (request.method == 'POST')or(signature): form = SignatureForm(request.POST) # A form bound to the POST data if (form.is_valid())or(signature): # All validation rules pass # Process the data in form.cleaned_data # ... if(signature == None): instances = form.save(commit=False) signature = instances.signature secret_key_sig = algs.EGSecretKey.from_dict( utils.from_json(signature)) #signer_id = 1 for j in range(len(pk_list)): pk = pk_list[j] if (pow(g, secret_key_sig.x, p) == elgamal.PublicKey.from_dict(utils.from_json(pk.public_key_signing)).y): signer = pk.name signer_id = pk.id trustee_signer_id = trustees[j].id break if not signer: return HttpResponse('Your signature doesnt belong to the election: ' + election.name) if (len(Signed_Encrypted_Share.objects.filter(signer_id=signer_id).filter(election_id=election_id)) > 0): return render_template(request, 'shares_already_uploaded', {'signer': signer, 'election': election}) s = Utils.random_mpz_lt(q) t = Utils.random_mpz_lt(q) shares = scheme.share_verifiably(s, t, ELGAMAL_PARAMS) if len(pk_list) == len(shares): # f=open('Encrypted_shares'+str(trustee_id)+'.txt','w') for i in range(len(trustees)): trustee_temp = trustees[i] key = trustee_temp.key receiver = key.name receiver_id = key.id share = shares[i] share_string = cryptoutils.to_json_js(share.to_dict()) if(share.point_s.x_value != trustee_temp.id): return HttpResponse('Shares have wrong x_coordinate') encry_share = share.encrypt( algs.EGPublicKey.from_dict(utils.from_json(key.public_key_encrypt))) sig = share.sign(secret_key_sig, p, q, g) signed_encry_share = thresholdalgs.Signed_Encrypted_Share( sig, encry_share) encry_share = Signed_Encrypted_Share() encry_share.share = utils.to_json( signed_encry_share.to_dict()) pk_sign = Key.objects.filter(id=signer_id)[0] if(sig.verify(share_string, algs.EGPublicKey.from_dict(utils.from_json(pk_sign.public_key_signing)), p, q, g)): encry_share.signer = pk_sign.name encry_share.signer_id = signer_id encry_share.receiver = receiver encry_share.receiver_id = receiver_id encry_share.election_id = election_id encry_share.trustee_receiver_id = trustees[i].id encry_share.trustee_signer_id = trustee_signer_id encry_share.save() else: # Dit doet hij return HttpResponse('Wrong Signature') if (len(Signed_Encrypted_Share.objects.filter(signer_id=signer_id).filter(election_id=election.id)) == scheme.n): signer_key = Key.objects.get(id=signer_id) signer_trustee = Trustee.objects.filter( key=signer_key)[0] signer_trustee.added_encrypted_shares = True signer_trustee.save() return HttpResponseRedirect('/bulletin_board/elections/' + str(election.id) + '/') else: return HttpResponse('pk_list and shares havent the same length') return render_template() else: form = SignatureForm() # An unbound form template = loader.get_template('bulletin_board/signature_form.html') context = Context() return render_template(request, 'signature_form', {'election': election})
def hash(self): s = to_json(self.toJSONDict()) return utils.hash_b64(s)
# create three ballots ballot_1 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "one ballot" ballot_2 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "two ballots" ballot_3 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[0]]) print "created 3 ballots" print "ballot #1 hash: %s" % ballot_1.get_hash() print "ballot #2 hash: %s" % ballot_2.get_hash() print "ballot #3 hash: %s" % ballot_3.get_hash() # open submit the three votes print "ballot #1 id: %s" % helios.open_submit( election_id, utils.to_json(ballot_1.toJSONDict()), '*****@*****.**', None, 'Ben Adida', 'Foo Category') print "ballot #2 id: %s" % helios.open_submit( election_id, utils.to_json(ballot_2.toJSONDict()), '*****@*****.**', None, 'Ben2 Adida', 'Foo Category') print "ballot #3 id: %s" % helios.open_submit( election_id, utils.to_json(ballot_3.toJSONDict()), '*****@*****.**', None, 'Ben3 Adida', 'Bar Category') # the secret key sk = kp.sk # start tallying tally = election.init_tally() tally.add_vote_batch([ballot_1, ballot_2, ballot_3])
# create three ballots ballot_1 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "one ballot" ballot_2 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "two ballots" ballot_3 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[0]]) print "created 3 ballots" print "ballot #1 hash: %s" % ballot_1.get_hash() print "ballot #2 hash: %s" % ballot_2.get_hash() print "ballot #3 hash: %s" % ballot_3.get_hash() # open submit the three votes print "ballot #1 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_1.toJSONDict()), '*****@*****.**', None, 'Ben Adida', 'Foo Category') print "ballot #2 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_2.toJSONDict()), '*****@*****.**', None, 'Ben2 Adida', 'Foo Category') print "ballot #3 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_3.toJSONDict()), '*****@*****.**', None, 'Ben3 Adida', 'Bar Category') # the secret key sk = kp.sk # start tallying tally = election.init_tally() tally.add_vote_batch([ballot_1, ballot_2, ballot_3]) result, proof = tally.decrypt_and_prove(sk) helios.set_tally(election_id, result, proof) print "tally is: "
election = helios.election_get(election_id) print "election hash is %s" % election.hash # create three ballots ballot_1 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) ballot_2 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) ballot_3 = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[0]]) print "created 3 ballots" print "ballot #1 hash: %s" % ballot_1.get_hash() print "ballot #2 hash: %s" % ballot_2.get_hash() print "ballot #3 hash: %s" % ballot_3.get_hash() # open submit the three votes print "ballot #1 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_1.toJSONDict()), '*****@*****.**', None, 'Ben Adida', 'Foo Category') print "ballot #2 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_2.toJSONDict()), '*****@*****.**', None, 'Ben2 Adida', 'Foo Category') print "ballot #3 id: %s" % helios.open_submit(election_id, utils.to_json(ballot_3.toJSONDict()), '*****@*****.**', None, 'Ben3 Adida', 'Bar Category') # do homomorphic encrypted tallying tally = election.init_tally() tally.add_vote_batch([ballot_1, ballot_2, ballot_3]) # get decryption of shares for the three keys # upload the shares and proofs # compute the full tally # upload the full tally
def get_hash(self): return utils.hash_b64(utils.to_json(self.toJSONDict()))
election_id = helios.election_new("Remote Test", kp.pk) print "election id is: " + election_id # set open reg helios.election_set_reg(election_id, open_reg=True) # set questions 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 helios.election_freeze(election_id) print "election questions set and frozen" # get the election election = helios.election_get(election_id) print "election hash is %s" % election.hash ballot = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[1]]) print "ballot hash: %s" % ballot.get_hash() # open submit it print helios.open_submit(election_id, utils.to_json(ballot.toJSONDict()), "*****@*****.**", None, "Ben Adida", "") # open submit clear it print helios.open_submit(election_id, "null", "*****@*****.**", None, "Ben Adida", "")
def _setup_complete_election(self, election_params=None): "do the setup part of a whole election" # REPLACE with params? self.setup_login(from_scratch=True) # create the election full_election_params = { "short_name": "test-complete", "name": "Test Complete", "description": "A complete election test", "election_type": "referendum", "use_voter_aliases": "0", "use_advanced_audit_features": "1", "private_p": "False", "csrf_token": self.client.session["csrf_token"], } # override with the given full_election_params.update(election_params or {}) response = self.client.post("/helios/elections/new", full_election_params) # we are redirected to the election, let's extract the ID out of the URL election_id = re.search("/elections/([^/]+)/", str(response["Location"])) self.assertIsNotNone( election_id, "Election id not found in redirect: %s" % str(response["Location"]), ) election_id = election_id.group(1) # helios is automatically added as a trustee # check that helios is indeed a trustee response = self.client.get("/helios/elections/%s/trustees/view" % election_id) assert "Trustee #1" in response.content.decode() # add a few voters with an improperly placed email address FILE = "helios/fixtures/voter-badfile.csv" voters_file = open(FILE) response = self.client.post( "/helios/elections/%s/voters/upload" % election_id, {"voters_file": voters_file}, ) voters_file.close() assert "HOLD ON" in response.content.decode() # add a few voters, via file upload # this file now includes a UTF-8 encoded unicode character # yes I know that's not how you spell Ernesto. # I just needed some unicode quickly. FILE = "helios/fixtures/voter-file.csv" voters_file = open(FILE) response = self.client.post( "/helios/elections/%s/voters/upload" % election_id, {"voters_file": voters_file}, ) voters_file.close() assert "first few rows of this file" in response.content.decode() # now we confirm the upload response = self.client.post( "/helios/elections/%s/voters/upload" % election_id, {"confirm_p": "1"}) self.assertRedirects(response, "/helios/elections/%s/voters/list" % election_id) # and we want to check that there are now voters response = self.client.get("/helios/elections/%s/voters/" % election_id) NUM_VOTERS = 4 self.assertEquals(len(utils.from_json(response.content)), NUM_VOTERS) # let's get a single voter single_voter = models.Election.objects.get( uuid=election_id).voter_set.all()[0] response = self.client.get("/helios/elections/%s/voters/%s" % (election_id, single_voter.uuid)) assert '"uuid": "%s"' % single_voter.uuid in response.content.decode() response = self.client.get("/helios/elections/%s/voters/foobar" % election_id) self.assertStatusCode(response, 404) # add questions response = self.client.post( "/helios/elections/%s/save_questions" % election_id, { "questions_json": utils.to_json([{ "answer_urls": ["http://example.com", None], "answers": ["Alice", "Bob"], "choice_type": "approval", "max": 1, "min": 0, "question": "Who should be president?", "result_type": "absolute", "short_name": "Who should be president?", "tally_type": "homomorphic", }]), "csrf_token": self.client.session["csrf_token"], }, ) assert "SUCCESS" in response.content.decode() # freeze election response = self.client.post( "/helios/elections/%s/freeze" % election_id, {"csrf_token": self.client.session["csrf_token"]}, ) self.assertRedirects(response, "/helios/elections/%s/view" % election_id) # email the voters num_messages_before = len(mail.outbox) response = self.client.post( "/helios/elections/%s/voters/email" % election_id, { "csrf_token": self.client.session["csrf_token"], "subject": "your password", "body": "time to vote", "suppress_election_links": "0", "send_to": "all", }, ) self.assertRedirects(response, "/helios/elections/%s/view" % election_id) num_messages_after = len(mail.outbox) self.assertEquals(num_messages_after - num_messages_before, NUM_VOTERS) email_message = mail.outbox[num_messages_before] assert "your password" in email_message.subject, "bad subject in email" # get the username and password username = re.search("voter ID: (.*)", email_message.body).group(1) password = re.search("password: (.*)", email_message.body).group(1) # now log out as administrator self.clear_login() self.assertEquals(self.client.session.has_key("user"), False) # return the voter username and password to vote return election_id, username, password
def election_set_pk(self, election_id, public_key): return self.post("/elections/%s/set_pk" % election_id, {'public_key_json' : utils.to_json(public_key.toJSONDict())})
# and we want to check that there are now voters response = self.client.get("/helios/elections/%s/voters/" % election_id) NUM_VOTERS = 4 self.assertEqual(len(response.json()), NUM_VOTERS) # let's get a single voter single_voter = models.Election.objects.get(uuid = election_id).voter_set.all()[0] response = self.client.get("/helios/elections/%s/voters/%s" % (election_id, single_voter.uuid)) self.assertContains(response, '"uuid": "%s"' % single_voter.uuid) response = self.client.get("/helios/elections/%s/voters/foobar" % election_id) self.assertStatusCode(response, 404) # add questions response = self.client.post("/helios/elections/%s/save_questions" % election_id, { 'questions_json': utils.to_json([{"answer_urls": ["http://example.com",None], "answers": ["Alice", "Bob"], "choice_type": "approval", "max": 1, "min": 0, "question": "Who should be president?", "result_type": "absolute", "short_name": "Who should be president?", "tally_type": "homomorphic"}]), 'csrf_token': self.client.session['csrf_token']}) self.assertContains(response, "SUCCESS") # freeze election response = self.client.post("/helios/elections/%s/freeze" % election_id, { "csrf_token" : self.client.session['csrf_token']}) self.assertRedirects(response, "/helios/elections/%s/view" % election_id) # email the voters num_messages_before = len(mail.outbox) response = self.client.post("/helios/elections/%s/voters/email" % election_id, { "csrf_token" : self.client.session['csrf_token'], "subject" : "your password", "body" : "time to vote",
def _cast_ballot( self, election_id, username, password, need_login=True, check_user_logged_in=False, ): """ check_user_logged_in looks for the "you're already logged" message """ # vote by preparing a ballot via the server-side encryption response = self.app.post( "/helios/elections/%s/encrypt-ballot" % election_id, params={"answers_json": utils.to_json([[1]])}, ) assert "answers" in response.content.decode() # parse it as an encrypted vote with randomness, and make sure randomness is there the_ballot = utils.from_json(response.testbody) assert the_ballot["answers"][0].has_key("randomness"), "no randomness" assert len(the_ballot["answers"][0] ["randomness"]) == 2, "not enough randomness" # parse it as an encrypted vote, and re-serialize it ballot = datatypes.LDObject.fromDict(utils.from_json( response.testbody), type_hint="legacy/EncryptedVote") encrypted_vote = ballot.serialize() # cast the ballot response = self.app.post( "/helios/elections/%s/cast" % election_id, params={"encrypted_vote": encrypted_vote}, ) self.assertRedirects( response, "%s/helios/elections/%s/cast_confirm" % (settings.SECURE_URL_HOST, election_id), ) cast_confirm_page = response.follow() if need_login: if check_user_logged_in: self.assertContains(cast_confirm_page, "You are logged in as") self.assertContains(cast_confirm_page, "requires election-specific credentials") # set the form login_form = cast_confirm_page.form login_form["voter_id"] = username login_form["password"] = password response = login_form.submit() else: # here we should be at the cast-confirm page and logged in self.assertContains(cast_confirm_page, "CAST this ballot") # confirm the vote, now with the actual form cast_form = cast_confirm_page.form if "status_update" in cast_form.fields.keys(): cast_form["status_update"] = False response = cast_form.submit() self.assertRedirects( response, "%s/helios/elections/%s/cast_done" % (settings.URL_HOST, election_id), ) # at this point an email should have gone out to the user # at position num_messages after, since that was the len() before we cast this ballot email_message = mail.outbox[len(mail.outbox) - 1] url = re.search("https?://[^/]+(/[^ \n]*)", email_message.body).group(1) # check that we can get at that URL if not need_login: # confusing piece: if need_login is True, that means it was a public election # that required login before casting a ballot. # so if need_login is False, it was a private election, and we do need to re-login here # we need to re-login if it's a private election, because all data, including ballots # is otherwise private login_page = self.app.get( "/helios/elections/%s/password_voter_login" % election_id) # if we redirected, that's because we can see the page, I think if login_page.status_int != 302: login_form = login_page.form # try with extra spaces login_form["voter_id"] = " " + username + " " login_form["password"] = "******" + password + " " login_form.submit() response = self.app.get(url, auto_follow=True) assert ballot.hash in response.content.decode() assert html_escape(encrypted_vote) in response.content.decode() # if we request the redirect to cast_done, the voter should be logged out, but not the user response = self.app.get("/helios/elections/%s/cast_done" % election_id)
def election_questions_save(self, election_id, questions): result = self.post("/elections/%s/save_questions" % election_id, {'questions_json' : utils.to_json(questions)}) return result == "SUCCESS"
# create 1000 ballots for i in range(100): # random choice for the ballot choice = algs.Utils.random_mpz_lt(1000) % 2 ballot = electionalgs.EncryptedVote.fromElectionAndAnswers(election, [[choice]]) # count the plaintexts plaintext_choices[choice] += 1 print "one ballot" print "ballot hash: %s" % ballot.get_hash() # open submit it print "ballot #" + str(i) + " id: %s" % helios.open_submit(election_id, utils.to_json(ballot.toJSONDict()), 'ben' + str(i) + '@adida.net', None, 'Ben Adida - ' + str(i), 'Category ' + str(i%3 + 1)) all_votes.append(ballot) # the secret key sk = kp.sk # start tallying tally = election.init_tally() print "adding all votes" tally.add_vote_batch(all_votes) print "decrypting and proving" result, proof = tally.decrypt_and_prove(sk)
def set_tally(self, election_id, result, result_proof): tally_obj = {'result' : result, 'result_proof' : result_proof} tally_obj_json = utils.to_json(tally_obj) result = self.post("/elections/%s/set_tally" % election_id, {'tally' : tally_obj_json}) return result == "SUCCESS"
def serialize(self): d = self.toDict(complete=True) return utils.to_json(d)
def get_hash(self): return utils.hash_b64(to_json(self.toJSONDict()))
def serialize(self): d = self.toDict(complete = True) return utils.to_json(d)
def toJSON(self): return to_json(self.toJSONDict())