def complete_handshake(self, response_packet: Packet) -> HandshakeResult: if not self.is_response_packet(response_packet): raise ValueError( f"Packet {response_packet} is not the expected response packet" ) if not isinstance(response_packet, WhoAreYouPacket): raise TypeError( "Invariant: Only WhoAreYou packets are valid responses") who_are_you_packet = response_packet # compute session keys ( ephemeral_private_key, ephemeral_public_key, ) = self.identity_scheme.create_handshake_key_pair() remote_public_key_object = PublicKey.from_compressed_bytes( self.remote_enr.public_key) remote_public_key_uncompressed = remote_public_key_object.to_bytes() session_keys = self.identity_scheme.compute_session_keys( local_private_key=ephemeral_private_key, remote_public_key=remote_public_key_uncompressed, local_node_id=self.local_enr.node_id, remote_node_id=self.remote_node_id, id_nonce=who_are_you_packet.id_nonce, is_locally_initiated=True, ) # prepare response packet id_nonce_signature = self.identity_scheme.create_id_nonce_signature( id_nonce=who_are_you_packet.id_nonce, ephemeral_public_key=ephemeral_public_key, private_key=self.local_private_key, ) if who_are_you_packet.enr_sequence_number < self.local_enr.sequence_number: enr = self.local_enr else: enr = None auth_header_packet = AuthHeaderPacket.prepare( tag=self.tag, auth_tag=get_random_auth_tag(), id_nonce=who_are_you_packet.id_nonce, message=self.initial_message, initiator_key=session_keys.encryption_key, id_nonce_signature=id_nonce_signature, auth_response_key=session_keys.auth_response_key, enr=enr, ephemeral_public_key=ephemeral_public_key, ) return HandshakeResult( session_keys=session_keys, enr=None, message=None, auth_header_packet=auth_header_packet, )
async def handle_outgoing_message_post_handshake(self, outgoing_message: OutgoingMessage, ) -> None: if not self.is_post_handshake: raise ValueError("Can only handle message post handshake") if self.session_keys is None: raise TypeError("session_keys are None even though handshake has been completed") packet = AuthTagPacket.prepare( tag=compute_tag(self.local_node_id, self.remote_node_id), auth_tag=get_random_auth_tag(), message=outgoing_message.message, key=self.session_keys.encryption_key, ) outgoing_packet = OutgoingPacket( packet, outgoing_message.receiver_endpoint, ) self.logger.debug("Sending %s", outgoing_message) await self.outgoing_packet_send_channel.send(outgoing_packet)
def __init__( self, *, local_private_key: bytes, local_enr: ENR, remote_enr: ENR, initial_message: BaseMessage, ) -> None: super().__init__( is_initiator=True, local_enr=local_enr, local_private_key=local_private_key, remote_node_id=remote_enr.node_id, ) self.remote_enr = remote_enr self.initial_message = initial_message self.initiating_packet = AuthTagPacket.prepare_random( tag=self.tag, auth_tag=get_random_auth_tag(), random_data=get_random_encrypted_data(), )