# internal imports import os,sys; sys.path.append(os.path.abspath(os.path.join(os.path.abspath(os.path.join(os.path.dirname(__file__),'..')),'..'))) from komrade import * # from komrade.backend.crypt import * # from komrade.backend.keymaker import * # from komrade.backend.mazes import * # from komrade.backend.switchboard import * from komrade.backend import * def locate_an_operator(name): global OPERATOR,TELEPHONE from komrade.backend.the_operator import TheOperator from komrade.backend.the_telephone import TheTelephone from komrade.backend.callers import Caller if name == OPERATOR_NAME: return OPERATOR if OPERATOR else TheOperator() if name == TELEPHONE_NAME: return TELEPHONE if TELEPHONE else TheTelephone() return Caller(name) class Operator(Keymaker): ROUTES = ['forge_new_keys','does_username_exist','hello_world'] def __init__(self, name, passphrase=DEBUG_DEFAULT_PASSPHRASE, keychain = {}, path_crypt_keys=PATH_CRYPT_CA_KEYS, path_crypt_data=PATH_CRYPT_CA_DATA): super().__init__(name=name,passphrase=passphrase, keychain=keychain, path_crypt_keys=path_crypt_keys, path_crypt_data=path_crypt_data) # self.boot(create=False) # connect phonelines? from komrade.backend.phonelines import connect_phonelines self.operator_keychain,self.telephone_keychain,self.omega_key = connect_phonelines() # def boot(self,create=False): # # Do I have my keys? # have_keys = self.exists() # # If not, forge them -- only once! # if not have_keys and create: # self.get_new_keys() @property def phone(self): from komrade.backend.the_telephone import TheTelephone if type(self)==TheTelephone: return self if hasattr(self,'_phone'): return self._phone global TELEPHONE,TELEPHONE_KEYCHAIN if TELEPHONE: return TELEPHONE self._phone=TELEPHONE=TheTelephone() return TELEPHONE @property def op(self): from komrade.backend.the_operator import TheOperator if type(self)==TheOperator: return self if hasattr(self,'_op'): return self._op global OPERATOR,OPERATOR_KEYCHAIN if OPERATOR: return OPERATOR self._op=OPERATOR=TheOperator() return OPERATOR def compose_msg_to(self,msg,another): if not self.privkey or not self.pubkey: raise KomradeException('why do I have no pub/privkey pair!?',self,self.name,self.pubkey,self.privkey,self.keychain()) if not another.name or not another.pubkey: raise KomradeException('why do I not know whom I\'m writing to?') # otherwise create msg msg_d = { '_from_pub':self.pubkey, '_from_name':self.name, '_to_pub':another.pubkey, '_to_name':another.name, '_msg':msg, } # self.log(f'I am {self} packaging a message to {another}: {msg_d}') from komrade.backend.messages import Message msg_obj = Message(msg_d,from_whom=self,to_whom=another) # encrypt! # msg_obj.encrypt() return msg_obj # def compose_reply(self,msg,another): def seal_msg(self,msg_d): # make sure encrypted self.log('sealing msg!:',dict_format(msg_d)) # msg_obj.encrypt(recursive=True) # return pure binary version of self's entire msg_d msg_b = pickle.dumps(msg_d) self.log('pickled!',msg_b) # encrypt by omega key msg_b_encr = self.omega_key.encrypt(msg_b) self.log('final seal:',msg_b_encr) return msg_b_encr def unseal_msg(self,msg_b_encr,from_whom=None,to_whom=None): # default to assumption that I am the recipient if not to_whom: to_whom=self # decrypt by omega msg_b = self.omega_key.decrypt(msg_b_encr) # unpackage from transmission msg_d = pickle.loads(msg_b) # get message obj print('unsealed msg:',msg_d) from komrade.backend.messages import Message msg_obj = Message(msg_d,from_whom=from_whom,to_whom=to_whom) # decrypt msg return msg_obj def __repr__(self): clsname=(type(self)).__name__ keystr='+'.join(self.top_keys) return f'[{clsname}] {self.name} ({keystr})' def locate_an_operator(self,name): if name == OPERATOR_NAME: return TheOperator() if name == TELEPHONE_NAME: return TheTelephone() return Caller(name) # return resp_msg_obj def route(self,msg_obj): data,route = msg_obj.data, msg_obj.route if not hasattr(self,route) or route not in self.ROUTES: raise KomradeException('route not valid!') # route it! func = getattr(self,route) new_data = func(**data) self.log('got back from route func <-',new_data) # return the other way self.log('message was sent this way:',msg_obj) msg_obj.mark_return_to_sender(new_msg=new_data) self.log('now it\'s going the other way:',msg_obj) # if not decrypted if not msg_obj.is_encrypted: msg_obj.encrypt() return msg_obj def route_msg(self,msg_obj): # decrypt self.log('got msg_obj!',msg_obj) if msg_obj.is_encrypted: msg_obj.decrypt() # are there instructions for us? if msg_obj.route: # get result from routing self.log(f'routing msg to self.{msg_obj.route}(**{msg_obj.data})') return self.route(msg_obj) # can we pass the buck on? elif msg_obj.has_embedded_msg: embedded_msg = msg_obj.msg embedded_recipient = embedded_msg.to_whom # whew, then we can make someone else take the phone self.log(f'passing msg onto {embedded_recipient} ...') return embedded_recipient.route_msg(embedded_msg) # ??? self.log('what do I do? giving this back to you...') return msg_obj def ring_ring(self,msg,to_whom,get_resp_from=None): # ring ring self.log(f''' ring ring! I am {self}. I have been told to pass onto {to_whom}, by way of function {get_resp_from}, the following msg: {dict_format(msg,tab=5)} ''') # get encr msg obj msg_obj = self.compose_msg_to( msg, to_whom ) self.log(f'ring ring! here is the message object I made, to send to {to_whom}: {msg_obj}') # encrypting msg_obj.encrypt() # get pure encrypted binary, sealed #msg_sealed = self.seal_msg(msg_obj) # pass onto next person... if not get_resp_from: get_resp_from=to_whom.ring_ring resp_msg_obj = get_resp_from(msg_obj.msg_d) self.log('resp_msg_obj <-',resp_msg_obj) if resp_msg_obj.is_encrypted: resp_msg_obj.decrypt() return resp_msg_obj # route back? # route_result = self.route_msg(resp_msg_obj) # self.log('route_result 2?',route_result) # decrypt? # from komrade.backend.messages import Message # if type(route_result)==Message: # if route_result.is_encrypted: # route_result.decrypt() # return route_result def pronto_pronto(self, msg_obj): self.log(f''' pronto pronto! >> {msg_obj} ''') route_response = self.route_msg(msg_obj) self.log('route_response',route_response) # set this to be the new msg #msg_obj.msg = msg_obj.msg_d['_msg'] = response #self.log('what msg_obj looks like now:',msg_obj) # send new content back resp_msg_obj = msg_obj.to_whom.compose_msg_to( route_response, msg_obj.from_whom ) self.log('resp_msg_obj',resp_msg_obj) # re-encrypt resp_msg_obj.encrypt() self.log(f're-encrypted: {resp_msg_obj}') # pass msg back the chain return resp_msg_obj