2
0
mirror of https://github.com/ComradCollective/Comrad synced 2024-11-05 21:20:51 +00:00
Comrad/komrade/backend/messages.py

290 lines
9.8 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
2020-09-12 18:18:37 +00:00
to_name=msg_d.get('to_name')
to_pub=msg_d.get('to')
from_name=msg_d.get('from_name')
from_pub=msg_d.get('from')
msg=msg_d.get('msg')
# if to_name and to_pub and from_name and from_pub and msg: return True
if to_pub and from_pub and msg: return True
2020-09-09 10:41:48 +00:00
return False
class Message(Logger):
2020-09-09 22:01:41 +00:00
def __init__(self,msg_d,from_whom=None,to_whom=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
2020-09-12 18:18:37 +00:00
self.to_name=msg_d.get('to_name')
self.to_pubkey=msg_d.get('to')
self.from_name=msg_d.get('from_name')
self.from_pubkey=msg_d.get('from')
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 22:01:41 +00:00
self._from_whom=from_whom
self._to_whom=to_whom
2020-09-09 14:38:37 +00:00
self.messenger=None
2020-09-09 21:30:14 +00:00
self._is_encrypted=None
2020-09-09 10:41:48 +00:00
# get operators straight away?
2020-09-09 22:01:41 +00:00
if not self._from_whom or not self._to_whom:
2020-09-09 22:04:56 +00:00
self.get_whoms()
2020-09-09 10:41:48 +00:00
2020-09-12 21:00:09 +00:00
if not self.from_name:
self.from_name=self.from_whom.name
if not self.to_name:
self.to_name=self.to_whom.name
2020-09-12 21:02:31 +00:00
if not self.to_pubkey:
self.to_pubkey=self.to_whom.pubkey.data
if not self.from_pubkey:
self.from_pubkey=self.from_whom.pubkey.data
2020-09-12 21:07:04 +00:00
if isBase64(self.to_pubkey): self.to_pubkey = b64decode(self.to_pubkey)
if isBase64(self.from_pubkey): self.from_pubkey = b64decode(self.from_pubkey)
2020-09-12 22:09:35 +00:00
if hasattr(self.to_pubkey,'data'): self.to_pubkey=self.to_pubkey.data
if hasattr(self.from_pubkey,'data'): self.from_pubkey=self.from_pubkey.data
2020-09-12 21:00:09 +00:00
2020-09-13 07:09:22 +00:00
# self.log('loaded message: to pub',self.to_pubkey,'from pub',self.from_pubkey)
2020-09-12 22:06:28 +00:00
2020-09-10 08:19:08 +00:00
def __repr__(self):
2020-09-12 22:10:42 +00:00
# self.log('my type??',type(self.msg),self.msg)
2020-09-12 18:18:37 +00:00
if type(self.msg)==dict:
2020-09-12 21:15:25 +00:00
if is_valid_msg_d(self.msg):
2020-09-12 21:47:08 +00:00
import textwrap
msg = textwrap.indent(repr(Message(self.msg)),' '*10)
2020-09-12 21:15:25 +00:00
else:
2020-09-13 08:54:01 +00:00
msg=dict_format(self.msg,tab=6)
2020-09-12 21:50:28 +00:00
elif type(self.msg)==bytes:
2020-09-13 07:12:22 +00:00
msg=b64enc_s(self.msg)
2020-09-12 18:18:37 +00:00
else:
msg=self.msg
2020-09-10 08:19:08 +00:00
return f"""
2020-09-12 22:00:01 +00:00
from: @{self.from_name if self.from_name else ''}
2020-09-13 07:11:30 +00:00
({b64enc_s(self.from_pubkey)})
2020-09-12 22:11:36 +00:00
2020-09-12 22:00:01 +00:00
to: @{self.to_name if self.to_name else ''}
2020-09-13 07:11:30 +00:00
({b64enc_s(self.to_pubkey)})
2020-09-12 22:11:36 +00:00
2020-09-13 07:12:22 +00:00
msg: {msg}
2020-09-12 18:18:37 +00:00
"""
2020-09-10 08:19:08 +00:00
2020-09-09 19:53:58 +00:00
@property
2020-09-09 21:30:14 +00:00
def data(self):
2020-09-09 19:53:58 +00:00
md={}
2020-09-09 20:07:50 +00:00
msg_d=self.msg_d
while msg_d:
2020-09-09 20:09:30 +00:00
for k,v in msg_d.items(): md[k]=v
2020-09-12 18:18:37 +00:00
msg_d = msg_d.get('msg',{})
2020-09-09 20:14:49 +00:00
if type(msg_d)!=dict: msg_d=None
2020-09-12 18:18:37 +00:00
if 'msg' in md and type(md['msg']) == dict:
del md['msg']
2020-09-09 20:14:49 +00:00
del md[ROUTE_KEYNAME]
2020-09-09 20:03:39 +00:00
return md
2020-09-09 10:58:00 +00:00
2020-09-10 07:53:40 +00:00
def mark_return_to_sender(self,new_msg=None):
2020-09-13 09:13:02 +00:00
self.log('making return to sender. v1:',self)
2020-09-09 22:01:41 +00:00
self._from_whom,self._to_whom = self._to_whom,self._from_whom
2020-09-13 09:13:02 +00:00
2020-09-12 18:18:37 +00:00
self.msg_d['from'],self.msg_d['to'] = self.msg_d['to'],self.msg_d['from'],
2020-09-13 09:13:02 +00:00
2020-09-13 07:05:14 +00:00
if 'from_name' in self.msg_d and 'to_name' in self.msg_d:
self.msg_d['from_name'],self.msg_d['to_name'] = self.msg_d['to_name'],self.msg_d['from_name']
2020-09-13 09:13:02 +00:00
2020-09-10 07:53:40 +00:00
if new_msg:
2020-09-12 18:18:37 +00:00
self.msg=self.msg_d['msg']=new_msg
2020-09-13 09:13:02 +00:00
self.log('making return to sender. v2:',self)
2020-09-09 21:53:01 +00:00
2020-09-12 20:19:53 +00:00
def get_whom(self,name=None,pubkey=None):
2020-09-09 22:09:08 +00:00
from komrade.backend.operators import locate_an_operator
2020-09-12 20:19:53 +00:00
return locate_an_operator(name=None,pubkey=None)
2020-09-09 14:38:37 +00:00
@property
2020-09-09 22:01:41 +00:00
def from_whom(self):
if not self._from_whom:
2020-09-12 21:56:50 +00:00
self._from_whom,self._to_whom = self.get_whoms()
2020-09-09 22:01:41 +00:00
return self._from_whom
2020-09-09 14:38:37 +00:00
@property
2020-09-09 22:01:41 +00:00
def to_whom(self):
if not self._to_whom:
2020-09-12 21:56:50 +00:00
self._from_whom,self._to_whom = self.get_whoms()
2020-09-09 22:01:41 +00:00
return self._to_whom
2020-09-09 14:38:37 +00:00
2020-09-09 22:04:56 +00:00
def get_whoms(self):
2020-09-12 20:19:53 +00:00
if self._from_whom is None or self._to_whom is None:
2020-09-12 21:16:56 +00:00
self._from_whom = locate_an_operator(self.from_name,self.from_pubkey)
self._to_whom = locate_an_operator(self.to_name,self.to_pubkey)
2020-09-12 20:19:53 +00:00
return self._from_whom,self._to_whom
## loading messages
def get_whoms1(self):
2020-09-09 22:01:41 +00:00
if self._from_whom is not None and self._to_whom is not None:
return (self._from_whom,self._to_whom)
2020-09-09 22:04:56 +00:00
alleged_from_whom = self.get_whom(self.from_name)
alleged_to_whom = self.get_whom(self.to_name)
2020-09-10 09:34:34 +00:00
if not self.whom_records_match(alleged_from_whom,alleged_to_whom):
2020-09-09 22:01:41 +00:00
raise KomradeException('Records of from_whoms on The Operator and the from_whom do not match. Something fishy going on?')
2020-09-09 10:41:48 +00:00
else:
2020-09-09 22:01:41 +00:00
self._from_whom = alleged_from_whom
self._to_whom = alleged_to_whom
2020-09-09 22:04:56 +00:00
return (self._from_whom,self._to_whom)
2020-09-09 22:01:41 +00:00
2020-09-09 22:11:57 +00:00
def whom_records_match(self,alleged_from_whom,alleged_to_whom):
2020-09-09 22:01:41 +00:00
alleged_from_whom_name = self.from_name
alleged_from_whom_pubkey = self.from_pubkey
alleged_to_whom_name = self.to_name
alleged_to_whom_pubkey = self.to_pubkey
# self.log('from_whom names:',alleged_from_whom.name, alleged_from_whom_name)
# self.log('from_whom pubs:',alleged_from_whom.pubkey, alleged_from_whom_pubkey)
# self.log('to_whom names:',alleged_to_whom.name, alleged_to_whom_name)
# self.log('to_whom pubs:',alleged_to_whom.pubkey, alleged_to_whom_pubkey)
if alleged_to_whom.name != alleged_to_whom_name:
2020-09-09 10:41:48 +00:00
return False
2020-09-09 22:01:41 +00:00
if alleged_from_whom.name != alleged_from_whom_name:
2020-09-09 10:41:48 +00:00
return False
2020-09-09 22:01:41 +00:00
if alleged_to_whom.pubkey != alleged_to_whom_pubkey:
2020-09-09 10:41:48 +00:00
return False
2020-09-09 22:01:41 +00:00
if alleged_from_whom.pubkey != alleged_from_whom_pubkey:
2020-09-09 10:41:48 +00:00
return False
return True
2020-09-09 23:07:03 +00:00
def decrypt(self,recursive=False):
2020-09-10 07:57:02 +00:00
# check if needs decryption
2020-09-09 21:42:01 +00:00
if not self.is_encrypted: return
2020-09-10 07:57:02 +00:00
# otherwise lets do it
self.msg_encr = self.msg
2020-09-13 11:27:26 +00:00
self.log(f'Attempting to decrypt:\n{self}')
2020-09-09 19:41:14 +00:00
2020-09-09 10:41:48 +00:00
# decrypt msg
2020-09-13 12:21:19 +00:00
# self.log('attempting to decrypt',self.msg,'from',self.from_pubkey,'to',self.to_whom,self.to_whom.keychain(),self.to_whom.assemble(self.to_whom.keychain()))
2020-09-12 18:18:37 +00:00
self.msg = self.msg_d['msg'] = decr_msg_b = SMessage(
2020-09-12 19:31:29 +00:00
self.to_whom.privkey.data,
2020-09-12 21:03:38 +00:00
self.from_pubkey
2020-09-09 19:41:14 +00:00
).unwrap(self.msg)
2020-09-10 08:28:03 +00:00
# self.log('Am I decrypted?',self)
2020-09-09 19:41:14 +00:00
2020-09-10 07:57:02 +00:00
# unpickle
2020-09-12 18:18:37 +00:00
self.msg = self.msg_d['msg'] = decr_msg = pickle.loads(decr_msg_b)
2020-09-13 11:22:35 +00:00
self.log('Message decrypted:\n',self)
2020-09-10 07:57:02 +00:00
2020-09-09 10:41:48 +00:00
# now, is the decrypted message itself a message?
2020-09-09 21:30:14 +00:00
if is_valid_msg_d(decr_msg):
2020-09-13 10:26:15 +00:00
self.log('Once decrypted, I discovered that I contain an enclosed encrypted message!\n\n',self)
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)
2020-09-09 23:05:34 +00:00
if recursive and self.msg.is_encrypted:
2020-09-09 23:01:08 +00:00
self.msg.decrypt()
2020-09-09 21:30:14 +00:00
2020-09-10 08:28:03 +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 21:30:14 +00:00
@property
def is_encrypted(self):
return type(self.msg) == bytes
2020-09-09 21:40:28 +00:00
# if self.msg._is_encrypted is not None:
# return self.msg._is_encrypted
2020-09-09 21:30:14 +00:00
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 21:30:14 +00:00
if self._is_encrypted: return
2020-09-09 22:01:41 +00:00
# self.log(f'attempting to encrypt msg {self.msg} from {self.from_whom} to {self.to_whom}')
2020-09-12 21:08:53 +00:00
self.log(f'Before encrypting the message from @{self.from_name} to @{self.to_name}, it looks like:\n{self}')
2020-09-09 14:38:37 +00:00
2020-09-10 07:58:52 +00:00
# make sure msg is not meeta
if self.has_embedded_msg:
self.msg = self.msg.msg_d
2020-09-13 08:51:10 +00:00
# self.log('woops, first had to replace Message object with dict',self)
2020-09-10 07:58:52 +00:00
2020-09-09 19:41:14 +00:00
# binarize msg
msg_b = pickle.dumps(self.msg)
# encrypt it!
2020-09-13 07:12:49 +00:00
# self.log('from whom keychain:',self.from_whom.keychain())
# self.log('to pubkey:',self.to_pubkey)
2020-09-09 19:41:14 +00:00
msg_encr = SMessage(
2020-09-12 21:04:44 +00:00
self.from_whom.privkey.data,
self.to_pubkey
2020-09-12 21:10:54 +00:00
).wrap(msg_b)
2020-09-09 19:41:14 +00:00
2020-09-09 14:38:37 +00:00
self.msg_decr = self.msg
2020-09-12 18:18:37 +00:00
self.msg_d['msg'] = self.msg = b64encode(msg_encr)
2020-09-12 18:43:50 +00:00
self.log(f'After encrypting the message from {self.from_whom} to {self.to_whom}, it looks like:\n{self}')
2020-09-12 18:18:37 +00:00
self.msg_d['msg'] = self.msg = msg_encr
2020-09-09 21:30:14 +00:00
self._is_encrypted = True
2020-09-09 19:41:14 +00:00
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 20:00:21 +00:00
def _msgs():
msg=self
while True:
yield msg
if msg.has_embedded_msg:
msg=msg.msg
break
return list(_msgs())
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-10 11:38:59 +00:00
def delete_route(self):
if type(self.msg)==dict:
del self.msg[ROUTE_KEYNAME]
2020-09-12 18:18:37 +00:00
if ROUTE_KEYNAME in self.msg_d['msg']:
del self.msg_d['msg'][ROUTE_KEYNAME]
2020-09-10 11:38:59 +00:00
if self.has_embedded_msg:
self.msg.delete_route()
2020-09-10 12:04:12 +00:00
2020-09-09 15:03:52 +00:00
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()