2
0
mirror of https://github.com/ComradCollective/Comrad synced 2024-11-01 21:40:32 +00:00
Comrad/komrade/backend/messages.py

228 lines
6.9 KiB
Python
Raw Normal View History

2020-09-09 10:41:48 +00:00
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 import *
def is_valid_msg_d(msg_d):
if not type(msg_d)==dict: return False
to_name=msg_d.get('_to_name')
to_pub=msg_d.get('_to_pub')
from_name=msg_d.get('_from_name')
from_pub=msg_d.get('_from_pub')
msg=msg_d.get('_msg')
if to_name and to_pub and from_name and from_pub and msg: return True
return False
class Message(Logger):
2020-09-09 14:38:37 +00:00
def __init__(self,msg_d,caller=None,callee=None,messenger=None,embedded_msg=None,is_encrypted=False):
2020-09-09 10:41:48 +00:00
# check input
if not is_valid_msg_d(msg_d):
raise KomradeException('This is not a valid msg_d:',msg_d)
# set fields
self.msg_d=msg_d
self.to_name=msg_d.get('_to_name')
self.to_pubkey=msg_d.get('_to_pub')
self.from_name=msg_d.get('_from_name')
self.from_pubkey=msg_d.get('_from_pub')
self.msg=msg_d.get('_msg')
2020-09-09 14:38:37 +00:00
self.embedded_msg=embedded_msg # only if this message has an embedded one
2020-09-09 10:58:00 +00:00
self._route=msg_d.get(ROUTE_KEYNAME)
2020-09-09 14:38:37 +00:00
self._caller=caller
self._callee=callee
self.messenger=None
self.is_encrypted=False
2020-09-09 10:41:48 +00:00
# get operators straight away?
2020-09-09 14:53:04 +00:00
if not self._caller or not self._callee:
2020-09-09 10:41:48 +00:00
self.get_callers()
2020-09-09 10:58:00 +00:00
2020-09-09 14:38:37 +00:00
def __repr__(self):
2020-09-09 19:15:35 +00:00
msg_d_str=dict_format(self.msg_d,tab=6)
2020-09-09 14:38:37 +00:00
return f"""
2020-09-09 18:31:36 +00:00
<MSG>
self.caller={self.caller}
self.callee={self.callee}
2020-09-09 18:43:53 +00:00
self.msg_d={msg_d_str}
2020-09-09 18:31:36 +00:00
</MSG>
2020-09-09 14:38:37 +00:00
"""
def get_caller(self,name):
if name == OPERATOR_NAME:
return TheOperator()
if name == TELEPHONE_NAME:
return TheTelephone()
return Caller(name)
@property
def caller(self):
if not self._caller:
self._caller,self._callee = self.get_callers()
return self._caller
@property
def callee(self):
if not self._callee:
self._caller,self._callee = self.get_callers()
return self._callee
2020-09-09 10:58:00 +00:00
## loading messages
2020-09-09 14:38:37 +00:00
def get_callers(self):
2020-09-09 14:54:10 +00:00
if self._caller is not None and self._callee is not None:
return (self._caller,self._callee)
2020-09-09 14:38:37 +00:00
alleged_caller = self.get_caller(self.from_name)
alleged_callee = self.get_caller(self.to_name)
if not self.caller_records_match(alleged_caller,alleged_callee):
2020-09-09 10:41:48 +00:00
raise KomradeException('Records of callers on The Operator and the Caller do not match. Something fishy going on?')
else:
2020-09-09 14:54:10 +00:00
self._caller = alleged_caller
self._callee = alleged_callee
2020-09-09 14:57:56 +00:00
return (self._caller,alleged_caller)
2020-09-09 10:41:48 +00:00
2020-09-09 14:38:37 +00:00
def caller_records_match(self,alleged_caller,alleged_callee):
2020-09-09 10:41:48 +00:00
alleged_caller_name = self.from_name
alleged_caller_pubkey = self.from_pubkey
alleged_callee_name = self.to_name
2020-09-09 14:38:37 +00:00
alleged_callee_pubkey = self.to_pubkey
2020-09-09 19:31:57 +00:00
# self.log('caller names:',alleged_caller.name, alleged_caller_name)
# self.log('caller pubs:',alleged_caller.pubkey, alleged_caller_pubkey)
# self.log('callee names:',alleged_callee.name, alleged_callee_name)
# self.log('callee pubs:',alleged_callee.pubkey, alleged_callee_pubkey)
2020-09-09 14:38:37 +00:00
2020-09-09 10:41:48 +00:00
if alleged_callee.name != alleged_callee_name:
return False
if alleged_caller.name != alleged_caller_name:
return False
if alleged_callee.pubkey != alleged_callee_pubkey:
return False
if alleged_caller.pubkey != alleged_caller_pubkey:
return False
return True
2020-09-09 19:41:14 +00:00
def decrypt(self,recursive=True):
2020-09-09 10:41:48 +00:00
# get callers
2020-09-09 19:41:14 +00:00
self.log(f'attempting to decrypt msg',self.msg) # {self.msg} from {caller} to {callee}')
2020-09-09 10:41:48 +00:00
# decrypt msg
2020-09-09 19:41:14 +00:00
decr_msg_b = SMessage(
self.callee.privkey,
self.caller.pubkey
).unwrap(self.msg)
self.log('Am I decrypted?',decr_msg_b)
decr_msg = pickle.loads(decr_msg_b)
self.log('unpickled:',decr_msg)
2020-09-09 10:41:48 +00:00
self.msg_encr = self.msg
self.msg = decr_msg
self.msg_d['_msg'] = decr_msg
2020-09-09 15:48:05 +00:00
self.log('got decr msg back:',decr_msg)
2020-09-09 10:41:48 +00:00
# now, is the decrypted message itself a message?
if recursive and is_valid_msg_d(decr_msg):
2020-09-09 19:44:59 +00:00
self.log('this is a valid msg in its own right!',decr_msg)
2020-09-09 10:58:00 +00:00
# then ... make that, a message object and decrypt it too!
2020-09-09 14:52:18 +00:00
self.msg = Message(decr_msg)
self.msg.decrypt()
2020-09-09 19:44:59 +00:00
self.log(f'done decrypting! {self}')
2020-09-09 10:41:48 +00:00
return decr_msg
2020-09-09 10:58:00 +00:00
2020-09-09 19:41:14 +00:00
def encrypt(self): # each child message should already be encrypted before coming to its parent message ,recursive=False):
2020-09-09 14:38:37 +00:00
if self.is_encrypted: return
2020-09-09 18:31:36 +00:00
# self.log(f'attempting to encrypt msg {self.msg} from {self.caller} to {self.callee}')
2020-09-09 19:41:14 +00:00
self.log(f'About to encrypt self.msg! I now look like v1: {self}')
2020-09-09 14:38:37 +00:00
2020-09-09 19:41:14 +00:00
# binarize msg
msg_b = pickle.dumps(self.msg)
2020-09-09 19:44:59 +00:00
# self.log('msg_b = ',msg_b)
2020-09-09 19:41:14 +00:00
# encrypt it!
msg_encr = SMessage(
2020-09-09 14:38:37 +00:00
self.caller.privkey,
2020-09-09 19:41:14 +00:00
self.callee.pubkey,
).wrap(msg_b)
2020-09-09 14:38:37 +00:00
self.msg_decr = self.msg
2020-09-09 19:41:53 +00:00
self.msg = msg_encr
self.msg_d['_msg'] = msg_encr
2020-09-09 19:41:14 +00:00
self.log(f'Encrypted! I now look like v2: {self}')
self.is_encrypted = True
# def decrypt_from_send(self,msg_encr,from_pubkey,to_privkey):
# if not msg_encr or not from_pubkey or not to_privkey:
# self.log('not enough info!',msg_encr,from_pubkey,to_privkey)
# return {}
# try:
# # decrypt
# msg_b = SMessage(
# to_privkey,
# from_pubkey,
# ).unwrap(msg_encr)
# # decode
# self.log('msg_b??',msg_b)
# msg_json = unpackage_from_transmission(msg_b)
# self.log('msg_json??',msg_json)
# # return
# return msg_json
# except ThemisError as e:
# self.log('unable to decrypt from send!',e)
# return {}
2020-09-09 14:38:37 +00:00
2020-09-09 10:58:00 +00:00
## msg properties
2020-09-09 14:38:37 +00:00
@property
2020-09-09 10:58:00 +00:00
def has_embedded_msg(self):
2020-09-09 14:38:37 +00:00
return type(self.msg) == Message
2020-09-09 10:58:00 +00:00
@property
def messages(self):
# move through msgs recursively
2020-09-09 15:03:52 +00:00
yield self
if self.has_embedded_msg:
yield self.messages
2020-09-09 10:58:00 +00:00
@property
def route(self):
2020-09-09 15:03:52 +00:00
if type(self.msg)==dict:
rte=self.msg.get(ROUTE_KEYNAME)
if rte:
return rte
if self.has_embedded_msg:
return self.msg.route
return None
2020-09-09 14:38:37 +00:00
def test_msg():
phone = TheTelephone()
op = TheOperator()
pprint(op.pubkey)
print('?keychains?')
pprint(phone.pubkey)
2020-09-09 18:31:36 +00:00
msg={'_route':'forge_new_keys'}
2020-09-09 14:38:37 +00:00
resp_msp_obj = phone.ring_ring(msg)
print(resp_msp_obj)
2020-09-09 14:50:10 +00:00
if __name__ == '__main__':
test_msg()