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 :
msg = dict_format ( self . msg , tab = 4 )
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-09 22:01:41 +00:00
self . _from_whom , self . _to_whom = self . _to_whom , self . _from_whom
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 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-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-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 07:05:52 +00:00
self . log ( f ' Attempting to decrypt { self } ' )
2020-09-09 19:41:14 +00:00
2020-09-09 10:41:48 +00:00
# decrypt msg
2020-09-13 08:33:14 +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 07:05:52 +00:00
self . log ( ' Message decrypted: ' , 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-10 08:28:03 +00:00
self . log ( ' Once decrypted, I discovered that I contain a valid msg in its own right! ' , 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-10 08:02:03 +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 ( )