class SessionContext: def __init__(self, sessid): if not sessid: raise ValueError("Missing sessid") self.__key = [evcommon.IDSPOOL, sessid] self.__reg = Election().get_root_reg() def store_session(self, cert): self.__reg.ensure_key(self.__key) self.__reg.create_value(self.__key, "cert", cert) self.__reg.create_integer_value(self.__key, "start", int(time.time())) def check_session(self, cert): if not self.__reg.check(self.__key): return evcommon.EVOTE_ERROR, evmessage.EV_ERRORS.SEANSS_PUUDUB start = self.__reg.read_integer_value(self.__key, "start").value length = Election().get_session_length() * 60 if start + length < int(time.time()): return evcommon.EVOTE_ERROR, evmessage.EV_ERRORS.SEANSS_PUUDUB if self.__reg.read_value(self.__key, "cert").value != cert: evlog.log_error('Sertifikaat muutus') return evcommon.EVOTE_CERT_ERROR, evmessage.EV_ERRORS.TEHNILINE_VIGA return evcommon.EVOTE_OK, None def kill(self): self.__reg.ensure_no_key(self.__key)
def issue_vote_id(self): vote_id = self.__create_vote_key() rreg = Election().get_root_reg() key = htscommon.get_verification_key(vote_id) rreg.create_string_value(key, "voter", self.signercode) rreg.create_integer_value(key, "timestamp", int(time.time())) rreg.create_integer_value(key, "count", \ Election().get_verification_count()) # Store the election IDs and include a backreference in the # corresponding questions' subregistries. elids = "" for elid in [quest[0] for quest in self.questions]: elids += elid + "\t" sreg = Election().get_sub_reg(elid) skey = htscommon.get_user_key(self.signercode) sreg.ensure_key(skey) sreg.create_string_value(skey, \ htscommon.VOTE_VERIFICATION_ID_FILENAME, vote_id) rreg.create_string_value(key, "elids", elids) return vote_id
class MobileIDContext: phoneno = None lang = None challenge = None midsess = None origvote = None votefiles = {} __sessid = None __reg = None def __init__(self, sessid): if sessid is None: raise Exception('Puuduv sessiooniidentifikaator') self.__sessid = sessid self.__reg = Election().get_root_reg() self.lang = 'EST' def sessid(self): return self.__sessid def kill(self): self.__reg.ensure_no_key([evcommon.MIDSPOOL, self.__sessid]) def set_phone(self, phone): self.phoneno = phone def set_origvote(self, hv): self.origvote = hv def get_origvote(self): self.origvote = self.__reg.read_value( [evcommon.MIDSPOOL, self.__sessid], 'origvote').value return self.origvote def add_votefile(self, filename, data): self.votefiles[filename] = data def get_votefiles(self): for key in self.__reg.list_keys( [evcommon.MIDSPOOL, self.__sessid, 'votefiles']): self.votefiles[key] = self.__reg.read_value( [evcommon.MIDSPOOL, self.__sessid, 'votefiles'], key).value return self.votefiles def generate_challenge(self): self.challenge = binascii.b2a_hex(os.urandom(10)) def verify_challenge(self, signature): return challenge_ok(self.certificate(), self.mychallenge(), self.ourchallenge(), signature) def mychallenge(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], 'mychallenge').value def ourchallenge(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], 'ourchallenge').value def certificate(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], 'cert').value def set_auth_succ(self): self.__reg.ensure_key([evcommon.MIDSPOOL, self.__sessid, 'authsucc']) def auth_succ(self): return self.__reg.check([evcommon.MIDSPOOL, self.__sessid, 'authsucc']) def check_session(self): if not self.__reg.check([evcommon.MIDSPOOL, self.__sessid]): return False start = self.__reg.read_integer_value( [evcommon.MIDSPOOL, self.__sessid], 'start').value length = Election().get_session_length() * 60 return start + length >= int(time.time()) and self.auth_succ() def save_post_auth(self, rsp): self.__reg.reset_key([evcommon.MIDSPOOL, self.__sessid]) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'cert', rsp._CertificateData) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'phone', self.phoneno) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'midsess', rsp._Sesscode) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'mychallenge', self.challenge) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'ourchallenge', rsp._Challenge) self.__reg.create_integer_value([evcommon.MIDSPOOL, self.__sessid], 'start', int(time.time())) def load_pre_sign(self): self.phoneno = self.__reg.read_value( [evcommon.MIDSPOOL, self.__sessid], 'phone').value def save_post_sign(self, midsess): self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'midsess', midsess) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], 'origvote', self.origvote) self.__reg.ensure_key([evcommon.MIDSPOOL, self.__sessid, 'votefiles']) for el in self.votefiles: self.__reg.create_value( [evcommon.MIDSPOOL, self.__sessid, 'votefiles'], el, self.votefiles[el]) def load_pre_poll(self): self.midsess = int( self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], 'midsess').value)
class HTSVerify: def __init__(self): self._rreg = Election().get_root_reg() self._vote_id = None self._voter_code = None self._voter = None def __revoke_vote_id(self): _revoke_vote_id(self._voter_code) def verify_id(self, vote_id): # check if valid vote ID if not formatutil.is_vote_verification_id(vote_id): # We don't know how large vote_id is, so don't write to disk evlog.log_error("Malformed vote ID") raise HTSVerifyException, evcommon.VERIFY_ERROR vote_id = vote_id.lower() otp_key = htscommon.get_verification_key(vote_id) # check if corresponding OTP exists if not self._rreg.check(otp_key): evlog.log_error("No such vote ID: %s" % vote_id) raise HTSVerifyException, evcommon.VERIFY_ERROR self._voter_code = self._rreg.read_string_value(\ otp_key, "voter").value.rstrip() # check if timestamp is OK current = int(time.time()) created = self._rreg.read_integer_value(otp_key, "timestamp").value timeout = Election().get_verification_time() * 60 if created + timeout < current: evlog.log("Vote ID %s has expired" % vote_id) self.__revoke_vote_id() raise HTSVerifyException, evcommon.VERIFY_ERROR # check if count is OK count = self._rreg.read_integer_value(otp_key, "count").value if count <= 0: evlog.log_error("Vote ID %s count is zero, but had not been revoked") self.__revoke_vote_id() raise HTSVerifyException, evcommon.VERIFY_ERROR self._vote_id = vote_id def __load_bdoc(self, elid): voter_key = htscommon.get_user_key(self._voter_code) sreg = Election().get_sub_reg(elid) for votefile in sreg.list_keys(voter_key): if htscommon.VALID_VOTE_PATTERN.match(votefile): bdoc = bdocpythonutils.BDocContainer() bdoc.load(sreg.path(voter_key + [votefile])) bdoc.validate(bdocpythonutils.ManifestProfile("TM")) self._voter = htscommon.get_votefile_voter(votefile) break if not bdoc: evlog.log_error("No valid BDOC found for voter %s using vote ID %s" % \ (self._voter, self._vote_id)) raise HTSVerifyException, evcommon.VERIFY_ERROR return bdoc def __decrease_count(self): otp_key = htscommon.get_verification_key(self._vote_id) count = self._rreg.read_integer_value(otp_key, "count").value - 1 if count > 0: self._rreg.create_integer_value(otp_key, "count", count) else: self.__revoke_vote_id() def get_response(self): import binascii # load a random BDOC from the ones available otp_key = htscommon.get_verification_key(self._vote_id) elids = self._rreg.read_string_value(otp_key, "elids")\ .value.rstrip().split("\t") bdoc = self.__load_bdoc(random.choice(elids)) evlog.log("Sending BDOC %s with vote ID %s for verification" %\ (ksum.votehash(bdoc.get_bytes()), self._vote_id)) # check consistency bdoc_set = set([doc.split(".")[0] for doc in bdoc.documents]) elids_set = set(elids) if bdoc_set != elids_set: evlog.log_error("Votes in BDOC for vote ID %s are inconsistent " \ "with registry: %s, %s" % (self._vote_id, bdoc_set, elids_set)) raise HTSVerifyException, evcommon.VERIFY_ERROR # create question objects questions = [] for elid in elids: questions.append(question.Question(\ elid, "hts", Election().get_sub_reg(elid))) # start assembling the response ret = "" # append questions for quest in questions: ret += quest.qname() + ":" + str(quest.get_type()) + "\t" ret += "\n" # append election IDs and votes for votefile in bdoc.documents: elid = votefile.split(".")[0] ret += elid + "\t" + binascii.b2a_hex(bdoc.documents[votefile]) + "\n" ret += "\n" # append voter ret += self._voter["nimi"] + "\t" + self._voter_code + "\n" # append choices list for quest in questions: ret += quest.choices_to_voter(self._voter) self.__decrease_count() return ret
class MobileIDContext: phoneno = None lang = None challenge = None midsess = None origvote = None votefiles = {} __sessid = None __reg = None def __init__(self, sessid): if sessid is None: raise Exception("Puuduv sessiooniidentifikaator") self.__sessid = sessid self.__reg = Election().get_root_reg() self.lang = "EST" def sessid(self): return self.__sessid def kill(self): self.__reg.ensure_no_key([evcommon.MIDSPOOL, self.__sessid]) def set_phone(self, phone): self.phoneno = phone def set_origvote(self, hv): self.origvote = hv def get_origvote(self): self.origvote = self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "origvote").value return self.origvote def add_votefile(self, filename, data): self.votefiles[filename] = data def get_votefiles(self): for key in self.__reg.list_keys([evcommon.MIDSPOOL, self.__sessid, "votefiles"]): self.votefiles[key] = self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid, "votefiles"], key).value return self.votefiles def generate_challenge(self): self.challenge = binascii.b2a_hex(os.urandom(10)) def verify_challenge(self, signature): return challenge_ok(self.certificate(), self.mychallenge(), self.ourchallenge(), signature) def mychallenge(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "mychallenge").value def ourchallenge(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "ourchallenge").value def certificate(self): return self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "cert").value def set_auth_succ(self): self.__reg.ensure_key([evcommon.MIDSPOOL, self.__sessid, "authsucc"]) def auth_succ(self): return self.__reg.check([evcommon.MIDSPOOL, self.__sessid, "authsucc"]) def check_session(self): if not self.__reg.check([evcommon.MIDSPOOL, self.__sessid]): return False start = self.__reg.read_integer_value([evcommon.MIDSPOOL, self.__sessid], "start").value length = Election().get_session_length() * 60 return start + length >= int(time.time()) and self.auth_succ() def save_post_auth(self, rsp): self.__reg.reset_key([evcommon.MIDSPOOL, self.__sessid]) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "cert", rsp._CertificateData) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "phone", self.phoneno) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "midsess", rsp._Sesscode) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "mychallenge", self.challenge) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "ourchallenge", rsp._Challenge) self.__reg.create_integer_value([evcommon.MIDSPOOL, self.__sessid], "start", int(time.time())) def load_pre_sign(self): self.phoneno = self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "phone").value def save_post_sign(self, midsess): self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "midsess", midsess) self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid], "origvote", self.origvote) self.__reg.ensure_key([evcommon.MIDSPOOL, self.__sessid, "votefiles"]) for el in self.votefiles: self.__reg.create_value([evcommon.MIDSPOOL, self.__sessid, "votefiles"], el, self.votefiles[el]) def load_pre_poll(self): self.midsess = int(self.__reg.read_value([evcommon.MIDSPOOL, self.__sessid], "midsess").value)