Recolectar el tráfico necesario para analizar la conexión entre el agente y el listener
$ sudo tcpdump -A -s 0'tcp port 8080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)'-i lo
Librerías a utilizar
ECDSA
This is an easy-to-use implementation of ECDSA cryptography (Elliptic Curve Digital Signature Algorithm), implemented purely in Python, released under the MIT license. With this library, you can quickly create keypairs (signing key and verifying key), sign messages, and verify the signatures. The keys and signatures are very short, making them easy to handle and incorporate into other protocols.
import jsonfrom typing import Mapping, Optionalfrom base64 import b64encode, b64decodefrom.import Handler, AuthenticatedHandlerfrom malon_lp.crypto.dh import KeyExchange, get_client_idfrom malon_lp.crypto.sym import SymmetricCipherKeyRespository = Mapping[str,bytes]classDHHandler(Handler):def__init__(self,ke: KeyExchange,handler: AuthenticatedHandler,kr: Optional[KeyRespository]=None): self._ke = ke self._handler = handler self._kr = kr if kr isnotNoneelse{}# en caso de no proveer un KeyRepository crea un diccionariodef_handle_handshake_msg(self,public_key:bytes) ->bytes:""" Recibe la clave publica del cliente, y la persiste en el KeyRepository. Al finalizar le retorna al cliente la clave publica del Listener. """ client_id =get_client_id(public_key).hex() self._kr[client_id]= public_key response_msg ={'handshake_msg':{'public_key':b64encode(self._ke.get_public_key()).decode('utf-8')}}return json.dumps(response_msg).encode('utf-8')def_handle_client_msg(self,client_id:str,encrypted_payload:bytes) ->bytes:""" - Obtiene la clave publica del KeyRepository a partir del client_id # self._kr.get(client_id) - Genera la clave compartida # self._ke.get_shared_key(pub_key) - Verifica y decifra el mensaje con la misma - Delega el mensaje en el AuthenticatedHandler para obtener la respuesta para el cliente - La cifra y firma la respuesta con la clave compartida - Encodea el payload cifrado en base64 - Devuelve la respuesta con el formato b'{"server_msg": {"payload": "cHVjYXJhCg==" } }' """raiseNotImplementedErrordefhandle_msg(self,msg:bytes) ->bytes:""" realiza un dispatch de los mensajes recibido, segun corresponda ver: -_handle_handshake_msg {"handshake_msg":{"public_key": "..."}} -_handle_client_msg {"client_msg":{"client_id": "...", "payload": "..."}} """ base_msg = json.loads(msg.decode('utf-8'))if base_msg.get('handshake_msg')isnotNone:return self._handle_handshake_msg(b64decode(base_msg['handshake_msg']['public_key']))elif base_msg.get('client_msg')isnotNone:return self._handle_client_msg( base_msg['client_msg']['client_id'],b64decode(base_msg['client_msg']['payload']) )else:raiseRuntimeError('Unexpected message type')
EncryptedHandler
from typing import Optionalfrom.import Handlerfrom malon_lp.crypto.sym import SymmetricCipherclassEncryptedHandler(Handler): KEY_LENGTH =16def__init__(self,key:bytes,handler: Handler):iflen(key)!= self.KEY_LENGTH:raiseRuntimeError('Invalid key length, should be {}'.format(self.KEY_LENGTH)) self._cipher =SymmetricCipher(key) self._handler = handlerdefhandle_msg(self,msg:bytes) ->bytes:""" Delega el mensaje descfirado (por la primer capa de criptografia simetrica) en el Handler siguiente. - se debe verificar y descifrar el mensaje - delegar el mensaje al Handler siguiente - finalmente se debe cifrar y firmar el mensaje, para poder devolverlo """raiseNotImplementedError