Exemple #1
0
    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,
        )
Exemple #2
0
    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)
Exemple #3
0
    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(),
        )