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
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, )
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
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