예제 #1
0
    async def _receive_handshake_completion(
            self, packet: Packet[HandshakePacket]) -> SessionKeys:
        self.logger.debug("%s: received handshake completion", self)

        if not isinstance(packet.auth_data, HandshakePacket):
            raise Exception(f"Invalid packet type: {type(packet.auth_data)}")

        if packet.auth_data.record is not None:
            remote_enr = packet.auth_data.record
            try:
                self._enr_db.set_enr(remote_enr)
            except OldSequenceNumber:
                pass
        else:
            remote_enr = self._enr_db.get_enr(self.remote_node_id)

        handshake_scheme = self.handshake_scheme
        signature_inputs = handshake_scheme.signature_inputs_cls(
            iv=self.handshake_response_packet.iv,
            header=self.handshake_response_packet.header,
            who_are_you=self.handshake_response_packet.auth_data,
            ephemeral_public_key=packet.auth_data.ephemeral_public_key,
            recipient_node_id=self._local_node_id,
        )
        # Verify the id_nonce_signature which ensures that the remote node has
        # not lied about their node_id
        try:
            handshake_scheme.validate_id_nonce_signature(
                signature_inputs=signature_inputs,
                signature=packet.auth_data.id_signature,
                public_key=remote_enr.public_key,
            )
        except ValidationError as err:
            raise HandshakeFailure(str(err)) from err

        session_keys = handshake_scheme.compute_session_keys(
            local_private_key=self._local_private_key,
            remote_public_key=packet.auth_data.ephemeral_public_key,
            local_node_id=self._local_node_id,
            remote_node_id=self.remote_node_id,
            salt=self.handshake_response_packet.challenge_data,
            is_locally_initiated=False,
        )

        message = decode_message(
            session_keys.decryption_key,
            packet.header.aes_gcm_nonce,
            packet.message_cipher_text,
            packet.challenge_data,
            self._message_type_registry,
        )

        await self._inbound_message_send_channel.send(
            AnyInboundMessage(
                message=message,
                sender_endpoint=self.remote_endpoint,
                sender_node_id=self.remote_node_id,
            ))
        return session_keys
예제 #2
0
 def decode_message(self, packet: Packet[MessagePacket]) -> BaseMessage:
     return decode_message(
         self.keys.decryption_key,
         packet.header.aes_gcm_nonce,
         packet.message_cipher_text,
         packet.challenge_data,
         self._message_type_registry,
     )
예제 #3
0
def do_message_packet_fixture_decoding_test(fixture):
    dest_node_id = decode_hex(fixture["dest-node-id"])
    expected_auth_data = MessagePacket(source_node_id=decode_hex(
        fixture["src-node-id"]), )
    expected_message = PingMessage(
        request_id=decode_hex(fixture["packet"]["message"]["req-id"]),
        enr_seq=to_int(hexstr=fixture["packet"]["message"]["enr-seq"]),
    )
    encoded_packet = decode_hex(fixture["encoded"])
    packet = decode_packet(encoded_packet, dest_node_id)
    assert packet.auth_data == expected_auth_data

    aes_gcm_nonce = decode_hex(fixture["nonce"])

    actual_message = decode_message(
        decryption_key=decode_hex(fixture["read-key"]),
        aes_gcm_nonce=aes_gcm_nonce,
        message_cipher_text=packet.message_cipher_text,
        authenticated_data=packet.challenge_data,
    )
    assert actual_message == expected_message
예제 #4
0
def do_handshake_packet_fixture_decoding_test(fixture):
    source_node_id = decode_hex(fixture["src-node-id"])
    dest_node_id = decode_hex(fixture["dest-node-id"])
    encoded_packet = decode_hex(fixture["encoded"])
    ping_enr_seq = to_int(hexstr=fixture["packet"]["message"]["enr-seq"])
    who_are_you_enr_seq = to_int(
        hexstr=fixture["handshake-inputs"]["whoareyou"]["enr-seq"])

    if who_are_you_enr_seq == ping_enr_seq and who_are_you_enr_seq != 0:
        should_have_record = False
    else:
        should_have_record = True

    # ephemeral_private_key = decode_hex(fixture['handshake-inputs']['ephemeral-key'])
    ephemeral_public_key = decode_hex(
        fixture["handshake-inputs"]["ephemeral-pubkey"])
    # ephemeral_private_key = decode_hex(fixture["handshake-inputs"]["ephemeral-key"])

    # request_nonce = decode_hex(fixture['handshake-inputs']['whoareyou']['request-nonce'])
    challenge_data = decode_hex(
        fixture["handshake-inputs"]["whoareyou"]["challenge-data"])
    masking_iv, static_header, who_are_you = extract_challenge_data(
        challenge_data)

    id_nonce = decode_hex(fixture["handshake-inputs"]["whoareyou"]["id-nonce"])
    assert who_are_you.id_nonce == id_nonce

    aes_gcm_nonce = decode_hex(fixture["nonce"])
    # TODO: why doesn't this match
    # assert static_header.aes_gcm_nonce == aes_gcm_nonce

    signature_inputs = V4HandshakeScheme.signature_inputs_cls(
        iv=masking_iv,
        header=static_header,
        who_are_you=WhoAreYouPacket(id_nonce, who_are_you_enr_seq),
        ephemeral_public_key=ephemeral_public_key,
        recipient_node_id=dest_node_id,
    )

    id_nonce_signature = V4HandshakeScheme.create_id_nonce_signature(
        signature_inputs=signature_inputs,
        private_key=NODE_KEY_A,
    )

    packet = decode_packet(encoded_packet, dest_node_id)
    expected_auth_data = HandshakePacket(
        auth_data_head=HandshakeHeader(source_node_id, 64, 33),
        id_signature=id_nonce_signature,
        ephemeral_public_key=ephemeral_public_key,
        record=packet.auth_data.record,
    )

    assert expected_auth_data == packet.auth_data
    assert packet.header.aes_gcm_nonce == aes_gcm_nonce

    if should_have_record:
        assert packet.auth_data.record is not None
        assert packet.auth_data.record.node_id == source_node_id
    else:
        assert packet.auth_data.record is None

    expected_message = PingMessage(
        request_id=decode_hex(fixture["packet"]["message"]["req-id"]),
        enr_seq=to_int(hexstr=fixture["packet"]["message"]["enr-seq"]),
    )
    actual_message = decode_message(
        decryption_key=decode_hex(fixture["read-key"]),
        aes_gcm_nonce=aes_gcm_nonce,
        message_cipher_text=packet.message_cipher_text,
        authenticated_data=packet.challenge_data,
    )
    assert expected_message == actual_message