gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[gnunet] 01/06: MESSENGER: Separate peer and member signed messages


From: gnunet
Subject: [gnunet] 01/06: MESSENGER: Separate peer and member signed messages
Date: Tue, 14 Nov 2023 17:59:14 +0100

This is an automated email from the git hooks/post-receive script.

thejackimonster pushed a commit to branch master
in repository gnunet.

commit b56d5e12c913e32d97b6192afa14d84be6e236fb
Author: TheJackiMonster <thejackimonster@gmail.com>
AuthorDate: Fri Nov 10 18:51:20 2023 +0100

    MESSENGER: Separate peer and member signed messages
    
    Signed-off-by: TheJackiMonster <thejackimonster@gmail.com>
---
 src/identity/identity_api.c                        |  15 +-
 src/include/gnunet_crypto_lib.h                    |  35 +-
 src/include/gnunet_identity_service.h              |  12 +-
 src/include/gnunet_messenger_service.h             |  82 ++-
 src/messenger/Makefile.am                          |   6 +-
 src/messenger/gnunet-messenger.c                   |  63 ++-
 src/messenger/gnunet-service-messenger.c           | 247 +++++----
 src/messenger/gnunet-service-messenger.h           |   4 +-
 src/messenger/gnunet-service-messenger_handle.c    | 541 ++++++-------------
 src/messenger/gnunet-service-messenger_handle.h    | 108 ++--
 src/messenger/gnunet-service-messenger_member.c    |   6 +-
 .../gnunet-service-messenger_member_session.c      |  12 +-
 .../gnunet-service-messenger_member_store.c        |  10 +-
 .../gnunet-service-messenger_member_store.h        |   6 +-
 .../gnunet-service-messenger_message_handle.c      |  52 +-
 .../gnunet-service-messenger_message_handle.h      |  39 +-
 .../gnunet-service-messenger_message_kind.c        | 151 +-----
 .../gnunet-service-messenger_message_kind.h        | 105 +---
 .../gnunet-service-messenger_message_recv.c        |  30 +-
 .../gnunet-service-messenger_message_recv.h        |   4 +-
 .../gnunet-service-messenger_message_send.c        |  97 +++-
 .../gnunet-service-messenger_message_send.h        |  19 +-
 .../gnunet-service-messenger_message_store.c       |   5 +-
 src/messenger/gnunet-service-messenger_room.c      | 289 +++++-----
 src/messenger/gnunet-service-messenger_room.h      |  14 +-
 .../gnunet-service-messenger_sender_session.h      |  41 ++
 src/messenger/gnunet-service-messenger_service.c   |  50 +-
 src/messenger/gnunet-service-messenger_service.h   |  26 +-
 src/messenger/gnunet-service-messenger_tunnel.c    |   7 +-
 src/messenger/messenger_api.c                      | 547 ++++++++++++-------
 src/messenger/messenger_api_handle.c               |  79 ++-
 src/messenger/messenger_api_handle.h               |  37 +-
 src/messenger/messenger_api_list_tunnels.c         |  48 +-
 src/messenger/messenger_api_list_tunnels.h         |  25 +-
 src/messenger/messenger_api_message.c              | 582 +++++++++++----------
 src/messenger/messenger_api_message.h              |  88 +++-
 ...message_kind.c => messenger_api_message_kind.c} |  85 +--
 ...message_kind.h => messenger_api_message_kind.h} |  51 +-
 src/messenger/messenger_api_peer_store.c           | 180 +++++++
 src/messenger/messenger_api_peer_store.h           |  93 ++++
 src/messenger/messenger_api_queue_messages.c       | 104 ++++
 src/messenger/messenger_api_queue_messages.h       |  89 ++++
 src/messenger/messenger_api_room.c                 |  96 +++-
 src/messenger/messenger_api_room.h                 |  44 +-
 src/messenger/messenger_api_util.c                 |  16 +-
 src/messenger/messenger_api_util.h                 |  22 +-
 src/messenger/test_messenger.c                     |  34 +-
 src/messenger/test_messenger_anonymous.c           |  24 +-
 src/messenger/testing_messenger_setup.c            |  20 +-
 src/util/crypto_ecc_setup.c                        |  30 +-
 50 files changed, 2557 insertions(+), 1813 deletions(-)

diff --git a/src/identity/identity_api.c b/src/identity/identity_api.c
index 3a9258aa4..bfb9d40fb 100644
--- a/src/identity/identity_api.c
+++ b/src/identity/identity_api.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2013, 2016, 2021 GNUnet e.V.
+     Copyright (C) 2013, 2016, 2021, 2023 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -582,6 +582,19 @@ GNUNET_IDENTITY_ego_get_public_key (struct 
GNUNET_IDENTITY_Ego *ego,
 }
 
 
+/**
+ * Obtain the name associated with an ego.
+ *
+ * @param ego the ego
+ * @return associated name, valid as long as the ego is valid
+ */
+const char*
+GNUNET_IDENTITY_ego_get_name (const struct GNUNET_IDENTITY_Ego *ego)
+{
+  return ego->name;
+}
+
+
 struct GNUNET_IDENTITY_Operation *
 GNUNET_IDENTITY_create (struct GNUNET_IDENTITY_Handle *h,
                         const char *name,
diff --git a/src/include/gnunet_crypto_lib.h b/src/include/gnunet_crypto_lib.h
index 289aa5649..2a975a440 100644
--- a/src/include/gnunet_crypto_lib.h
+++ b/src/include/gnunet_crypto_lib.h
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2001-2013 GNUnet e.V.
+     Copyright (C) 2001-2023 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -1644,6 +1644,39 @@ GNUNET_CRYPTO_get_peer_identity (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
                                  struct GNUNET_PeerIdentity *dst);
 
 
+/**
+ * @ingroup crypto
+ * Sign a given block with a specific purpose using the host's peer identity.
+ *
+ * @param cfg configuration to use
+ * @param purpose what to sign (size, purpose)
+ * @param sig where to write the signature
+ * @return #GNUNET_OK on success, #GNUNET_SYSERR if the identity
+ *         could not be retrieved
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_sign_by_peer_identity (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+                                     const struct 
GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+                                     struct GNUNET_CRYPTO_EddsaSignature *sig);
+
+
+/**
+ * @ingroup crypto
+ * Verify a given signature with a peer's identity.
+ *
+ * @param purpose what is the purpose that the signature should have?
+ * @param validate block to validate (size, purpose, data)
+ * @param sig signature that is being validated
+ * @param identity the peer's identity to verify
+ * @return #GNUNET_OK if ok, #GNUNET_SYSERR if invalid
+ */
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_verify_peer_identity (uint32_t purpose,
+                                    const struct 
GNUNET_CRYPTO_EccSignaturePurpose * validate,
+                                    const struct GNUNET_CRYPTO_EddsaSignature 
*sig,
+                                    const struct GNUNET_PeerIdentity 
*identity);
+
+
 /**
  * Internal structure used to cache pre-calculated values for DLOG calculation.
  */
diff --git a/src/include/gnunet_identity_service.h 
b/src/include/gnunet_identity_service.h
index fd0458f62..d4192a77f 100644
--- a/src/include/gnunet_identity_service.h
+++ b/src/include/gnunet_identity_service.h
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2013 GNUnet e.V.
+     Copyright (C) 2013--2023 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -206,6 +206,16 @@ GNUNET_IDENTITY_ego_get_public_key (struct 
GNUNET_IDENTITY_Ego *ego,
                                     struct GNUNET_IDENTITY_PublicKey *pk);
 
 
+/**
+ * Obtain the name associated with an ego.
+ *
+ * @param ego the ego
+ * @return associated name, valid as long as the ego is valid
+ */
+const char*
+GNUNET_IDENTITY_ego_get_name (const struct GNUNET_IDENTITY_Ego *ego);
+
+
 /**
  * Method called to inform about the egos of this peer.
  *
diff --git a/src/include/gnunet_messenger_service.h 
b/src/include/gnunet_messenger_service.h
index 5f4207d2f..475f8e32e 100644
--- a/src/include/gnunet_messenger_service.h
+++ b/src/include/gnunet_messenger_service.h
@@ -42,7 +42,6 @@ extern "C" {
 #include "gnunet_common.h"
 #include "gnunet_configuration_lib.h"
 #include "gnunet_identity_service.h"
-#include "gnunet_protocols.h"
 #include "gnunet_scheduler_lib.h"
 #include "gnunet_time_lib.h"
 #include "gnunet_util_lib.h"
@@ -50,9 +49,9 @@ extern "C" {
 /**
  * Version number of GNUnet Messenger API.
  *
- * Current version of the Messenger: 0.2
+ * Current version of the Messenger: 0.3
  */
-#define GNUNET_MESSENGER_VERSION 0x00000002
+#define GNUNET_MESSENGER_VERSION 0x00000003
 
 /**
  * Identifier of GNUnet MESSENGER Service.
@@ -255,11 +254,6 @@ struct GNUNET_MESSENGER_MessageHeader
  */
 struct GNUNET_MESSENGER_MessageInfo
 {
-  /**
-   * The senders key to verify its signatures.
-   */
-  struct GNUNET_IDENTITY_PublicKey host_key;
-
   /**
    * The version of GNUnet Messenger API.
    *
@@ -462,6 +456,10 @@ struct GNUNET_MESSENGER_MessageFile
  */
 struct GNUNET_MESSENGER_MessagePrivate
 {
+  /**
+   * The ECDH key to decrypt the message.
+   */
+  struct GNUNET_CRYPTO_EcdhePublicKey key;
 
   /**
    * The length of the encrypted message.
@@ -554,18 +552,12 @@ enum GNUNET_MESSENGER_MessageFlags
    * The private flag. The flag indicates that the message was privately 
encrypted.
    */
   GNUNET_MESSENGER_FLAG_PRIVATE = 2,
-};
 
-/**
- * Method called whenever the EGO of a <i>handle</i> changes or if the first 
connection fails
- * to load a valid EGO and the anonymous key pair will be used instead.
- *
- * @param[in/out] cls Closure from #GNUNET_MESSENGER_connect
- * @param[in/out] handle Messenger handle
- */
-typedef void
-(*GNUNET_MESSENGER_IdentityCallback) (void *cls,
-                                      struct GNUNET_MESSENGER_Handle *handle);
+  /**
+   * The peer flag. The flag indicates that the message was sent by a peer and 
not a member.
+   */
+  GNUNET_MESSENGER_FLAG_PEER = 4,
+};
 
 /**
  * Method called whenever a message is sent or received from a <i>room</i>.
@@ -602,13 +594,12 @@ typedef int
                                     const struct GNUNET_MESSENGER_Contact 
*contact);
 
 /**
- * Set up a handle for the messenger related functions and connects to all 
necessary services. It will look up the ego
- * key identified by its <i>name</i> and use it for signing all messages from 
the handle.
+ * Set up a handle for the messenger related functions and connects to all 
necessary services. It will use the
+ * a custom name in combination of a private key provided for signing all 
messages from the handle.
  *
  * @param[in] cfg Configuration to use
- * @param[in] name Name to look up an ego or NULL to stay anonymous
- * @param[in] identity_callback Function called when the EGO of the handle 
changes
- * @param[in,out] identity_cls Closure for the <i>identity_callback</i> handler
+ * @param[in] name Name or NULL
+ * @param[in] key Private key or NULL to stay anonymous
  * @param[in] msg_callback Function called when a new message is sent or 
received
  * @param[in,out] msg_cls Closure for the <i>msg_callback</i> handler
  * @return Messenger handle to use, NULL on error
@@ -616,25 +607,10 @@ typedef int
 struct GNUNET_MESSENGER_Handle*
 GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                           const char *name,
-                          GNUNET_MESSENGER_IdentityCallback identity_callback,
-                          void *identity_cls,
+                          const struct GNUNET_IDENTITY_PrivateKey *key,
                           GNUNET_MESSENGER_MessageCallback msg_callback,
                           void *msg_cls);
 
-/**
- * Update a handle of the messenger to use a different ego key and replace the 
old one with a newly generated one. All
- * participated rooms get informed about the key renewal. The handle requires 
a set name for this function to work and
- * it needs to be unused by other egos.
- *
- * Keep in mind that this will fully delete the old ego key (if any is used) 
even if any other service wants to use it
- * as default.
- *
- * @param[in,out] handle Messenger handle to use
- * @return #GNUNET_OK on success, #GNUNET_SYSERR on failure
- */
-int
-GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle);
-
 /**
  * Disconnect all of the messengers used services and clears up its used 
memory.
  *
@@ -653,9 +629,8 @@ const char*
 GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle);
 
 /**
- * Set the name for the messenger. This will rename the currently used ego and 
move all stored files related to the current
- * name to its new directory. If anything fails during this process the 
function returns #GNUNET_NO and the name for
- * the messenger won't change as specified.
+ * Set the name for the messenger handle and sends messages renaming your 
contact in currently
+ * open rooms.
  *
  * @param[in,out] handle Messenger handle to use
  * @param[in] name Name for the messenger to change to
@@ -669,11 +644,24 @@ GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle 
*handle,
  * Get the public key used by the messenger or NULL if the anonymous key was 
used.
  *
  * @param[in] handle Messenger handle to use
- * @return Used ego's public key or NULL
+ * @return Used public key or NULL
  */
 const struct GNUNET_IDENTITY_PublicKey*
 GNUNET_MESSENGER_get_key (const struct GNUNET_MESSENGER_Handle *handle);
 
+/**
+ * Set the private key used by the messenger or NULL if the anonymous key 
should be
+ * used instead. The currently used key will be replaced and the change will 
get signed
+ * accordingly to be verified by all contacts.
+ *
+ * @param[in,out] handle Messenger handle to use
+ * @param[in] key Private key to change to or NULL
+ * @return #GNUNET_YES on success, #GNUNET_NO on failure and #GNUNET_SYSERR if 
<i>handle</i> is NULL
+ */
+int
+GNUNET_MESSENGER_set_key (struct GNUNET_MESSENGER_Handle *handle,
+                          const struct GNUNET_IDENTITY_PrivateKey *key);
+
 /**
  * Open a room to send and receive messages. The room will use the specified 
<i>key</i> as port for the underlying cadet
  * service. Opening a room results in opening the port for incoming 
connections as possible <b>door</b>.
@@ -781,7 +769,7 @@ GNUNET_MESSENGER_contact_get_name (const struct 
GNUNET_MESSENGER_Contact *contac
  * Get the public key used by the <i>contact</i> or NULL if the anonymous key 
was used.
  *
  * @param[in] contact Contact handle
- * @return Public key of the ego used by <i>contact</i> or NULL
+ * @return Public key used by <i>contact</i> or NULL
  */
 const struct GNUNET_IDENTITY_PublicKey*
 GNUNET_MESSENGER_contact_get_key (const struct GNUNET_MESSENGER_Contact 
*contact);
@@ -801,12 +789,12 @@ GNUNET_MESSENGER_contact_get_key (const struct 
GNUNET_MESSENGER_Contact *contact
  * Sending a message to all members in a given room can be done by providing 
NULL as contact.
  *
  * @param[in,out] room Room handle
- * @param[in] message New message to send
+ * @param[in,out] message New message to send
  * @param[in] contact Contact or NULL
  */
 void
 GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
-                               const struct GNUNET_MESSENGER_Message *message,
+                               struct GNUNET_MESSENGER_Message *message,
                                const struct GNUNET_MESSENGER_Contact* contact);
 
 /**
diff --git a/src/messenger/Makefile.am b/src/messenger/Makefile.am
index 4be11f3aa..43852caef 100644
--- a/src/messenger/Makefile.am
+++ b/src/messenger/Makefile.am
@@ -43,11 +43,13 @@ lib_LTLIBRARIES = \
 
 libgnunetmessenger_la_SOURCES = \
   messenger_api.c \
-  messenger_api_ego.h \
   messenger_api_contact.c messenger_api_contact.h \
   messenger_api_contact_store.c messenger_api_contact_store.h \
+  messenger_api_peer_store.c messenger_api_peer_store.h \
   messenger_api_message.c messenger_api_message.h \
+  messenger_api_message_kind.c messenger_api_message_kind.h \
   messenger_api_list_tunnels.c messenger_api_list_tunnels.h \
+  messenger_api_queue_messages.c messenger_api_queue_messages.h \
   messenger_api_util.c messenger_api_util.h \
   messenger_api_handle.c messenger_api_handle.h \
   messenger_api_room.c messenger_api_room.h
@@ -75,6 +77,7 @@ gnunet_service_messenger_SOURCES = \
   gnunet-service-messenger_list_handles.c 
gnunet-service-messenger_list_handles.h \
   gnunet-service-messenger_list_messages.c 
gnunet-service-messenger_list_messages.h \
   gnunet-service-messenger_member_session.c 
gnunet-service-messenger_member_session.h \
+  gnunet-service-messenger_sender_session.h \
   gnunet-service-messenger_member.c gnunet-service-messenger_member.h \
   gnunet-service-messenger_member_store.c 
gnunet-service-messenger_member_store.h \
   gnunet-service-messenger_message_handle.c 
gnunet-service-messenger_message_handle.h \
@@ -86,7 +89,6 @@ gnunet_service_messenger_SOURCES = \
   gnunet-service-messenger_operation_store.c 
gnunet-service-messenger_operation_store.h \
   gnunet-service-messenger_operation.c gnunet-service-messenger_operation.h \
   gnunet-service-messenger_basement.c gnunet-service-messenger_basement.h \
-  gnunet-service-messenger_ego_store.c gnunet-service-messenger_ego_store.h \
   gnunet-service-messenger_handle.c gnunet-service-messenger_handle.h \
   gnunet-service-messenger_room.c gnunet-service-messenger_room.h \
   gnunet-service-messenger_tunnel.c gnunet-service-messenger_tunnel.h
diff --git a/src/messenger/gnunet-messenger.c b/src/messenger/gnunet-messenger.c
index 9444fa12d..0fa706319 100644
--- a/src/messenger/gnunet-messenger.c
+++ b/src/messenger/gnunet-messenger.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -29,6 +29,7 @@
 #include "gnunet_util_lib.h"
 #include "gnunet_messenger_service.h"
 
+const struct GNUNET_CONFIGURATION_Handle *config;
 struct GNUNET_MESSENGER_Handle *messenger;
 
 /**
@@ -54,6 +55,8 @@ on_message (void *cls,
   if (!sender_name)
     sender_name = "anonymous";
 
+  printf ("[%s ->", GNUNET_h2s(&(message->header.previous)));
+  printf (" %s]", GNUNET_h2s(hash));
   printf ("[%s] ", GNUNET_sh2s(&(message->header.sender_id)));
 
   if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
@@ -97,9 +100,26 @@ on_message (void *cls,
       break;
     }
   }
+
+  if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) && (flags & 
GNUNET_MESSENGER_FLAG_SENT))
+  {
+    const char* name = GNUNET_MESSENGER_get_name (messenger);
+
+    if (!name)
+      return;
+
+    struct GNUNET_MESSENGER_Message response;
+    response.header.kind = GNUNET_MESSENGER_KIND_NAME;
+    response.body.name.name = GNUNET_strdup (name);
+
+    GNUNET_MESSENGER_send_message (room, &response, NULL);
+
+    GNUNET_free (response.body.name.name);
+  }
 }
 
 struct GNUNET_SCHEDULER_Task *read_task;
+struct GNUNET_IDENTITY_EgoLookup *ego_lookup;
 
 /**
  * Task to shut down this application.
@@ -119,6 +139,9 @@ shutdown_hook (void *cls)
 
   if (messenger)
     GNUNET_MESSENGER_disconnect (messenger);
+  
+  if (ego_lookup)
+    GNUNET_IDENTITY_ego_lookup_cancel (ego_lookup);
 }
 
 static void
@@ -276,18 +299,26 @@ on_identity (void *cls,
     GNUNET_SCHEDULER_shutdown ();
   else
   {
-    struct GNUNET_MESSENGER_Message message;
-    message.header.kind = GNUNET_MESSENGER_KIND_NAME;
-    message.body.name.name = GNUNET_strdup(name);
-
-    GNUNET_MESSENGER_send_message (room, &message, NULL);
-    GNUNET_free(message.body.name.name);
-
     GNUNET_SCHEDULER_add_delayed_with_priority (GNUNET_TIME_relative_get_zero_ 
(), GNUNET_SCHEDULER_PRIORITY_IDLE, idle,
                                                 room);
   }
 }
 
+static void
+on_ego_lookup (void *cls,
+               struct GNUNET_IDENTITY_Ego *ego)
+{
+  ego_lookup = NULL;
+
+  const struct GNUNET_IDENTITY_PrivateKey *key;
+  key = ego ? GNUNET_IDENTITY_ego_get_private_key (ego) : NULL;
+
+  messenger = GNUNET_MESSENGER_connect (config, ego_name, key, &on_message, 
NULL);
+
+  on_identity (NULL, messenger);
+}
+
+
 /**
  * Main function that will be run by the scheduler.
  *
@@ -302,9 +333,23 @@ run (void *cls,
      const char *cfgfile,
      const struct GNUNET_CONFIGURATION_Handle *cfg)
 {
-  messenger = GNUNET_MESSENGER_connect (cfg, ego_name, &on_identity, NULL, 
&on_message, NULL);
+  config = cfg;
+
+  if (ego_name)
+  {
+    ego_lookup = GNUNET_IDENTITY_ego_lookup (cfg, ego_name, &on_ego_lookup, 
NULL);
+    messenger = NULL;
+  }
+  else
+  {
+    ego_lookup = NULL;
+    messenger = GNUNET_MESSENGER_connect (cfg, NULL, NULL, &on_message, NULL);
+  }
 
   shutdown_task = GNUNET_SCHEDULER_add_shutdown (shutdown_hook, NULL);
+
+  if (messenger)
+    on_identity (NULL, messenger);
 }
 
 /**
diff --git a/src/messenger/gnunet-service-messenger.c 
b/src/messenger/gnunet-service-messenger.c
index f0bb853d7..0b447f3cf 100644
--- a/src/messenger/gnunet-service-messenger.c
+++ b/src/messenger/gnunet-service-messenger.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -27,9 +27,9 @@
 #include "gnunet-service-messenger.h"
 
 #include "gnunet-service-messenger_handle.h"
-#include "gnunet-service-messenger_message_kind.h"
 #include "gnunet-service-messenger_service.h"
 #include "messenger_api_message.h"
+#include "messenger_api_message_kind.h"
 
 struct GNUNET_MESSENGER_Client
 {
@@ -39,36 +39,13 @@ struct GNUNET_MESSENGER_Client
 
 struct GNUNET_MESSENGER_Service *messenger;
 
-static int
-check_create (void *cls,
-              const struct GNUNET_MESSENGER_CreateMessage *msg)
-{
-  GNUNET_MQ_check_zero_termination (msg);
-  return GNUNET_OK;
-}
-
 static void
 handle_create (void *cls,
                const struct GNUNET_MESSENGER_CreateMessage *msg)
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
-  const char *name = ((const char*) msg) + sizeof(*msg);
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handle created with name: %s\n", name);
-
-  setup_srv_handle_name (msg_client->handle, strlen (name) > 0 ? name : NULL);
-
-  GNUNET_SERVICE_client_continue (msg_client->client);
-}
-
-static void
-handle_update (void *cls,
-               const struct GNUNET_MESSENGER_UpdateMessage *msg)
-{
-  struct GNUNET_MESSENGER_Client *msg_client = cls;
-
-  update_srv_handle (msg_client->handle);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handle created\n");
 
   GNUNET_SERVICE_client_continue (msg_client->client);
 }
@@ -79,30 +56,63 @@ handle_destroy (void *cls,
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handle destroyed\n");
+
   GNUNET_SERVICE_client_drop (msg_client->client);
 }
 
 static int
-check_set_name (void *cls,
-                const struct GNUNET_MESSENGER_NameMessage *msg)
+check_room_initial_key (const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
-  GNUNET_MQ_check_zero_termination (msg);
-  return GNUNET_OK;
+  const uint16_t full_length = ntohs (msg->header.size);
+
+  if (full_length < sizeof(*msg))
+    return GNUNET_NO;
+
+  const uint16_t msg_length = full_length - sizeof(*msg);
+  const char *msg_buffer = ((const char*) msg) + sizeof(*msg);
+
+  if (0 == msg_length)
+    return GNUNET_OK;
+
+  struct GNUNET_IDENTITY_PublicKey key;
+  size_t key_len;
+
+  if (GNUNET_OK != GNUNET_IDENTITY_read_public_key_from_buffer(msg_buffer, 
msg_length, &key, &key_len))
+    return GNUNET_NO;
+
+  return key_len == msg_length ? GNUNET_OK : GNUNET_NO;
 }
 
 static void
-handle_set_name (void *cls,
-                 const struct GNUNET_MESSENGER_NameMessage *msg)
+initialize_handle_via_key (struct GNUNET_MESSENGER_SrvHandle *handle,
+                           const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
-  struct GNUNET_MESSENGER_Client *msg_client = cls;
+  GNUNET_assert (handle);
 
-  const char *name = ((const char*) msg) + sizeof(*msg);
+  const uint16_t full_length = ntohs (msg->header.size);
+  const uint16_t msg_length = full_length - sizeof(*msg);
+  const char *msg_buffer = ((const char*) msg) + sizeof(*msg);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Handles name is now: %s\n", name);
+  if (msg_length > 0)
+  {
+    struct GNUNET_IDENTITY_PublicKey key;
+    size_t key_len;
 
-  set_srv_handle_name (msg_client->handle, name);
+    if (GNUNET_OK == GNUNET_IDENTITY_read_public_key_from_buffer(msg_buffer, 
msg_length, &key, &key_len))
+      set_srv_handle_key(handle, &key);
+    else
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Initialization failed while 
reading invalid key!\n");
+  }
+  else
+    GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Initialization is missing key!\n");
+}
 
-  GNUNET_SERVICE_client_continue (msg_client->client);
+static int
+check_room_open (void *cls,
+                 const struct GNUNET_MESSENGER_RoomMessage *msg)
+{
+  return check_room_initial_key (msg);
 }
 
 static void
@@ -111,6 +121,8 @@ handle_room_open (void *cls,
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
+  initialize_handle_via_key (msg_client->handle, msg);
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Opening room: %s\n", GNUNET_h2s (
                 &(msg->key)));
 
@@ -136,12 +148,21 @@ handle_room_open (void *cls,
   GNUNET_SERVICE_client_continue (msg_client->client);
 }
 
+static int
+check_room_entry (void *cls,
+                  const struct GNUNET_MESSENGER_RoomMessage *msg)
+{
+  return check_room_initial_key (msg);
+}
+
 static void
 handle_room_entry (void *cls,
                    const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
+  initialize_handle_via_key (msg_client->handle, msg);
+
   GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entering room: %s, %s\n", GNUNET_h2s (
                 &(msg->key)), GNUNET_i2s (&(msg->door)));
 
@@ -207,40 +228,22 @@ check_send_message (void *cls,
   if (full_length < sizeof(*msg))
     return GNUNET_NO;
 
-  const enum GNUNET_MESSENGER_MessageFlags flags = (
-    (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
-    );
-
-  const uint16_t length = full_length - sizeof(*msg);
-  const char *buffer = ((const char*) msg) + sizeof(*msg);
-  struct GNUNET_IDENTITY_PublicKey public_key;
-
-
-  size_t key_length = 0;
-
-  if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE))
-    if (GNUNET_SYSERR ==
-        GNUNET_IDENTITY_read_public_key_from_buffer (buffer, length,
-                                                     &public_key,
-                                                     &key_length))
-      return GNUNET_NO;
-
-  const uint16_t msg_length = length - key_length;
-  const char *msg_buffer = buffer + key_length;
+  const uint16_t msg_length = full_length - sizeof(*msg);
+  const char *msg_buffer = ((const char*) msg) + sizeof(*msg);
 
   struct GNUNET_MESSENGER_Message message;
 
-  if (length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, 
GNUNET_NO))
+  if (msg_length < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, 
GNUNET_YES))
     return GNUNET_NO;
 
-  if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, 
GNUNET_NO,
+  if (GNUNET_YES != decode_message (&message, msg_length, msg_buffer, 
GNUNET_YES,
                                     NULL))
     return GNUNET_NO;
 
   const int allowed = filter_message_sending (&message);
 
   cleanup_message (&message);
-  return GNUNET_YES == allowed? GNUNET_OK : GNUNET_NO;
+  return GNUNET_SYSERR != allowed? GNUNET_OK : GNUNET_NO;
 }
 
 static void
@@ -249,44 +252,17 @@ handle_send_message (void *cls,
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
-  const enum GNUNET_MESSENGER_MessageFlags flags = (
-    (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
-    );
-
   const struct GNUNET_HashCode *key = &(msg->key);
-  const char *buffer = ((const char*) msg) + sizeof(*msg);
-
-  const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
-  size_t key_length = 0;
-
-  struct GNUNET_IDENTITY_PublicKey public_key;
-
-  if (flags & GNUNET_MESSENGER_FLAG_PRIVATE)
-  {
-    GNUNET_assert (GNUNET_SYSERR !=
-                   GNUNET_IDENTITY_read_public_key_from_buffer (buffer,
-                                                                length,
-                                                                &public_key,
-                                                                &key_length));
-  }
-  const uint16_t msg_length = length - key_length;
-  const char*msg_buffer = buffer + key_length;
+  const char *msg_buffer = ((const char*) msg) + sizeof(*msg);
+  const uint16_t msg_length = ntohs (msg->header.size) - sizeof(*msg);
 
   struct GNUNET_MESSENGER_Message message;
-  decode_message (&message, msg_length, msg_buffer, GNUNET_NO, NULL);
-
-  if ((flags & GNUNET_MESSENGER_FLAG_PRIVATE) &&
-      (GNUNET_YES != encrypt_message (&message, &public_key)))
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
-                "Encrypting message failed: Message got dropped!\n");
+  decode_message (&message, msg_length, msg_buffer, GNUNET_YES, NULL);
 
-    goto end_handling;
-  }
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s\n",
-              GNUNET_MESSENGER_name_of_kind (message.header.kind), GNUNET_h2s (
-                key));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message: %s to %s (by %s)\n",
+              GNUNET_MESSENGER_name_of_kind (message.header.kind),
+              GNUNET_h2s (key),
+              GNUNET_sh2s (&(message.header.sender_id)));
 
   if (GNUNET_YES != send_srv_handle_message (msg_client->handle, key, 
&message))
     GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sending message failed: %s to %s\n",
@@ -307,30 +283,49 @@ callback_found_message (void *cls,
 {
   struct GNUNET_MESSENGER_Client *msg_client = cls;
 
-  if (! message)
+  if (!message)
   {
-    send_srv_room_message (room, msg_client->handle, create_message_request (
-                             hash));
+    struct GNUNET_MESSENGER_GetMessage *response;
+    struct GNUNET_MQ_Envelope *env;
+
+    env = GNUNET_MQ_msg (response, 
GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE);
+    GNUNET_memcpy(&(response->key), &(room->key), sizeof(room->key));
+    GNUNET_memcpy(&(response->hash), hash, sizeof(*hash));
+    GNUNET_MQ_send (msg_client->handle->mq, env);
     return;
   }
 
-  struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store 
(room);
-
-  struct GNUNET_MESSENGER_Member *member = get_store_member_of (store, 
message);
+  struct GNUNET_MESSENGER_SenderSession session;
 
-  if (! member)
+  if (GNUNET_YES == is_peer_message (message))
   {
-    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n",
-                GNUNET_h2s (hash));
-    return;
+    struct GNUNET_MESSENGER_PeerStore *store = get_srv_room_peer_store (room);
+
+    session.peer = get_store_peer_of (store, message, hash);
+
+    if (!session.peer)
+      return;
   }
+  else
+  {
+    struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store 
(room);
+    struct GNUNET_MESSENGER_Member *member = get_store_member_of (store, 
message);
+
+    if (!member)
+    {
+      GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Sender of message (%s) unknown!\n",
+                  GNUNET_h2s (hash));
+      return;
+    }
 
-  struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of (
-    member, message, hash);
+    session.member = get_member_session_of (member, message, hash);
 
-  if (session)
-    notify_srv_handle_message (msg_client->handle, room, session, message,
-                               hash);
+    if (!session.member)
+      return;
+  }
+
+  notify_srv_handle_message (msg_client->handle, room, &session, message,
+                             hash);
 }
 
 static void
@@ -369,13 +364,17 @@ handle_get_message (void *cls,
     goto end_handling;
   }
 
+  const struct GNUNET_IDENTITY_PublicKey* pubkey = 
get_srv_handle_key(msg_client->handle);
+
+  if (! pubkey)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                "Handle needs to have a public key to request a message!\n");
+    goto end_handling;
+  }
+
   struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member,
-                                                                       &(
-                                                                         
get_srv_handle_ego (
-                                                                           
msg_client
-                                                                           ->
-                                                                           
handle)
-                                                                         
->pub));
+                                                                       pubkey);
 
   if (! session)
   {
@@ -445,24 +444,16 @@ GNUNET_SERVICE_MAIN (
   &callback_client_connect,
   &callback_client_disconnect,
   NULL,
-  GNUNET_MQ_hd_var_size (create,
-                         GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, 
struct
-                         GNUNET_MESSENGER_CreateMessage, NULL),
-  GNUNET_MQ_hd_fixed_size (update,
-                           GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE,
-                           struct
-                           GNUNET_MESSENGER_UpdateMessage, NULL),
+  GNUNET_MQ_hd_fixed_size (create,
+                           GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE, 
struct
+                           GNUNET_MESSENGER_CreateMessage, NULL),
   GNUNET_MQ_hd_fixed_size (destroy,
                            GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_DESTROY,
                            struct
                            GNUNET_MESSENGER_DestroyMessage, NULL),
-  GNUNET_MQ_hd_var_size (set_name,
-                         GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME,
-                         struct
-                         GNUNET_MESSENGER_NameMessage, NULL),
-  GNUNET_MQ_hd_fixed_size (room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
+  GNUNET_MQ_hd_var_size (room_open, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN,
                            struct GNUNET_MESSENGER_RoomMessage, NULL),
-  GNUNET_MQ_hd_fixed_size (room_entry, 
GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
+  GNUNET_MQ_hd_var_size (room_entry, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY,
                            struct GNUNET_MESSENGER_RoomMessage, NULL),
   GNUNET_MQ_hd_fixed_size (room_close, 
GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE,
                            struct GNUNET_MESSENGER_RoomMessage, NULL),
diff --git a/src/messenger/gnunet-service-messenger.h 
b/src/messenger/gnunet-service-messenger.h
index 1db5c651c..a3e683ecd 100644
--- a/src/messenger/gnunet-service-messenger.h
+++ b/src/messenger/gnunet-service-messenger.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -92,6 +92,7 @@ struct GNUNET_MESSENGER_MemberMessage
 
   struct GNUNET_HashCode key;
   struct GNUNET_ShortHashCode id;
+  uint32_t reset;
 };
 
 /**
@@ -102,7 +103,6 @@ struct GNUNET_MESSENGER_SendMessage
   struct GNUNET_MessageHeader header;
 
   struct GNUNET_HashCode key;
-  uint32_t flags;
 };
 
 /**
diff --git a/src/messenger/gnunet-service-messenger_handle.c 
b/src/messenger/gnunet-service-messenger_handle.c
index 17692761d..ddb437b7e 100644
--- a/src/messenger/gnunet-service-messenger_handle.c
+++ b/src/messenger/gnunet-service-messenger_handle.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -27,10 +27,15 @@
 #include "gnunet-service-messenger_handle.h"
 
 #include "gnunet-service-messenger.h"
-#include "gnunet-service-messenger_message_kind.h"
-
+#include "messenger_api_message_kind.h"
 #include "messenger_api_util.h"
 
+struct GNUNET_MESSENGER_NextMemberId
+{
+  struct GNUNET_ShortHashCode id;
+  enum GNUNET_GenericReturnValue reset;
+};
+
 struct GNUNET_MESSENGER_SrvHandle*
 create_srv_handle (struct GNUNET_MESSENGER_Service *service,
                    struct GNUNET_MQ_Handle *mq)
@@ -42,10 +47,10 @@ create_srv_handle (struct GNUNET_MESSENGER_Service *service,
   handle->service = service;
   handle->mq = mq;
 
-  handle->name = NULL;
-  handle->ego = NULL;
-
   handle->member_ids = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
+  handle->next_ids = GNUNET_CONTAINER_multihashmap_create (4, GNUNET_NO);
+
+  handle->notify = NULL;
 
   return handle;
 }
@@ -65,22 +70,42 @@ destroy_srv_handle (struct GNUNET_MESSENGER_SrvHandle 
*handle)
 {
   GNUNET_assert(handle);
 
-  if (handle->service->dir)
-    save_srv_handle_configuration (handle);
+  if (handle->notify)
+    GNUNET_SCHEDULER_cancel(handle->notify);
 
-  if (handle->name)
-  {
-    struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
+  GNUNET_CONTAINER_multihashmap_iterate (handle->next_ids, 
iterate_free_member_ids, NULL);
+  GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, 
iterate_free_member_ids, NULL);
+
+  GNUNET_CONTAINER_multihashmap_destroy (handle->next_ids);
+  GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
 
-    unbind_store_ego(store, handle->name, handle);
+  GNUNET_free(handle);
+}
+
+void
+set_srv_handle_key (struct GNUNET_MESSENGER_SrvHandle *handle,
+                    const struct GNUNET_IDENTITY_PublicKey *key)
+{
+  GNUNET_assert(handle);
 
-    GNUNET_free(handle->name);
+  if ((handle->key) && (!key))
+  {
+    GNUNET_free(handle->key);
+    handle->key = NULL;
   }
+  else if (!handle->key)
+    handle->key = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
 
-  GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, 
iterate_free_member_ids, NULL);
-  GNUNET_CONTAINER_multihashmap_destroy (handle->member_ids);
+  if (key)
+    memcpy(handle->key, key, sizeof(struct GNUNET_IDENTITY_PublicKey));
+}
 
-  GNUNET_free(handle);
+const struct GNUNET_IDENTITY_PublicKey*
+get_srv_handle_key (const struct GNUNET_MESSENGER_SrvHandle *handle)
+{
+  GNUNET_assert(handle);
+
+  return handle->key;
 }
 
 void
@@ -156,7 +181,7 @@ change_srv_handle_member_id (struct 
GNUNET_MESSENGER_SrvHandle *handle,
   }
 
   if (0 == GNUNET_memcmp(unique_id, member_id))
-    goto send_message_to_client;
+    return GNUNET_OK;
 
   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Change a member id (%s) for room 
(%s).\n", GNUNET_sh2s (member_id),
              GNUNET_h2s (key));
@@ -164,264 +189,70 @@ change_srv_handle_member_id (struct 
GNUNET_MESSENGER_SrvHandle *handle,
   GNUNET_memcpy(member_id, unique_id, sizeof(*unique_id));
 
   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member id changed to (%s).\n", 
GNUNET_sh2s (unique_id));
-
-  struct GNUNET_MESSENGER_MemberMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-send_message_to_client:
-
-  env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
-
-  GNUNET_memcpy(&(msg->key), key, sizeof(*key));
-  GNUNET_memcpy(&(msg->id), member_id, sizeof(*member_id));
-
-  GNUNET_MQ_send (handle->mq, env);
   return GNUNET_OK;
 }
 
-static void
-change_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
-                    const char *name)
-{
-  GNUNET_assert(handle);
-
-  if (handle->name)
-    GNUNET_free(handle->name);
-
-  handle->name = name ? GNUNET_strdup(name) : NULL;
-
-  const uint16_t name_len = handle->name ? strlen (handle->name) : 0;
-
-  struct GNUNET_MESSENGER_NameMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  env = GNUNET_MQ_msg_extra(msg, name_len + 1, 
GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME);
-
-  char *extra = ((char*) msg) + sizeof(*msg);
-
-  if (name_len)
-    GNUNET_memcpy(extra, handle->name, name_len);
-
-  extra[name_len] = '\0';
-
-  GNUNET_MQ_send (handle->mq, env);
-}
-
-static void
-change_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
-                   const struct GNUNET_MESSENGER_Ego *ego)
-{
-  GNUNET_assert(handle);
-
-  handle->ego = ego;
-
-  ego = get_srv_handle_ego (handle);
-
-  const uint16_t length = GNUNET_IDENTITY_public_key_get_length(&(ego->pub));
-
-  struct GNUNET_MESSENGER_KeyMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  env = GNUNET_MQ_msg_extra(msg, length, 
GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY);
-
-  char *extra = ((char*) msg) + sizeof(*msg);
-
-  if (GNUNET_IDENTITY_write_public_key_to_buffer(&(ego->pub), extra, length) < 
0)
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Could not write key to buffer.\n");
-
-  GNUNET_MQ_send (handle->mq, env);
-}
-
-struct GNUNET_MESSENGER_MessageHandle
+struct RoomInitializationClosure
 {
   struct GNUNET_MESSENGER_SrvHandle *handle;
-  struct GNUNET_MESSENGER_Message *message;
+  const struct GNUNET_HashCode *key;
+  const struct GNUNET_IDENTITY_PublicKey *pubkey;
 };
 
 static int
-iterate_send_message (void *cls,
-                      const struct GNUNET_HashCode *key,
-                      void *value)
-{
-  struct GNUNET_MESSENGER_MessageHandle *msg_handle = cls;
-
-  send_srv_handle_message (msg_handle->handle, key, msg_handle->message);
-
-  return GNUNET_YES;
-}
-
-void
-set_srv_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
-                    const struct GNUNET_MESSENGER_Ego *ego)
+find_member_session_in_room (void *cls,
+                             const struct GNUNET_IDENTITY_PublicKey 
*public_key,
+                             struct GNUNET_MESSENGER_MemberSession *session)
 {
-  GNUNET_assert((handle) && (ego));
-
-  struct GNUNET_MESSENGER_MessageHandle msg_handle;
-
-  msg_handle.handle = handle;
-  msg_handle.message = create_message_key (&(ego->priv));
-
-  GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, 
iterate_send_message, &msg_handle);
-
-  destroy_message (msg_handle.message);
+  struct RoomInitializationClosure *init = cls;
 
-  change_handle_ego (handle, ego);
-}
+  if (!public_key)
+    return GNUNET_YES;
 
-const struct GNUNET_MESSENGER_Ego*
-get_srv_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle)
-{
-  GNUNET_assert(handle);
+  const struct GNUNET_IDENTITY_PublicKey *pubkey = 
get_srv_handle_key(init->handle);
 
-  static struct GNUNET_MESSENGER_Ego anonymous;
-  static int read_keys = 0;
+  if (0 != GNUNET_memcmp(pubkey, public_key))
+    return GNUNET_YES;
 
-  if (handle->ego)
-    return handle->ego;
+  const struct GNUNET_ShortHashCode *id = get_member_session_id(session);
 
-  if (!read_keys)
+  if (!id)
   {
-    struct GNUNET_IDENTITY_Ego *ego = GNUNET_IDENTITY_ego_get_anonymous ();
-    GNUNET_memcpy(&(anonymous.priv), GNUNET_IDENTITY_ego_get_private_key 
(ego), sizeof(anonymous.priv));
-    GNUNET_IDENTITY_ego_get_public_key (ego, &(anonymous.pub));
-    read_keys = 1;
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialitation: Missing member id!");
+    return GNUNET_NO;
   }
 
-  return &anonymous;
-}
+  GNUNET_log (GNUNET_ERROR_TYPE_INFO, "Initialitation: Matching member found 
(%s)!\n",
+              GNUNET_sh2s(id));
 
-static void
-callback_setup_handle_name (void *cls,
-                            const char *name,
-                            const struct GNUNET_MESSENGER_Ego *ego)
-{
-  struct GNUNET_MESSENGER_SrvHandle *handle = cls;
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Setting up handle...\n");
-
-  change_handle_name (handle, name);
-  change_handle_ego (handle, ego);
-
-  if (handle->service->dir)
-    load_srv_handle_configuration (handle);
-}
-
-void
-setup_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
-                       const char *name)
-{
-  GNUNET_assert(handle);
-
-  struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
-
-  lookup_store_ego (store, name, callback_setup_handle_name, handle);
+  change_srv_handle_member_id(init->handle, init->key, id);
+  return GNUNET_NO;
 }
 
 static void
-callback_update_handle (void *cls,
-                        const char *name,
-                        const struct GNUNET_MESSENGER_Ego *ego)
+initialize_srv_handle_via_matching_member (struct GNUNET_MESSENGER_SrvHandle 
*handle,
+                                           const struct GNUNET_HashCode *key)
 {
-  struct GNUNET_MESSENGER_SrvHandle *handle = cls;
-
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Updating handle...\n");
-
-  struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
-
-  bind_store_ego(store, handle->name, handle);
-
-  if (!ego)
-    create_store_ego (store, handle->name);
-  else
-    renew_store_ego (store, handle->name);
-}
-
-void
-update_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle)
-{
-  GNUNET_assert (handle);
-
-  if (!handle->name)
-  {
-    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Updating handle failed: Name is 
required!\n");
+  struct GNUNET_MESSENGER_SrvRoom *room = get_service_room(handle->service, 
key);
+  if (!room)
     return;
-  }
 
-  struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
-
-  lookup_store_ego (store, handle->name, callback_update_handle, handle);
-}
-
-static void
-callback_set_handle_name (void *cls,
-                          const char *name,
-                          const struct GNUNET_MESSENGER_Ego *ego)
-{
-  struct GNUNET_MESSENGER_SrvHandle *handle = cls;
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Renaming handle...\n");
-
-  if (ego)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is 
occupied! (%s)\n", name);
+  struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store(room);
+  if (!store)
     return;
-  }
-
-  struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
-
-  char *old_dir;
-  get_srv_handle_data_subdir (handle, handle->name, &old_dir);
-
-  char *new_dir;
-  get_srv_handle_data_subdir (handle, name, &new_dir);
-
-  if ((GNUNET_YES == GNUNET_DISK_directory_test (new_dir, GNUNET_NO)) &&
-      (GNUNET_OK != GNUNET_DISK_directory_remove(new_dir)))
-    goto free_dirs;
-
-  if (GNUNET_YES == GNUNET_DISK_directory_test (old_dir, GNUNET_YES))
-  {
-    GNUNET_DISK_directory_create_for_file (new_dir);
-
-    if (0 != rename (old_dir, new_dir))
-      goto free_dirs;
-  }
-
-  if (handle->ego)
-    rename_store_ego(store, handle->name, name);
-
-  struct GNUNET_MESSENGER_MessageHandle msg_handle;
-  msg_handle.handle = handle;
-  msg_handle.message = create_message_name (name);
-
-  GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, 
iterate_send_message, &msg_handle);
-  destroy_message (msg_handle.message);
-  change_handle_name (handle, name);
-
-free_dirs:
-  GNUNET_free(old_dir);
-  GNUNET_free(new_dir);
-}
-
-void
-set_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
-                     const char *name)
-{
-  GNUNET_assert(handle);
-
-  if (!name)
-  {
-    if (handle->ego)
-      GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Renaming handle failed: Name is 
required!\n");
-    else
-      change_handle_name (handle, name);
 
+  const struct GNUNET_IDENTITY_PublicKey *pubkey = get_srv_handle_key(handle);
+  if ((!pubkey) || (0 == GNUNET_memcmp (pubkey, get_anonymous_public_key())))
     return;
-  }
 
-  struct GNUNET_MESSENGER_EgoStore *store = 
get_service_ego_store(handle->service);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Initialize member id of handle via 
matching member in room!\n");
+
+  struct RoomInitializationClosure init;
+  init.handle = handle;
+  init.key = key;
+  init.pubkey = pubkey;
 
-  lookup_store_ego (store, name, callback_set_handle_name, handle);
+  iterate_store_members(store, find_member_session_in_room, &init);
 }
 
 int
@@ -430,6 +261,8 @@ open_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle 
*handle,
 {
   GNUNET_assert((handle) && (key));
 
+  initialize_srv_handle_via_matching_member (handle, key);
+
   if ((!get_srv_handle_member_id (handle, key)) && (GNUNET_YES != 
create_handle_member_id (handle, key)))
     return GNUNET_NO;
 
@@ -443,6 +276,8 @@ entry_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle 
*handle,
 {
   GNUNET_assert((handle) && (door) && (key));
 
+  initialize_srv_handle_via_matching_member (handle, key);
+
   if ((!get_srv_handle_member_id (handle, key)) && (GNUNET_YES != 
create_handle_member_id (handle, key)))
     return GNUNET_NO;
 
@@ -455,6 +290,15 @@ close_srv_handle_room (struct GNUNET_MESSENGER_SrvHandle 
*handle,
 {
   GNUNET_assert((handle) && (key));
 
+  GNUNET_CONTAINER_multihashmap_get_multiple (handle->next_ids, key, 
iterate_free_member_ids, NULL);
+  GNUNET_CONTAINER_multihashmap_remove_all (handle->next_ids, key);
+
+  if ((handle->notify) && (0 == GNUNET_CONTAINER_multihashmap_size 
(handle->next_ids)))
+  {
+    GNUNET_SCHEDULER_cancel(handle->notify);
+    handle->notify = NULL;
+  }
+
   if (!get_srv_handle_member_id (handle, key))
     return GNUNET_NO;
 
@@ -476,6 +320,15 @@ send_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle 
*handle,
     return GNUNET_NO;
   }
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message with member id: %s\n",
+              GNUNET_sh2s (id));
+
+  if (0 != GNUNET_memcmp(id, &(message->header.sender_id)))
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Member id does not match with 
handle!\n");
+    return GNUNET_NO;
+  }
+
   struct GNUNET_MESSENGER_SrvRoom *room = get_service_room (handle->service, 
key);
 
   if (!room)
@@ -485,17 +338,14 @@ send_srv_handle_message (struct 
GNUNET_MESSENGER_SrvHandle *handle,
   }
 
   struct GNUNET_MESSENGER_Message *msg = copy_message(message);
-
-  GNUNET_memcpy(&(msg->header.sender_id), id, sizeof(*id));
-
   return send_srv_room_message (room, handle, msg);
 }
 
 static const struct GNUNET_HashCode*
-get_next_member_session_contect(const struct GNUNET_MESSENGER_MemberSession 
*session)
+get_next_member_session_context(const struct GNUNET_MESSENGER_MemberSession 
*session)
 {
   if (session->next)
-    return get_next_member_session_contect (session->next);
+    return get_next_member_session_context (session->next);
   else
     return get_member_session_context(session);
 }
@@ -510,23 +360,33 @@ get_handle_member_session (struct 
GNUNET_MESSENGER_SrvHandle *handle,
   const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id(handle, 
key);
 
   if (!id)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Handle is missing a member id for its member session! (%s)\n",
+                GNUNET_h2s (key));
     return NULL;
+  }
 
   struct GNUNET_MESSENGER_MemberStore *store = get_srv_room_member_store(room);
   struct GNUNET_MESSENGER_Member *member = get_store_member(store, id);
 
-  const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(handle);
+  const struct GNUNET_IDENTITY_PublicKey *pubkey = get_srv_handle_key(handle);
 
-  if (!ego)
+  if (!pubkey)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
+                "Handle is missing a public key for its member session! 
(%s)\n",
+                GNUNET_h2s (key));
     return NULL;
+  }
 
-  return get_member_session(member, &(ego->pub));
+  return get_member_session(member, pubkey);
 }
 
 void
 notify_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
                            struct GNUNET_MESSENGER_SrvRoom *room,
-                           const struct GNUNET_MESSENGER_MemberSession 
*session,
+                           const struct GNUNET_MESSENGER_SenderSession 
*session,
                            const struct GNUNET_MESSENGER_Message *message,
                            const struct GNUNET_HashCode *hash)
 {
@@ -540,30 +400,26 @@ notify_srv_handle_message (struct 
GNUNET_MESSENGER_SrvHandle *handle,
     return;
   }
 
-  const struct GNUNET_IDENTITY_PublicKey *pubkey = 
get_contact_key(session->contact);
-
   struct GNUNET_HashCode sender;
-  GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
-
-  const struct GNUNET_HashCode *context = get_next_member_session_contect 
(session);
+  const struct GNUNET_HashCode *context = NULL;
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Notifying client about message: %s\n", 
GNUNET_h2s (hash));
-
-  struct GNUNET_MESSENGER_Message *private_message = NULL;
+  if (GNUNET_YES == is_peer_message (message))
+  {
+    const struct GNUNET_PeerIdentity *identity = session->peer;
+    GNUNET_CRYPTO_hash(identity, sizeof(*identity), &sender);
 
-  if (GNUNET_MESSENGER_KIND_PRIVATE == message->header.kind)
+    context = &sender;
+  }
+  else
   {
-    private_message = copy_message(message);
+    const struct GNUNET_IDENTITY_PublicKey *pubkey = 
get_contact_key(session->member->contact);
+    GNUNET_CRYPTO_hash(pubkey, sizeof(*pubkey), &sender);
 
-    if (GNUNET_YES != decrypt_message(private_message, 
&(get_srv_handle_ego(handle)->priv)))
-    {
-      destroy_message(private_message);
-      private_message = NULL;
-    }
-    else
-      message = private_message;
+    context = get_next_member_session_context (session->member);
   }
 
+  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Notifying client about message: %s\n", 
GNUNET_h2s (hash));
+
   struct GNUNET_MESSENGER_RecvMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
@@ -578,135 +434,78 @@ notify_srv_handle_message (struct 
GNUNET_MESSENGER_SrvHandle *handle,
 
   msg->flags = (uint32_t) GNUNET_MESSENGER_FLAG_NONE;
 
-  if (get_handle_member_session(handle, room, key) == session)
+  if (GNUNET_YES == is_peer_message (message))
+    msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PEER;
+  else if (get_handle_member_session(handle, room, key) == session->member)
     msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_SENT;
 
-  if (private_message)
-    msg->flags |= (uint32_t) GNUNET_MESSENGER_FLAG_PRIVATE;
-
   char *buffer = ((char*) msg) + sizeof(*msg);
   encode_message (message, length, buffer, GNUNET_YES);
 
-  if (private_message)
-    destroy_message(private_message);
-
   GNUNET_MQ_send (handle->mq, env);
 }
 
 static int
-callback_scan_for_rooms (void *cls,
-                         const char *filename)
+iterate_next_member_ids (void *cls,
+                         const struct GNUNET_HashCode *key,
+                         void *value)
 {
   struct GNUNET_MESSENGER_SrvHandle *handle = cls;
+  struct GNUNET_MESSENGER_NextMemberId *next = value;
 
-  if ((strlen(filename) <= 4) || (0 != strcmp(filename + strlen(filename) - 4, 
".cfg")))
-    return GNUNET_OK;
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Load room configuration of handle: 
%s\n", filename);
+  struct GNUNET_MESSENGER_MemberMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
 
-  struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
+  env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID);
 
-  if ((GNUNET_YES == GNUNET_DISK_file_test (filename)) && (GNUNET_OK == 
GNUNET_CONFIGURATION_parse (cfg, filename)))
-  {
-    struct GNUNET_HashCode key;
-    struct GNUNET_ShortHashCode member_id;
+  GNUNET_memcpy(&(msg->key), key, sizeof(*key));
+  GNUNET_memcpy(&(msg->id), &(next->id), sizeof(next->id));
+  msg->reset = (uint32_t) next->reset;
 
-    if ((GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "key", &key, 
sizeof(key))) &&
-        (GNUNET_OK == GNUNET_CONFIGURATION_get_data (cfg, "room", "member_id", 
&member_id, sizeof(member_id))))
-      change_srv_handle_member_id (handle, &key, &member_id);
-  }
+  GNUNET_MQ_send (handle->mq, env);
 
-  GNUNET_CONFIGURATION_destroy (cfg);
-  return GNUNET_OK;
+  GNUNET_free (next);
+  return GNUNET_YES;
 }
 
-void
-load_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
+static void
+task_notify_srv_handle_member_id (void *cls)
 {
-  GNUNET_assert(handle);
-
-  char *id_dir;
-  get_srv_handle_data_subdir (handle, handle->name, &id_dir);
-
-  if (GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_YES))
-  {
-    char *scan_dir;
-    GNUNET_asprintf (&scan_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
-
-    if (GNUNET_OK == GNUNET_DISK_directory_test (scan_dir, GNUNET_YES))
-      GNUNET_DISK_directory_scan (scan_dir, callback_scan_for_rooms, handle);
-
-    GNUNET_free(scan_dir);
-  }
+  struct GNUNET_MESSENGER_SrvHandle *handle = cls;
+  handle->notify = NULL;
 
-  GNUNET_free(id_dir);
+  GNUNET_CONTAINER_multihashmap_iterate (handle->next_ids, 
iterate_next_member_ids, handle);
+  GNUNET_CONTAINER_multihashmap_clear (handle->next_ids);
 }
 
-static int
-iterate_save_rooms (void *cls,
-                    const struct GNUNET_HashCode *key,
-                    void *value)
+void
+notify_srv_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
+                             struct GNUNET_MESSENGER_SrvRoom *room,
+                             const struct GNUNET_ShortHashCode *member_id,
+                             enum GNUNET_GenericReturnValue reset)
 {
-  struct GNUNET_MESSENGER_SrvHandle *handle = cls;
-  struct GNUNET_ShortHashCode *member_id = value;
-
-  char *id_dir;
-  get_srv_handle_data_subdir (handle, handle->name, &id_dir);
-
-  char *filename;
-  GNUNET_asprintf (&filename, "%s%s%c%s.cfg", id_dir, "rooms", DIR_SEPARATOR, 
GNUNET_h2s (key));
-  GNUNET_free(id_dir);
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Save room configuration of handle: 
%s\n", filename);
-
-  struct GNUNET_CONFIGURATION_Handle *cfg = GNUNET_CONFIGURATION_create ();
-
-  char *key_data = GNUNET_STRINGS_data_to_string_alloc (key, sizeof(*key));
+  GNUNET_assert((handle) && (room) && (member_id));
 
-  if (key_data)
+  struct GNUNET_MESSENGER_NextMemberId *next = GNUNET_new (struct 
GNUNET_MESSENGER_NextMemberId);
+  if (!next)
   {
-    GNUNET_CONFIGURATION_set_value_string (cfg, "room", "key", key_data);
-
-    GNUNET_free(key_data);
-  }
-
-  char *member_id_data = GNUNET_STRINGS_data_to_string_alloc (member_id, 
sizeof(*member_id));
-
-  if (member_id_data)
-  {
-    GNUNET_CONFIGURATION_set_value_string (cfg, "room", "member_id", 
member_id_data);
-
-    GNUNET_free(member_id_data);
+    return;
   }
 
-  GNUNET_CONFIGURATION_write (cfg, filename);
-  GNUNET_CONFIGURATION_destroy (cfg);
+  GNUNET_memcpy (&(next->id), member_id, sizeof(next->id));
+  next->reset = reset;
 
-  GNUNET_free(filename);
-
-  return GNUNET_YES;
-}
-
-void
-save_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle)
-{
-  GNUNET_assert(handle);
-
-  char *id_dir;
-  get_srv_handle_data_subdir (handle, handle->name, &id_dir);
+  const struct GNUNET_HashCode *key = get_srv_room_key(room);
 
-  if ((GNUNET_YES == GNUNET_DISK_directory_test (id_dir, GNUNET_NO)) || 
(GNUNET_OK
-      == GNUNET_DISK_directory_create (id_dir)))
+  struct GNUNET_MESSENGER_NextMemberId *prev = 
GNUNET_CONTAINER_multihashmap_get(handle->next_ids, key);
+  if (GNUNET_YES != GNUNET_CONTAINER_multihashmap_put(handle->next_ids, key, 
next, GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE))
   {
-    char *save_dir;
-    GNUNET_asprintf (&save_dir, "%s%s%c", id_dir, "rooms", DIR_SEPARATOR);
-
-    if ((GNUNET_YES == GNUNET_DISK_directory_test (save_dir, GNUNET_NO)) ||
-        (GNUNET_OK == GNUNET_DISK_directory_create (save_dir)))
-      GNUNET_CONTAINER_multihashmap_iterate (handle->member_ids, 
iterate_save_rooms, handle);
-
-    GNUNET_free(save_dir);
+    return;
   }
 
-  GNUNET_free(id_dir);
+  if (prev)
+    GNUNET_free (prev);
+
+  if (!handle->notify)
+    handle->notify = GNUNET_SCHEDULER_add_now 
(task_notify_srv_handle_member_id, handle);
 }
diff --git a/src/messenger/gnunet-service-messenger_handle.h 
b/src/messenger/gnunet-service-messenger_handle.h
index edcd2ccd0..4a68ff276 100644
--- a/src/messenger/gnunet-service-messenger_handle.h
+++ b/src/messenger/gnunet-service-messenger_handle.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -32,9 +32,8 @@
 #include "gnunet_identity_service.h"
 
 #include "gnunet-service-messenger_service.h"
-#include "gnunet-service-messenger_member_session.h"
+#include "gnunet-service-messenger_sender_session.h"
 
-#include "messenger_api_ego.h"
 #include "messenger_api_message.h"
 
 struct GNUNET_MESSENGER_SrvHandle
@@ -42,11 +41,12 @@ struct GNUNET_MESSENGER_SrvHandle
   struct GNUNET_MESSENGER_Service *service;
   struct GNUNET_MQ_Handle *mq;
 
-  char *name;
-
-  const struct GNUNET_MESSENGER_Ego *ego;
+  struct GNUNET_IDENTITY_PublicKey *key;
 
   struct GNUNET_CONTAINER_MultiHashMap *member_ids;
+  struct GNUNET_CONTAINER_MultiHashMap *next_ids;
+
+  struct GNUNET_SCHEDULER_Task *notify;
 };
 
 /**
@@ -68,6 +68,25 @@ create_srv_handle (struct GNUNET_MESSENGER_Service *service,
 void
 destroy_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
 
+/**
+ * Sets the public key from the EGO of a given <i>handle</i>.
+ *
+ * @param[out] handle Handle
+ * @param[in] key Public key of EGO
+ */
+void
+set_srv_handle_key (struct GNUNET_MESSENGER_SrvHandle *handle,
+                    const struct GNUNET_IDENTITY_PublicKey *key);
+
+/**
+ * Returns the public key from the EGO of a given <i>handle</i>.
+ *
+ * @param[in] handle Handle
+ * @return Public key of handles EGO
+ */
+const struct GNUNET_IDENTITY_PublicKey*
+get_srv_handle_key (const struct GNUNET_MESSENGER_SrvHandle *handle);
+
 /**
  * Writes the path of the directory for a given <i>handle</i> using a specific 
<i>name</i> to the parameter
  * <i>dir</i>. This directory will be used to store data regarding the handle 
and its messages.
@@ -110,57 +129,6 @@ change_srv_handle_member_id (struct 
GNUNET_MESSENGER_SrvHandle *handle,
                              const struct GNUNET_HashCode *key,
                              const struct GNUNET_ShortHashCode *unique_id);
 
-/**
- * Sets the EGO used by a given <i>handle</i>.
- *
- * @param[in,out] handle Handle
- * @param[in] ego EGO key pair
- */
-void
-set_srv_handle_ego (struct GNUNET_MESSENGER_SrvHandle *handle,
-                    const struct GNUNET_MESSENGER_Ego *ego);
-
-/**
- * Returns the EGO used by a given <i>handle</i>.
- *
- * @param[in] handle Handle
- * @return EGO key pair
- */
-const struct GNUNET_MESSENGER_Ego*
-get_srv_handle_ego (const struct GNUNET_MESSENGER_SrvHandle *handle);
-
-/**
- * Tries to set the name and EGO key of a <i>handle</i> initially by looking 
up a specific <i>name</i>.
- *
- * @param[in,out] handle Handle
- * @param[in] name Name (optionally: valid EGO name)
- */
-void
-setup_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
-                       const char *name);
-
-/**
- * Tries to change the key pair of an EGO of a <i>handle</i> under the same 
name and informs all rooms
- * about the change automatically.
- *
- * @param[in,out] handle Handle
- */
-void
-update_srv_handle (struct GNUNET_MESSENGER_SrvHandle *handle);
-
-/**
- * Tries to rename the handle which implies renaming the EGO its using and 
moving all related data into
- * the directory fitting to the changed <i>name</i>.
- *
- * The client connected to the <i>handle</i> will be informed afterwards 
automatically.
- *
- * @param[in,out] handle Handle
- * @param[in] name New name
- */
-void
-set_srv_handle_name (struct GNUNET_MESSENGER_SrvHandle *handle,
-                     const char *name);
-
 /**
  * Makes a given <i>handle</i> a member of the room using a specific 
<i>key</i> and opens the
  * room from the handles service.
@@ -217,33 +185,29 @@ send_srv_handle_message (struct 
GNUNET_MESSENGER_SrvHandle *handle,
  *
  * @param[in,out] handle Handle
  * @param[in] room Room of the message
- * @param[in] session Member session
+ * @param[in] session Sender session
  * @param[in] message Message
  * @param[in] hash Hash of message
  */
 void
 notify_srv_handle_message (struct GNUNET_MESSENGER_SrvHandle *handle,
                            struct GNUNET_MESSENGER_SrvRoom *room,
-                           const struct GNUNET_MESSENGER_MemberSession 
*session,
+                           const struct GNUNET_MESSENGER_SenderSession 
*session,
                            const struct GNUNET_MESSENGER_Message *message,
                            const struct GNUNET_HashCode *hash);
 
 /**
- * Loads member ids and other potential configuration from a given 
<i>handle</i> which
- * depends on the given name the <i>handle</i> uses.
+ * Notifies the handle that a new member id needs to be used.
  *
- * @param[out] handle Handle
- */
-void
-load_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
-
-/**
- * Saves member ids and other potential configuration from a given 
<i>handle</i> which
- * depends on the given name the <i>handle</i> uses.
- *
- * @param[in] handle Handle
+ * @param[in,out] handle Handle
+ * @param[in] room Room of the member
+ * @param[in] member_id Member id
+ * @param[in] reset Reset member session with join message
  */
 void
-save_srv_handle_configuration (struct GNUNET_MESSENGER_SrvHandle *handle);
+notify_srv_handle_member_id (struct GNUNET_MESSENGER_SrvHandle *handle,
+                             struct GNUNET_MESSENGER_SrvRoom *room,
+                             const struct GNUNET_ShortHashCode *member_id,
+                             enum GNUNET_GenericReturnValue reset);
 
 #endif //GNUNET_SERVICE_MESSENGER_HANDLE_H
diff --git a/src/messenger/gnunet-service-messenger_member.c 
b/src/messenger/gnunet-service-messenger_member.c
index 444148831..b483f315b 100644
--- a/src/messenger/gnunet-service-messenger_member.c
+++ b/src/messenger/gnunet-service-messenger_member.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -331,9 +331,7 @@ get_member_session_of (struct GNUNET_MESSENGER_Member 
*member,
   GNUNET_assert ((member) && (message) && (hash) &&
                  (0 == GNUNET_memcmp(&(member->id), 
&(message->header.sender_id))));
 
-  if (GNUNET_MESSENGER_KIND_INFO == message->header.kind)
-    return try_member_session(member, &(message->body.info.host_key));
-  else if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
+  if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
     return try_member_session(member, &(message->body.join.key));
 
   struct GNUNET_MESSENGER_ClosureSearchSession search;
diff --git a/src/messenger/gnunet-service-messenger_member_session.c 
b/src/messenger/gnunet-service-messenger_member_session.c
index 519ac6f05..2e26fd228 100644
--- a/src/messenger/gnunet-service-messenger_member_session.c
+++ b/src/messenger/gnunet-service-messenger_member_session.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2021--2022 GNUnet e.V.
+   Copyright (C) 2021--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -384,13 +384,17 @@ int verify_member_session_as_sender (const struct 
GNUNET_MESSENGER_MemberSession
 {
   GNUNET_assert((session) && (message) && (hash));
 
-  if (GNUNET_YES == is_member_session_completed(session))
+  if (GNUNET_YES == is_member_session_completed (session))
     return GNUNET_SYSERR;
 
-  if (0 != GNUNET_memcmp(get_member_session_id(session), 
&(message->header.sender_id)))
+  if (0 != GNUNET_memcmp (get_member_session_id (session), 
&(message->header.sender_id)))
     return GNUNET_SYSERR;
 
-  return verify_message(message, hash, get_member_session_public_key(session));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Check message (%s) using key: %s\n",
+              GNUNET_h2s (hash),
+              GNUNET_IDENTITY_public_key_to_string 
(get_member_session_public_key (session)));
+
+  return verify_message (message, hash, get_member_session_public_key 
(session));
 }
 
 int
diff --git a/src/messenger/gnunet-service-messenger_member_store.c 
b/src/messenger/gnunet-service-messenger_member_store.c
index fc28babc4..8b2bd7ac8 100644
--- a/src/messenger/gnunet-service-messenger_member_store.c
+++ b/src/messenger/gnunet-service-messenger_member_store.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -204,8 +204,12 @@ struct GNUNET_MESSENGER_Member*
 get_store_member_of (struct GNUNET_MESSENGER_MemberStore *store,
                      const struct GNUNET_MESSENGER_Message *message)
 {
-  if ((GNUNET_MESSENGER_KIND_INFO == message->header.kind) ||
-      (GNUNET_MESSENGER_KIND_JOIN == message->header.kind))
+  GNUNET_assert((store) && (message));
+
+  if (GNUNET_YES == is_peer_message(message))
+    return NULL;
+
+  if (GNUNET_MESSENGER_KIND_JOIN == message->header.kind)
     return add_store_member(store, &(message->header.sender_id));
   else
     return get_store_member(store, &(message->header.sender_id));
diff --git a/src/messenger/gnunet-service-messenger_member_store.h 
b/src/messenger/gnunet-service-messenger_member_store.h
index 05b00f39a..3dc39114b 100644
--- a/src/messenger/gnunet-service-messenger_member_store.h
+++ b/src/messenger/gnunet-service-messenger_member_store.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -118,7 +118,9 @@ get_store_member (const struct GNUNET_MESSENGER_MemberStore 
*store,
 
 /**
  * Returns the member of a <i>store</i> using a sender id of a given 
<i>message</i>.
- * If the member does not provide a matching session, NULL gets returned.
+ *
+ * If the message is a peer message or the member does not provide a matching 
session,
+ * NULL gets returned.
  *
  * @param[in,out] store Member store
  * @param[in] message Message
diff --git a/src/messenger/gnunet-service-messenger_message_handle.c 
b/src/messenger/gnunet-service-messenger_message_handle.c
index 06b987657..57b758fa4 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.c
+++ b/src/messenger/gnunet-service-messenger_message_handle.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -27,9 +27,9 @@
 #include "gnunet-service-messenger_message_handle.h"
 
 static void
-handle_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
-                       const struct GNUNET_MESSENGER_Message *message,
-                       const struct GNUNET_HashCode *hash)
+handle_member_session_switch (struct GNUNET_MESSENGER_MemberSession *session,
+                              const struct GNUNET_MESSENGER_Message *message,
+                              const struct GNUNET_HashCode *hash)
 {
   struct GNUNET_MESSENGER_MemberSession *next = switch_member_session(session, 
message, hash);
 
@@ -39,14 +39,14 @@ handle_session_switch (struct 
GNUNET_MESSENGER_MemberSession *session,
 
 void
 handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash)
 {
   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) joins room (%s).\n",
              GNUNET_sh2s (&(message->header.sender_id)), 
GNUNET_h2s(get_srv_room_key(room)));
 
-  if (GNUNET_OK != reset_member_session(session, hash))
+  if (GNUNET_OK != reset_member_session(session->member, hash))
     GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Resetting member session failed!\n");
 
   solve_srv_room_member_collisions (
@@ -59,23 +59,23 @@ handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
 
 void
 handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
-                      struct GNUNET_MESSENGER_MemberSession *session,
+                      struct GNUNET_MESSENGER_SenderSession *session,
                       const struct GNUNET_MESSENGER_Message *message,
                       const struct GNUNET_HashCode *hash)
 {
   GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Member (%s) leaves room (%s).\n",
              GNUNET_sh2s (&(message->header.sender_id)), 
GNUNET_h2s(get_srv_room_key(room)));
 
-  close_member_session(session);
+  close_member_session(session->member);
 }
 
 void
 handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash)
 {
-  struct GNUNET_MESSENGER_Contact *contact = 
get_member_session_contact(session);
+  struct GNUNET_MESSENGER_Contact *contact = 
get_member_session_contact(session->member);
 
   if (!contact)
     return;
@@ -85,21 +85,26 @@ handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
 
 void
 handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
-                    struct GNUNET_MESSENGER_MemberSession *session,
+                    struct GNUNET_MESSENGER_SenderSession *session,
                     const struct GNUNET_MESSENGER_Message *message,
                     const struct GNUNET_HashCode *hash)
 {
-  handle_session_switch (session, message, hash);
+  handle_member_session_switch (session->member, message, hash);
 }
 
 void
 handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash)
 {
+  struct GNUNET_MESSENGER_PeerStore *store = get_srv_room_peer_store (room);
+
+  if (0 == GNUNET_memcmp(session->peer, &(message->body.peer.peer)))
+    update_store_peer(store, &(message->body.peer.peer));
+
   if (GNUNET_NO == contains_list_tunnels (&(room->basement), 
&(message->body.peer.peer)))
-    add_to_list_tunnels (&(room->basement), &(message->body.peer.peer));
+    add_to_list_tunnels (&(room->basement), &(message->body.peer.peer), hash);
 
   if (room->peer_message)
     rebuild_srv_room_basement_structure (room);
@@ -107,15 +112,15 @@ handle_message_peer (struct GNUNET_MESSENGER_SrvRoom 
*room,
 
 void
 handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
-                   struct GNUNET_MESSENGER_MemberSession *session,
+                   struct GNUNET_MESSENGER_SenderSession *session,
                    const struct GNUNET_MESSENGER_Message *message,
                    const struct GNUNET_HashCode *hash)
 {
-  handle_session_switch (session, message, hash);
+  handle_member_session_switch (session->member, message, hash);
 
   solve_srv_room_member_collisions (
       room,
-      get_member_session_public_key(session),
+      get_member_session_public_key(session->member),
       &(message->body.id.id),
       GNUNET_TIME_absolute_ntoh(message->header.timestamp)
   );
@@ -123,11 +128,16 @@ handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
 
 void
 handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash)
 {
-  struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels 
(&(room->basement), &(message->body.peer.peer), NULL);
+  struct GNUNET_MESSENGER_PeerStore *store = get_srv_room_peer_store (room);
+
+  if (0 == GNUNET_memcmp(session->peer, &(message->body.miss.peer)))
+    remove_store_peer(store, &(message->body.miss.peer));
+
+  struct GNUNET_MESSENGER_ListTunnel *element = find_list_tunnels 
(&(room->basement), &(message->body.miss.peer), NULL);
 
   if (!element)
     return;
@@ -140,7 +150,7 @@ handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
 
 void
 handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room,
-                       struct GNUNET_MESSENGER_MemberSession *session,
+                       struct GNUNET_MESSENGER_SenderSession *session,
                        const struct GNUNET_MESSENGER_Message *message,
                        const struct GNUNET_HashCode *hash)
 {
@@ -150,5 +160,5 @@ handle_message_delete (struct GNUNET_MESSENGER_SrvRoom 
*room,
   action = GNUNET_TIME_absolute_add (action, delay);
   delay = GNUNET_TIME_absolute_get_difference (GNUNET_TIME_absolute_get (), 
action);
 
-  delete_srv_room_message (room, session, &(message->body.deletion.hash), 
delay);
+  delete_srv_room_message (room, session->member, 
&(message->body.deletion.hash), delay);
 }
diff --git a/src/messenger/gnunet-service-messenger_message_handle.h 
b/src/messenger/gnunet-service-messenger_message_handle.h
index 0a97cd840..228b129c7 100644
--- a/src/messenger/gnunet-service-messenger_message_handle.h
+++ b/src/messenger/gnunet-service-messenger_message_handle.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -29,24 +29,23 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 
-#include "gnunet-service-messenger_message_kind.h"
-
-#include "gnunet-service-messenger_member_session.h"
+#include "gnunet-service-messenger_sender_session.h"
 #include "gnunet-service-messenger_tunnel.h"
 #include "messenger_api_message.h"
+#include "messenger_api_message_kind.h"
 
 /**
  * Handles a received or sent join message to make changes of current member 
information.
  * (add matching member and clear member info)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message JOIN-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash);
 
@@ -55,13 +54,13 @@ handle_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
  * (remove matching member and clear member info)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message LEAVE-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
-                      struct GNUNET_MESSENGER_MemberSession *session,
+                      struct GNUNET_MESSENGER_SenderSession *session,
                       const struct GNUNET_MESSENGER_Message *message,
                       const struct GNUNET_HashCode *hash);
 
@@ -70,13 +69,13 @@ handle_message_leave (struct GNUNET_MESSENGER_SrvRoom *room,
  * (change name of matching member)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message NAME-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash);
 
@@ -85,13 +84,13 @@ handle_message_name (struct GNUNET_MESSENGER_SrvRoom *room,
  * (move the member in the contacts and change its key)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message KEY-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
-                    struct GNUNET_MESSENGER_MemberSession *session,
+                    struct GNUNET_MESSENGER_SenderSession *session,
                     const struct GNUNET_MESSENGER_Message *message,
                     const struct GNUNET_HashCode *hash);
 
@@ -100,13 +99,13 @@ handle_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
  * (add a new peer to the basement and restructure connections based on 
updated list of peers)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message PEER-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash);
 
@@ -115,13 +114,13 @@ handle_message_peer (struct GNUNET_MESSENGER_SrvRoom 
*room,
  * (change id of matching member)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message ID-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
-                   struct GNUNET_MESSENGER_MemberSession *session,
+                   struct GNUNET_MESSENGER_SenderSession *session,
                    const struct GNUNET_MESSENGER_Message *message,
                    const struct GNUNET_HashCode *hash);
 
@@ -130,13 +129,13 @@ handle_message_id (struct GNUNET_MESSENGER_SrvRoom *room,
  * (remove a peer from the basement and restructure connections based on 
updated list of peers)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message MISS-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_miss (struct GNUNET_MESSENGER_SrvRoom *room,
-                     struct GNUNET_MESSENGER_MemberSession *session,
+                     struct GNUNET_MESSENGER_SenderSession *session,
                      const struct GNUNET_MESSENGER_Message *message,
                      const struct GNUNET_HashCode *hash);
 
@@ -145,13 +144,13 @@ handle_message_miss (struct GNUNET_MESSENGER_SrvRoom 
*room,
  * (remove a message from the store of a room under a given delay)
  *
  * @param[in,out] room Room of the message
- * @param[in,out] session Member session
+ * @param[in,out] session Sender session
  * @param[in] message DELETE-Message
  * @param[in] hash Hash of the message
  */
 void
 handle_message_delete (struct GNUNET_MESSENGER_SrvRoom *room,
-                       struct GNUNET_MESSENGER_MemberSession *session,
+                       struct GNUNET_MESSENGER_SenderSession *session,
                        const struct GNUNET_MESSENGER_Message *message,
                        const struct GNUNET_HashCode *hash);
 
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c 
b/src/messenger/gnunet-service-messenger_message_kind.c
index 828e84d4f..688dd2fd9 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ b/src/messenger/gnunet-service-messenger_message_kind.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -29,9 +29,9 @@
 #include "messenger_api_util.h"
 
 struct GNUNET_MESSENGER_Message*
-create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
+create_message_info (struct GNUNET_MESSENGER_Service *service)
 {
-  if (!ego)
+  if (!service)
     return NULL;
 
   struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_INFO);
@@ -39,67 +39,13 @@ create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
   if (!message)
     return NULL;
 
-  GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
-
   message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
 
   return message;
 }
 
 struct GNUNET_MESSENGER_Message*
-create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
-{
-  if (!ego)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_JOIN);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.join.key), &(ego->pub), sizeof(ego->pub));
-
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_leave ()
-{
-  return create_message (GNUNET_MESSENGER_KIND_LEAVE);
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_name (const char *name)
-{
-  if (!name)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_NAME);
-
-  if (!message)
-    return NULL;
-
-  message->body.name.name = GNUNET_strdup(name);
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key)
-{
-  if (!key)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_KEY);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_IDENTITY_key_get_public (key, &(message->body.key.key));
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_peer (const struct GNUNET_MESSENGER_Service *service)
+create_message_peer (struct GNUNET_MESSENGER_Service *service)
 {
   if (!service)
     return NULL;
@@ -118,22 +64,6 @@ create_message_peer (const struct GNUNET_MESSENGER_Service 
*service)
   }
 }
 
-struct GNUNET_MESSENGER_Message*
-create_message_id (const struct GNUNET_ShortHashCode *unique_id)
-{
-  if (!unique_id)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_ID);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.id.id), unique_id, sizeof(struct 
GNUNET_ShortHashCode));
-
-  return message;
-}
-
 struct GNUNET_MESSENGER_Message*
 create_message_miss (const struct GNUNET_PeerIdentity *peer)
 {
@@ -167,76 +97,3 @@ create_message_merge (const struct GNUNET_HashCode 
*previous)
 
   return message;
 }
-
-struct GNUNET_MESSENGER_Message*
-create_message_request (const struct GNUNET_HashCode *hash)
-{
-  if (!hash)
-    return NULL;
-
-  struct GNUNET_HashCode zero;
-  memset (&zero, 0, sizeof(zero));
-
-  if (0 == GNUNET_CRYPTO_hash_cmp (hash, &zero))
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_REQUEST);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.request.hash), hash, sizeof(struct 
GNUNET_HashCode));
-
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_invite (const struct GNUNET_PeerIdentity *door,
-                       const struct GNUNET_HashCode *key)
-{
-  if ((!door) || (!key))
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_INVITE);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.invite.door), door, sizeof(struct 
GNUNET_PeerIdentity));
-  GNUNET_memcpy(&(message->body.invite.key), key, sizeof(struct 
GNUNET_HashCode));
-
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_text (const char *text)
-{
-  if (!text)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_TEXT);
-
-  if (!message)
-    return NULL;
-
-  message->body.text.text = GNUNET_strdup(text);
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_delete (const struct GNUNET_HashCode *hash,
-                       const struct GNUNET_TIME_Relative delay)
-{
-  if (!hash)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_DELETE);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.deletion.hash), hash, sizeof(struct 
GNUNET_HashCode));
-  message->body.deletion.delay = GNUNET_TIME_relative_hton (delay);
-
-  return message;
-}
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h 
b/src/messenger/gnunet-service-messenger_message_kind.h
index 102a70e33..2e13e7710 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ b/src/messenger/gnunet-service-messenger_message_kind.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -36,73 +36,24 @@
 #include "messenger_api_ego.h"
 
 /**
- * Creates and allocates a new info message containing the hosts EGO public 
key and a newly generated unique member id.
+ * Creates and allocates a new info message containing the hosts service peer 
identity and version.
  * (all values are stored as copy)
  *
- * @param[in] ego EGO of the host
- * @param[in] members Map of all assigned member ids
+ * @param[in,out] service Service
  * @return New message
  */
 struct GNUNET_MESSENGER_Message*
-create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
-
-/**
- * Creates and allocates a new join message containing the clients EGO public 
key.
- * (all values are stored as copy)
- *
- * @param[in] ego EGO of the client
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
-
-/**
- * Creates and allocates a new leave message.
- *
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_leave ();
-
-/**
- * Creates and allocates a new name message containing the <i>name</i> to 
change to.
- * (all values are stored as copy)
- *
- * @param[in] name New name
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_name (const char *name);
-
-/**
- * Creates and allocates a new key message containing the public <i>key</i> to 
change to derived
- * from its private counterpart. (all values are stored as copy)
- *
- * @param[in] key Private key of EGO
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
+create_message_info (struct GNUNET_MESSENGER_Service *service);
 
 /**
  * Creates and allocates a new peer message containing a services peer 
identity.
  * (all values are stored as copy)
  *
- * @param[in] service Service
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_peer (const struct GNUNET_MESSENGER_Service *service);
-
-/**
- * Creates and allocates a new id message containing the unique member id to 
change to.
- * (all values are stored as copy)
- *
- * @param[in] unique_id Unique member id
+ * @param[in,out] service Service
  * @return New message
  */
 struct GNUNET_MESSENGER_Message*
-create_message_id (const struct GNUNET_ShortHashCode *unique_id);
+create_message_peer (struct GNUNET_MESSENGER_Service *service);
 
 /**
  * Creates and allocates a new miss message containing the missing <i>peer</i> 
identity.
@@ -125,49 +76,5 @@ create_message_miss (const struct GNUNET_PeerIdentity 
*peer);
 struct GNUNET_MESSENGER_Message*
 create_message_merge (const struct GNUNET_HashCode *previous);
 
-/**
- * Creates and allocates a new request message containing the <i>hash</i> of a 
missing message.
- * (all values are stored as copy)
- *
- * @param[in] hash Hash of message
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_request (const struct GNUNET_HashCode *hash);
-
-/**
- * Creates and allocates a new invite message containing the peer identity of 
an entrance peer
- * to a room using a given <i>key</i> as shared secret for communication.
- * (all values are stored as copy)
- *
- * @param[in] door Peer identity
- * @param[in] key Shared secret of a room
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_invite (const struct GNUNET_PeerIdentity *door,
-                       const struct GNUNET_HashCode *key);
-
-/**
- * Creates and allocates a new <i>text</i> message containing a string 
representing text.
- * (all values are stored as copy)
- *
- * @param[in] text Text
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_text (const char *text);
-
-/**
- * Creates and allocates a new delete message containing the <i>hash</i> of a 
message to delete after a specific <i>delay</i>.
- * (all values are stored as copy)
- *
- * @param[in] hash Hash of message
- * @param[in] delay Delay of deletion
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_delete (const struct GNUNET_HashCode *hash,
-                       const struct GNUNET_TIME_Relative delay);
 
 #endif //GNUNET_SERVICE_MESSENGER_MESSAGE_KIND_H
diff --git a/src/messenger/gnunet-service-messenger_message_recv.c 
b/src/messenger/gnunet-service-messenger_message_recv.c
index 94202fdca..3b545cfa4 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.c
+++ b/src/messenger/gnunet-service-messenger_message_recv.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -26,6 +26,7 @@
 #include "platform.h"
 #include "gnunet-service-messenger_message_recv.h"
 
+#include "gnunet-service-messenger_message_kind.h"
 #include "gnunet-service-messenger_operation.h"
 
 static void
@@ -92,15 +93,28 @@ recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room,
     return GNUNET_NO;
 
   if (room->host)
-  {
-    const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(room->host);
-
-    send_tunnel_message (tunnel, room->host, create_message_info(ego));
-  }
+    send_tunnel_message (tunnel, room->host, create_message_info 
(room->service));
 
   struct GNUNET_PeerIdentity peer;
   get_tunnel_peer_identity(tunnel, &peer);
 
+  if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
+  {
+    struct GNUNET_MESSENGER_MessageStore *message_store = 
get_srv_room_message_store(room);
+
+    struct GNUNET_MESSENGER_ListTunnel *element;
+    for (element = room->basement.head; element; element = element->next)
+    {
+      if (!element->hash)
+        continue;
+
+      const struct GNUNET_MESSENGER_Message *message = 
get_store_message(message_store, element->hash);
+
+      if (message)
+        forward_tunnel_message(tunnel, message, element->hash);
+    }
+  }
+
   if (GNUNET_YES != contains_list_tunnels(&(room->basement), &peer))
   {
     struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store(room);
@@ -109,7 +123,6 @@ recv_message_info (struct GNUNET_MESSENGER_SrvRoom *room,
   }
 
   check_srv_room_peer_status(room, tunnel);
-
   return GNUNET_NO;
 }
 
@@ -130,6 +143,7 @@ recv_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
     GNUNET_memcpy(tunnel->peer_message, &hash, sizeof(hash));
   }
 
+  update_to_list_tunnels(&(room->basement), &(message->body.peer.peer), hash);
   return GNUNET_YES;
 }
 
@@ -176,7 +190,7 @@ recv_message_request (struct GNUNET_MESSENGER_SrvRoom *room,
 
   struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session_of(member, message, hash);
 
-  if ((!session) || (GNUNET_YES != check_member_session_history(session, hash, 
GNUNET_NO)))
+  if ((!session) || (GNUNET_YES != check_member_session_history(session, 
&(message->body.request.hash), GNUNET_NO)))
     return GNUNET_NO;
 
   if (GNUNET_NO == request_srv_room_message(room, 
&(message->body.request.hash), session, callback_found_message, tunnel))
diff --git a/src/messenger/gnunet-service-messenger_message_recv.h 
b/src/messenger/gnunet-service-messenger_message_recv.h
index 8e5b02504..104d62ba0 100644
--- a/src/messenger/gnunet-service-messenger_message_recv.h
+++ b/src/messenger/gnunet-service-messenger_message_recv.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -29,8 +29,6 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 
-#include "gnunet-service-messenger_message_kind.h"
-
 #include "gnunet-service-messenger_member_session.h"
 #include "gnunet-service-messenger_tunnel.h"
 #include "messenger_api_message.h"
diff --git a/src/messenger/gnunet-service-messenger_message_send.c 
b/src/messenger/gnunet-service-messenger_message_send.c
index 09039758b..40ff95cef 100644
--- a/src/messenger/gnunet-service-messenger_message_send.c
+++ b/src/messenger/gnunet-service-messenger_message_send.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -26,9 +26,73 @@
 #include "platform.h"
 #include "gnunet-service-messenger_message_send.h"
 
+#include "gnunet-service-messenger_handle.h"
 #include "gnunet-service-messenger_member.h"
 #include "gnunet-service-messenger_member_session.h"
 #include "gnunet-service-messenger_operation.h"
+#include "gnunet-service-messenger_room.h"
+
+struct GNUNET_MESSENGER_MemberNotify
+{
+  struct GNUNET_MESSENGER_SrvRoom *room;
+  struct GNUNET_MESSENGER_SrvHandle *handle;
+  struct GNUNET_MESSENGER_MemberSession *session;
+};
+
+static void
+notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify,
+                      struct GNUNET_MESSENGER_MemberSession *session,
+                      struct GNUNET_CONTAINER_MultiHashMap *map,
+                      int check_permission)
+{
+  if (session->prev)
+    notify_about_members (notify, session->prev, map, GNUNET_YES);
+
+  struct GNUNET_MESSENGER_MessageStore *message_store = 
get_srv_room_message_store(notify->room);
+  struct GNUNET_MESSENGER_ListMessage *element;
+
+  for (element = session->messages.head; element; element = element->next)
+  {
+    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, 
&(element->hash)))
+      continue;
+
+    if ((GNUNET_YES == check_permission) &&
+        (GNUNET_YES != check_member_session_history(notify->session, 
&(element->hash), GNUNET_NO)))
+      continue;
+
+    if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), 
NULL,
+                                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message 
could be duplicated!\n");
+
+    const struct GNUNET_MESSENGER_Message *message = 
get_store_message(message_store, &(element->hash));
+
+    if ((!message) || (GNUNET_YES == is_peer_message (message)))
+      continue;
+
+    struct GNUNET_MESSENGER_SenderSession sender;
+    sender.member = session;
+
+    notify_srv_handle_message (notify->handle, notify->room, &sender, message, 
&(element->hash));
+  }
+}
+
+static int
+iterate_notify_about_members (void *cls,
+                              const struct GNUNET_IDENTITY_PublicKey 
*public_key,
+                              struct GNUNET_MESSENGER_MemberSession *session)
+{
+  struct GNUNET_MESSENGER_MemberNotify *notify = cls;
+
+  if ((notify->session == session) || (GNUNET_YES == 
is_member_session_completed(session)))
+    return GNUNET_YES;
+
+  struct GNUNET_CONTAINER_MultiHashMap *map = 
GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
+
+  notify_about_members (notify, session, map, GNUNET_NO);
+
+  GNUNET_CONTAINER_multihashmap_destroy(map);
+  return GNUNET_YES;
+}
 
 void
 send_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
@@ -36,9 +100,40 @@ send_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
                    const struct GNUNET_MESSENGER_Message *message,
                    const struct GNUNET_HashCode *hash)
 {
+  set_srv_handle_key(handle, &(message->body.join.key));
+
+  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store(room);
+  struct GNUNET_MESSENGER_Member *member = add_store_member(member_store, 
&(message->header.sender_id));
+
+  struct GNUNET_MESSENGER_MemberSession *session = get_member_session_of 
(member, message, hash);
+
+  if (!session)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join 
a room!\n");
+    goto skip_member_notification;
+  }
+
+  struct GNUNET_MESSENGER_MemberNotify notify;
+
+  notify.room = room;
+  notify.handle = handle;
+  notify.session = session;
+
+  iterate_store_members(get_srv_room_member_store(room), 
iterate_notify_about_members, &notify);
+
+skip_member_notification:
   check_srv_room_peer_status(room, NULL);
 }
 
+void
+send_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
+                  struct GNUNET_MESSENGER_SrvHandle *handle,
+                  const struct GNUNET_MESSENGER_Message *message,
+                  const struct GNUNET_HashCode *hash)
+{
+  set_srv_handle_key(handle, &(message->body.key.key));
+}
+
 void
 send_message_peer (struct GNUNET_MESSENGER_SrvRoom *room,
                    struct GNUNET_MESSENGER_SrvHandle *handle,
diff --git a/src/messenger/gnunet-service-messenger_message_send.h 
b/src/messenger/gnunet-service-messenger_message_send.h
index 4f4c6cfc2..4c25c0913 100644
--- a/src/messenger/gnunet-service-messenger_message_send.h
+++ b/src/messenger/gnunet-service-messenger_message_send.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -29,10 +29,9 @@
 #include "platform.h"
 #include "gnunet_util_lib.h"
 
-#include "gnunet-service-messenger_message_kind.h"
-
 #include "gnunet-service-messenger_tunnel.h"
 #include "messenger_api_message.h"
+#include "messenger_api_message_kind.h"
 
 /**
  * Handles a sent join message to ensure growth of the decentralized room 
structure.
@@ -49,6 +48,20 @@ send_message_join (struct GNUNET_MESSENGER_SrvRoom *room,
                    const struct GNUNET_MESSENGER_Message *message,
                    const struct GNUNET_HashCode *hash);
 
+/**
+ * Handles a sent key message to ensure changes to the public key of the 
sending handle.
+ *
+ * @param[in,out] room Room of the message
+ * @param[in,out] handle Sending handle
+ * @param[in] message KEY-Message
+ * @param[in] hash Hash of the message
+ */
+void
+send_message_key (struct GNUNET_MESSENGER_SrvRoom *room,
+                  struct GNUNET_MESSENGER_SrvHandle *handle,
+                  const struct GNUNET_MESSENGER_Message *message,
+                  const struct GNUNET_HashCode *hash);
+
 /**
  * Handles a sent peer message to update the rooms peer message of this 
service.
  * (a set peer message indicates this service being a part of the 
decentralized room structure)
diff --git a/src/messenger/gnunet-service-messenger_message_store.c 
b/src/messenger/gnunet-service-messenger_message_store.c
index 1f77de9ca..e137e9d93 100644
--- a/src/messenger/gnunet-service-messenger_message_store.c
+++ b/src/messenger/gnunet-service-messenger_message_store.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -291,6 +291,9 @@ iterate_save_messages (void *cls,
       (save_message_store_attribute_failed(save->storage, 
storage.entry.length)))
     return GNUNET_YES;
 
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Storing message with hash: %s\n",
+                 GNUNET_h2s (&(storage.hash)));
+
   char *buffer = GNUNET_malloc(storage.entry.length);
 
   encode_message (message, storage.entry.length, buffer, GNUNET_YES);
diff --git a/src/messenger/gnunet-service-messenger_room.c 
b/src/messenger/gnunet-service-messenger_room.c
index 4b734cb40..4bb194d01 100644
--- a/src/messenger/gnunet-service-messenger_room.c
+++ b/src/messenger/gnunet-service-messenger_room.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -27,7 +27,7 @@
 #include "gnunet-service-messenger_room.h"
 
 #include "gnunet-service-messenger_member.h"
-#include "gnunet-service-messenger_member_session.h"
+#include "gnunet-service-messenger_sender_session.h"
 
 #include "gnunet-service-messenger_message_kind.h"
 #include "gnunet-service-messenger_message_handle.h"
@@ -38,6 +38,8 @@
 #include "gnunet-service-messenger.h"
 #include "gnunet-service-messenger_service.h"
 #include "gnunet-service-messenger_tunnel.h"
+
+#include "messenger_api_message.h"
 #include "messenger_api_util.h"
 
 static void
@@ -59,9 +61,10 @@ create_srv_room (struct GNUNET_MESSENGER_SrvHandle *handle,
 
   room->tunnels = GNUNET_CONTAINER_multipeermap_create (8, GNUNET_NO);
 
-  init_member_store(get_srv_room_member_store(room), room);
-  init_message_store (get_srv_room_message_store(room));
-  init_operation_store(get_srv_room_operation_store(room), room);
+  init_peer_store (get_srv_room_peer_store (room));
+  init_member_store (get_srv_room_member_store (room), room);
+  init_message_store (get_srv_room_message_store (room));
+  init_operation_store (get_srv_room_operation_store (room), room);
 
   init_list_tunnels (&(room->basement));
   init_message_state(&(room->state));
@@ -119,18 +122,27 @@ destroy_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
     save_srv_room (room);
 
 skip_saving:
-  clear_member_store (get_srv_room_member_store(room));
-  clear_message_store (get_srv_room_message_store(room));
-  clear_operation_store(get_srv_room_operation_store(room));
+  clear_peer_store (get_srv_room_peer_store (room));
+  clear_member_store (get_srv_room_member_store (room));
+  clear_message_store (get_srv_room_message_store (room));
+  clear_operation_store (get_srv_room_operation_store (room));
 
   GNUNET_CONTAINER_multipeermap_destroy (room->tunnels);
   clear_list_tunnels (&(room->basement));
-  clear_message_state(&(room->state));
+  clear_message_state (&(room->state));
 
   if (room->peer_message)
-    GNUNET_free(room->peer_message);
+    GNUNET_free (room->peer_message);
+
+  GNUNET_free (room);
+}
+
+struct GNUNET_MESSENGER_PeerStore*
+get_srv_room_peer_store (struct GNUNET_MESSENGER_SrvRoom *room)
+{
+  GNUNET_assert(room);
 
-  GNUNET_free(room);
+  return &(room->peer_store);
 }
 
 struct GNUNET_MESSENGER_MemberStore*
@@ -165,7 +177,7 @@ send_room_info (struct GNUNET_MESSENGER_SrvRoom *room,
   if ((!handle) || (!is_tunnel_connected (tunnel)))
     return GNUNET_NO;
 
-  return send_tunnel_message (tunnel, handle, create_message_info 
(get_srv_handle_ego (handle)));
+  return send_tunnel_message (tunnel, handle, create_message_info 
(room->service));
 }
 
 static void*
@@ -222,73 +234,7 @@ join_room (struct GNUNET_MESSENGER_SrvRoom *room,
   if (GNUNET_OK != change_srv_handle_member_id (handle, 
get_srv_room_key(room), member_id))
     return GNUNET_NO;
 
-  struct GNUNET_MESSENGER_Message *message = create_message_join 
(get_srv_handle_ego (handle));
-
-  if (!message)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Your join message could not be 
created!\n");
-
-    return GNUNET_NO;
-  }
-
-  GNUNET_memcpy(&(message->header.sender_id), member_id, sizeof(*member_id));
-  return send_srv_room_message (room, handle, message);
-}
-
-struct GNUNET_MESSENGER_MemberNotify
-{
-  struct GNUNET_MESSENGER_SrvRoom *room;
-  struct GNUNET_MESSENGER_SrvHandle *handle;
-  struct GNUNET_MESSENGER_MemberSession *session;
-};
-
-static void
-notify_about_members (struct GNUNET_MESSENGER_MemberNotify *notify,
-                      struct GNUNET_MESSENGER_MemberSession *session,
-                      struct GNUNET_CONTAINER_MultiHashMap *map,
-                      int check_permission)
-{
-  if (session->prev)
-    notify_about_members (notify, session->prev, map, GNUNET_YES);
-
-  struct GNUNET_MESSENGER_MessageStore *message_store = 
get_srv_room_message_store(notify->room);
-  struct GNUNET_MESSENGER_ListMessage *element;
-
-  for (element = session->messages.head; element; element = element->next)
-  {
-    if (GNUNET_YES == GNUNET_CONTAINER_multihashmap_contains(map, 
&(element->hash)))
-      continue;
-
-    if ((GNUNET_YES == check_permission) &&
-        (GNUNET_YES != check_member_session_history(notify->session, 
&(element->hash), GNUNET_NO)))
-      continue;
-
-    if (GNUNET_OK != GNUNET_CONTAINER_multihashmap_put(map, &(element->hash), 
NULL,
-                                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_UNIQUE_FAST))
-      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Notification of session message 
could be duplicated!\n");
-
-    const struct GNUNET_MESSENGER_Message *message = 
get_store_message(message_store, &(element->hash));
-
-    if (message)
-      notify_srv_handle_message (notify->handle, notify->room, session, 
message, &(element->hash));
-  }
-}
-
-static int
-iterate_notify_about_members (void *cls,
-                              const struct GNUNET_IDENTITY_PublicKey 
*public_key,
-                              struct GNUNET_MESSENGER_MemberSession *session)
-{
-  struct GNUNET_MESSENGER_MemberNotify *notify = cls;
-
-  if ((notify->session == session) || (GNUNET_YES == 
is_member_session_completed(session)))
-    return GNUNET_YES;
-
-  struct GNUNET_CONTAINER_MultiHashMap *map = 
GNUNET_CONTAINER_multihashmap_create(4, GNUNET_NO);
-
-  notify_about_members (notify, session, map, GNUNET_NO);
-
-  GNUNET_CONTAINER_multihashmap_destroy(map);
+  notify_srv_handle_member_id (handle, room, member_id, GNUNET_YES);
   return GNUNET_YES;
 }
 
@@ -304,23 +250,6 @@ join_room_locally (struct GNUNET_MESSENGER_SrvRoom *room,
   if (GNUNET_NO == join_room (room, handle, member))
     return GNUNET_NO;
 
-  const struct GNUNET_MESSENGER_Ego *ego = get_srv_handle_ego(handle);
-  struct GNUNET_MESSENGER_MemberSession *session = get_member_session (member, 
&(ego->pub));
-
-  if (!session)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "A valid session is required to join 
a room!\n");
-    return GNUNET_NO;
-  }
-
-  struct GNUNET_MESSENGER_MemberNotify notify;
-
-  notify.room = room;
-  notify.handle = handle;
-  notify.session = session;
-
-  iterate_store_members(get_srv_room_member_store(room), 
iterate_notify_about_members, &notify);
-
   return GNUNET_YES;
 }
 
@@ -379,9 +308,10 @@ open_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
     return GNUNET_NO;
   }
 
-  struct GNUNET_MESSENGER_Message *peer_msg = create_message_peer 
(room->service);
-  GNUNET_memcpy(&(peer_msg->header.sender_id), member_id, sizeof(*member_id));
-  return (room->port ? send_srv_room_message (room, handle, peer_msg) : 
GNUNET_NO);
+  if (!room->port)
+    return GNUNET_NO;
+
+  return send_srv_room_message (room, handle, create_message_peer 
(room->service));
 }
 
 int
@@ -423,6 +353,20 @@ enter_srv_room_at (struct GNUNET_MESSENGER_SrvRoom *room,
   return join_room_locally (room, handle);
 }
 
+static void
+sign_srv_room_message_by_peer (const void *cls,
+                                 struct GNUNET_MESSENGER_Message *message,
+                                 uint16_t length,
+                                 char *buffer,
+                                 const struct GNUNET_HashCode *hash)
+{
+  const struct GNUNET_MESSENGER_SrvHandle *handle = cls;
+
+  GNUNET_assert((handle) && (handle->service));
+
+  sign_message_by_peer(message, length, buffer, hash, handle->service->config);
+}
+
 struct GNUNET_MQ_Envelope*
 pack_srv_room_message (const struct GNUNET_MESSENGER_SrvRoom *room,
                        const struct GNUNET_MESSENGER_SrvHandle *handle,
@@ -432,16 +376,23 @@ pack_srv_room_message (const struct 
GNUNET_MESSENGER_SrvRoom *room,
 {
   GNUNET_assert((room) && (handle) && (message) && (hash));
 
-  message->header.timestamp = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_absolute_get ());
+  if (GNUNET_YES != is_peer_message(message))
+    return pack_message (message, hash, NULL, mode, NULL);
 
-  const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle, 
get_srv_room_key(room));
+  message->header.timestamp = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_absolute_get ());
 
-  GNUNET_assert(id);
+  struct GNUNET_PeerIdentity peer;
+  if (GNUNET_OK != get_service_peer_identity(handle->service, &peer))
+    return NULL;
 
-  GNUNET_memcpy(&(message->header.sender_id), id, sizeof(struct 
GNUNET_ShortHashCode));
+  convert_peer_identity_to_id(&peer, &(message->header.sender_id));
   get_message_state_chain_hash (&(room->state), &(message->header.previous));
 
-  return pack_message (message, hash, get_srv_handle_ego (handle), mode);
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Packing message with peer signature: 
%s\n",
+                 GNUNET_sh2s (&(message->header.sender_id)));
+
+  message->header.signature.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA);
+  return pack_message (message, hash, sign_srv_room_message_by_peer, mode, 
handle);
 }
 
 struct GNUNET_MESSENGER_ClosureSendRoom
@@ -481,7 +432,7 @@ iterate_send_room_message (void *cls,
       closure->packed = GNUNET_YES;
   }
   else
-    env = pack_message (closure->message, NULL, NULL, 
GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
+    env = pack_message(closure->message, NULL, NULL, 
GNUNET_MESSENGER_PACK_MODE_ENVELOPE, NULL);
 
   if (env)
     send_tunnel_envelope (tunnel, env, closure->hash);
@@ -496,7 +447,6 @@ update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
 
 void
 callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
-                              struct GNUNET_MESSENGER_SrvHandle *handle,
                               const struct GNUNET_MESSENGER_Message *message,
                               const struct GNUNET_HashCode *hash);
 
@@ -513,8 +463,10 @@ send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom 
*room,
   if (GNUNET_YES == is_message_session_bound(message))
     merge_srv_room_last_messages(room, handle);
 
-  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Sending message from handle with member 
id: %s\n",
-             GNUNET_sh2s(get_srv_handle_member_id(handle, 
get_srv_room_key(room))));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sending message from handle in room: 
%s (%s)\n",
+              GNUNET_h2s (&(room->key)),
+              GNUNET_MESSENGER_name_of_kind (message->header.kind));
 
   struct GNUNET_HashCode hash;
   struct GNUNET_MESSENGER_ClosureSendRoom closure;
@@ -541,6 +493,9 @@ send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom 
*room,
   case GNUNET_MESSENGER_KIND_JOIN:
     send_message_join (room, handle, message, &hash);
     break;
+  case GNUNET_MESSENGER_KIND_KEY:
+    send_message_key (room, handle, message, &hash);
+    break;
   case GNUNET_MESSENGER_KIND_PEER:
     send_message_peer (room, handle, message, &hash);
     break;
@@ -554,7 +509,7 @@ send_srv_room_message (struct GNUNET_MESSENGER_SrvRoom 
*room,
     break;
   }
 
-  callback_room_handle_message (room, handle, message, &hash);
+  callback_room_handle_message (room, message, &hash);
   return GNUNET_YES;
 }
 
@@ -602,23 +557,6 @@ check_srv_room_peer_status (struct 
GNUNET_MESSENGER_SrvRoom *room,
     return;
   }
 
-  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store(room);
-  struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, 
message);
-
-  if (!member)
-    goto resend_peer_message;
-
-  struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session_of(member, message, room->peer_message);
-
-  if (GNUNET_YES == is_member_session_closed(session))
-    goto resend_peer_message;
-
-  if (tunnel)
-    forward_tunnel_message(tunnel, message, room->peer_message);
-
-  return;
-
-resend_peer_message:
   if (room->host)
     send_srv_room_message (room, room->host, create_message_peer 
(room->service));
 }
@@ -887,15 +825,19 @@ solve_srv_room_member_collisions (struct 
GNUNET_MESSENGER_SrvRoom *room,
   struct GNUNET_MESSENGER_ListHandles *handles = &(room->service->handles);
   struct GNUNET_MESSENGER_ListHandle* element;
 
+  const struct GNUNET_IDENTITY_PublicKey *pubkey;
+
   for (element = handles->head; element; element = element->next)
   {
     if (0 != GNUNET_memcmp(member_id, 
get_srv_handle_member_id(element->handle, get_srv_room_key(room))))
       continue;
 
-    if (0 == GNUNET_memcmp(public_key, 
&(get_srv_handle_ego(element->handle)->pub)))
+    pubkey = get_srv_handle_key(element->handle);
+
+    if (0 == GNUNET_memcmp(public_key, pubkey))
       continue;
 
-    struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session(member, &(get_srv_handle_ego(element->handle)->pub));
+    struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session(member, pubkey);
 
     if (!session)
       continue;
@@ -908,7 +850,7 @@ solve_srv_room_member_collisions (struct 
GNUNET_MESSENGER_SrvRoom *room,
     struct GNUNET_ShortHashCode random_id;
     generate_free_member_id (&random_id, member_store->members);
 
-    send_srv_room_message(room, element->handle, 
create_message_id(&random_id));
+    notify_srv_handle_member_id (element->handle, room, &random_id, GNUNET_NO);
   }
 }
 
@@ -962,8 +904,9 @@ rebuild_srv_room_basement_structure (struct 
GNUNET_MESSENGER_SrvRoom *room)
 static void
 handle_room_messages (struct GNUNET_MESSENGER_SrvRoom *room)
 {
-  struct GNUNET_MESSENGER_MessageStore *message_store = 
get_srv_room_message_store(room);
-  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store(room);
+  struct GNUNET_MESSENGER_MessageStore *message_store = 
get_srv_room_message_store (room);
+  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store (room);
+  struct GNUNET_MESSENGER_PeerStore *peer_store = get_srv_room_peer_store 
(room);
 
   while (room->handling.head)
   {
@@ -974,15 +917,29 @@ handle_room_messages (struct GNUNET_MESSENGER_SrvRoom 
*room)
     if (!message)
       goto finish_handling;
 
-    struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, 
message);
+    struct GNUNET_MESSENGER_SenderSession session;
 
-    if (!member)
-      goto finish_handling;
+    if (GNUNET_YES == is_peer_message (message))
+    {
+      session.peer = get_store_peer_of (peer_store, message, &(element->hash));
 
-    struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session_of(member, message, &(element->hash));
+      if (!session.peer)
+        goto finish_handling;
+    }
+    else
+    {
+      struct GNUNET_MESSENGER_Member *member = get_store_member_of 
(member_store, message);
 
-    if (session)
-      handle_service_message (room->service, room, session, message, 
&(element->hash));
+      if (!member)
+        goto finish_handling;
+
+      session.member = get_member_session_of (member, message, 
&(element->hash));
+
+      if (!session.member)
+        goto finish_handling;
+    }
+
+    handle_service_message (room->service, room, &session, message, 
&(element->hash));
 
 finish_handling:
     GNUNET_CONTAINER_DLL_remove(room->handling.head, room->handling.tail, 
element);
@@ -1084,27 +1041,45 @@ remove_room_member_session (struct 
GNUNET_MESSENGER_SrvRoom *room,
 
 void
 callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
-                              struct GNUNET_MESSENGER_SrvHandle *handle,
                               const struct GNUNET_MESSENGER_Message *message,
                               const struct GNUNET_HashCode *hash)
 {
-  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store(room);
-  struct GNUNET_MESSENGER_Member *member = get_store_member_of(member_store, 
message);
+  GNUNET_assert((room) && (message) && (hash));
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", 
GNUNET_h2s (hash));
+  struct GNUNET_MESSENGER_PeerStore *peer_store = get_srv_room_peer_store 
(room);
+  struct GNUNET_MESSENGER_MemberStore *member_store = 
get_srv_room_member_store (room);
 
-  if (!member)
+  struct GNUNET_MESSENGER_SenderSession session;
+
+  if (GNUNET_YES == is_peer_message (message))
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member is 
missing!\n");
-    return;
+    session.peer = get_store_peer_of (peer_store, message, hash);
+
+    if (!session.peer)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Peer is 
missing!\n");
+      return;
+    }
   }
+  else
+  {
+    struct GNUNET_MESSENGER_Member *member = get_store_member_of 
(member_store, message);
 
-  struct GNUNET_MESSENGER_MemberSession *session = 
get_member_session_of(member, message, hash);
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Callback for message (%s)\n", 
GNUNET_h2s (hash));
 
-  if (!session)
-  {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session 
is missing!\n");
-    return;
+    if (!member)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Member 
is missing!\n");
+      return;
+    }
+
+    session.member = get_member_session_of (member, message, hash);
+
+    if (!session.member)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Message handling dropped: Session 
is missing!\n");
+      return;
+    }
   }
 
   struct GNUNET_MESSENGER_MemberUpdate update;
@@ -1133,28 +1108,28 @@ callback_room_handle_message (struct 
GNUNET_MESSENGER_SrvRoom *room,
   switch (message->header.kind)
   {
   case GNUNET_MESSENGER_KIND_JOIN:
-    handle_message_join (room, session, message, hash);
+    handle_message_join (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_LEAVE:
-    handle_message_leave (room, session, message, hash);
+    handle_message_leave (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_NAME:
-    handle_message_name (room, session, message, hash);
+    handle_message_name (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_KEY:
-    handle_message_key (room, session, message, hash);
+    handle_message_key (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_PEER:
-    handle_message_peer (room, session, message, hash);
+    handle_message_peer (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_ID:
-    handle_message_id (room, session, message, hash);
+    handle_message_id (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_MISS:
-    handle_message_miss (room, session, message, hash);
+    handle_message_miss (room, &session, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_DELETE:
-    handle_message_delete (room, session, message, hash);
+    handle_message_delete (room, &session, message, hash);
     break;
   default:
     break;
diff --git a/src/messenger/gnunet-service-messenger_room.h 
b/src/messenger/gnunet-service-messenger_room.h
index 2e9382595..f0bb33f80 100644
--- a/src/messenger/gnunet-service-messenger_room.h
+++ b/src/messenger/gnunet-service-messenger_room.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -38,11 +38,11 @@
 #include "gnunet-service-messenger_list_messages.h"
 
 #include "messenger_api_list_tunnels.h"
+#include "messenger_api_peer_store.h"
 
 #include "gnunet-service-messenger_member_store.h"
 #include "gnunet-service-messenger_message_store.h"
 #include "gnunet-service-messenger_operation_store.h"
-#include "messenger_api_ego.h"
 
 #define GNUNET_MESSENGER_IDLE_DELAY GNUNET_TIME_relative_multiply \
   (GNUNET_TIME_relative_get_second_ (), 5)
@@ -66,6 +66,7 @@ struct GNUNET_MESSENGER_SrvRoom
 
   struct GNUNET_CONTAINER_MultiPeerMap *tunnels;
 
+  struct GNUNET_MESSENGER_PeerStore peer_store;
   struct GNUNET_MESSENGER_MemberStore member_store;
   struct GNUNET_MESSENGER_MessageStore message_store;
   struct GNUNET_MESSENGER_OperationStore operation_store;
@@ -103,6 +104,15 @@ void
 destroy_srv_room (struct GNUNET_MESSENGER_SrvRoom *room,
               int deletion);
 
+/**
+ * Returns the used peer store of a given <i>room</i>.
+ *
+ * @param[in,out] room Room
+ * @return Peer store
+ */
+struct GNUNET_MESSENGER_PeerStore*
+get_srv_room_peer_store (struct GNUNET_MESSENGER_SrvRoom *room);
+
 /**
  * Returns the used member store of a given <i>room</i>.
  *
diff --git a/src/messenger/gnunet-service-messenger_sender_session.h 
b/src/messenger/gnunet-service-messenger_sender_session.h
new file mode 100644
index 000000000..b137da11a
--- /dev/null
+++ b/src/messenger/gnunet-service-messenger_sender_session.h
@@ -0,0 +1,41 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2023 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Tobias Frisch
+ * @file src/messenger/gnunet-service-messenger_sender_session.h
+ * @brief GNUnet MESSENGER service
+ */
+
+#ifndef GNUNET_SERVICE_MESSENGER_SENDER_SESSION_H
+#define GNUNET_SERVICE_MESSENGER_SENDER_SESSION_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+#include "gnunet-service-messenger_member_session.h"
+
+struct GNUNET_MESSENGER_SenderSession {
+  union {
+    struct GNUNET_MESSENGER_MemberSession *member;
+    struct GNUNET_PeerIdentity *peer;
+  };
+};
+
+#endif /* GNUNET_SERVICE_MESSENGER_SENDER_SESSION_H */
diff --git a/src/messenger/gnunet-service-messenger_service.c 
b/src/messenger/gnunet-service-messenger_service.c
index 8dfc258c1..2f4d7bf80 100644
--- a/src/messenger/gnunet-service-messenger_service.c
+++ b/src/messenger/gnunet-service-messenger_service.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -25,8 +25,8 @@
 
 #include "platform.h"
 #include "gnunet-service-messenger_service.h"
-#include "gnunet-service-messenger_message_kind.h"
 #include "gnunet-service-messenger.h"
+#include "messenger_api_message_kind.h"
 
 static void
 callback_shutdown_service (void *cls)
@@ -54,6 +54,7 @@ create_service (const struct GNUNET_CONFIGURATION_Handle 
*config,
 
   service->shutdown = GNUNET_SCHEDULER_add_shutdown 
(&callback_shutdown_service, service);
 
+  service->peer = NULL;
   service->dir = NULL;
 
   if (GNUNET_OK != GNUNET_CONFIGURATION_get_value_filename (service->config,
@@ -78,13 +79,11 @@ create_service (const struct GNUNET_CONFIGURATION_Handle 
*config,
 
   service->cadet = GNUNET_CADET_connect (service->config);
 
-  init_ego_store(get_service_ego_store(service), service->config);
-
   init_list_handles (&(service->handles));
 
   service->rooms = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
 
-  init_contact_store(get_service_contact_store(service));
+  init_contact_store (get_service_contact_store (service));
 
   return service;
 }
@@ -111,13 +110,12 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
     service->shutdown = NULL;
   }
 
-  clear_ego_store(get_service_ego_store(service));
   clear_list_handles (&(service->handles));
 
   GNUNET_CONTAINER_multihashmap_iterate (service->rooms, 
iterate_destroy_rooms, NULL);
   GNUNET_CONTAINER_multihashmap_destroy (service->rooms);
 
-  clear_contact_store(get_service_contact_store(service));
+  clear_contact_store (get_service_contact_store (service));
 
   if (service->cadet)
   {
@@ -133,17 +131,16 @@ destroy_service (struct GNUNET_MESSENGER_Service *service)
     service->dir = NULL;
   }
 
-  GNUNET_SERVICE_shutdown (service->service);
+  if (service->peer)
+  {
+    GNUNET_free(service->peer);
 
-  GNUNET_free(service);
-}
+    service->peer = NULL;
+  }
 
-struct GNUNET_MESSENGER_EgoStore*
-get_service_ego_store (struct GNUNET_MESSENGER_Service *service)
-{
-  GNUNET_assert(service);
+  GNUNET_SERVICE_shutdown (service->service);
 
-  return &(service->ego_store);
+  GNUNET_free(service);
 }
 
 struct GNUNET_MESSENGER_ContactStore*
@@ -184,12 +181,27 @@ remove_service_handle (struct GNUNET_MESSENGER_Service 
*service,
 }
 
 int
-get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
+get_service_peer_identity (struct GNUNET_MESSENGER_Service *service,
                            struct GNUNET_PeerIdentity *peer)
 {
   GNUNET_assert((service) && (peer));
 
-  return GNUNET_CRYPTO_get_peer_identity (service->config, peer);
+  if (service->peer)
+  {
+    GNUNET_memcpy(peer, service->peer, sizeof(struct GNUNET_PeerIdentity));
+    return GNUNET_OK;
+  }
+
+  int result = GNUNET_CRYPTO_get_peer_identity(service->config, peer);
+
+  if (GNUNET_OK != result)
+    return result;
+
+  if (!service->peer)
+    service->peer = GNUNET_new(struct GNUNET_PeerIdentity);
+
+  GNUNET_memcpy(service->peer, peer, sizeof(struct GNUNET_PeerIdentity));
+  return result;
 }
 
 struct GNUNET_MESSENGER_SrvRoom*
@@ -272,8 +284,6 @@ close_service_room (struct GNUNET_MESSENGER_Service 
*service,
   if (!room)
     return GNUNET_NO;
 
-  send_srv_room_message (room, handle, create_message_leave ());
-
   const struct GNUNET_ShortHashCode *id = get_srv_handle_member_id (handle, 
key);
 
   GNUNET_assert(id);
@@ -304,7 +314,7 @@ close_service_room (struct GNUNET_MESSENGER_Service 
*service,
 void
 handle_service_message (struct GNUNET_MESSENGER_Service *service,
                         struct GNUNET_MESSENGER_SrvRoom *room,
-                        const struct GNUNET_MESSENGER_MemberSession *session,
+                        const struct GNUNET_MESSENGER_SenderSession *session,
                         const struct GNUNET_MESSENGER_Message *message,
                         const struct GNUNET_HashCode *hash)
 {
diff --git a/src/messenger/gnunet-service-messenger_service.h 
b/src/messenger/gnunet-service-messenger_service.h
index 36df81141..69486b415 100644
--- a/src/messenger/gnunet-service-messenger_service.h
+++ b/src/messenger/gnunet-service-messenger_service.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -31,13 +31,12 @@
 #include "gnunet_util_lib.h"
 #include "gnunet_identity_service.h"
 
-#include "gnunet-service-messenger_ego_store.h"
 #include "gnunet-service-messenger_list_handles.h"
 
 #include "messenger_api_contact_store.h"
-#include "gnunet-service-messenger_room.h"
 
-#include "gnunet-service-messenger_member_session.h"
+#include "gnunet-service-messenger_room.h"
+#include "gnunet-service-messenger_sender_session.h"
 
 struct GNUNET_MESSENGER_Service
 {
@@ -46,11 +45,11 @@ struct GNUNET_MESSENGER_Service
 
   struct GNUNET_SCHEDULER_Task *shutdown;
 
+  struct GNUNET_PeerIdentity *peer;
   char *dir;
 
   struct GNUNET_CADET_Handle *cadet;
 
-  struct GNUNET_MESSENGER_EgoStore ego_store;
   struct GNUNET_MESSENGER_ContactStore contact_store;
 
   struct GNUNET_MESSENGER_ListHandles handles;
@@ -77,15 +76,6 @@ create_service (const struct GNUNET_CONFIGURATION_Handle 
*config,
 void
 destroy_service (struct GNUNET_MESSENGER_Service *service);
 
-/**
- * Returns the used EGO-store of a given <i>service</i>.
- *
- * @param[in,out] service Service
- * @return EGO-store
- */
-struct GNUNET_MESSENGER_EgoStore*
-get_service_ego_store (struct GNUNET_MESSENGER_Service *service);
-
 /**
  * Returns the used contact store of a given <i>service</i>.
  *
@@ -120,12 +110,12 @@ remove_service_handle (struct GNUNET_MESSENGER_Service 
*service,
  * Tries to write the peer identity of the peer running a <i>service</i> on to 
the <i>peer</i>
  * parameter. The functions returns #GNUNET_OK on success, otherwise 
#GNUNET_SYSERR.
  *
- * @param[in] service Service
+ * @param[in,out] service Service
  * @param[out] peer Peer identity
  * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
  */
 int
-get_service_peer_identity (const struct GNUNET_MESSENGER_Service *service,
+get_service_peer_identity (struct GNUNET_MESSENGER_Service *service,
                            struct GNUNET_PeerIdentity *peer);
 
 /**
@@ -196,14 +186,14 @@ close_service_room (struct GNUNET_MESSENGER_Service 
*service,
  *
  * @param[in,out] service Service
  * @param[in,out] room Room
- * @param[in] session Member session
+ * @param[in] session Sender session
  * @param[in] message Message
  * @param[in] hash Hash of message
  */
 void
 handle_service_message (struct GNUNET_MESSENGER_Service *service,
                         struct GNUNET_MESSENGER_SrvRoom *room,
-                        const struct GNUNET_MESSENGER_MemberSession *session,
+                        const struct GNUNET_MESSENGER_SenderSession *session,
                         const struct GNUNET_MESSENGER_Message *message,
                         const struct GNUNET_HashCode *hash);
 
diff --git a/src/messenger/gnunet-service-messenger_tunnel.c 
b/src/messenger/gnunet-service-messenger_tunnel.c
index 8ad7fff1c..c82a42cd0 100644
--- a/src/messenger/gnunet-service-messenger_tunnel.c
+++ b/src/messenger/gnunet-service-messenger_tunnel.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2022 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -150,7 +150,6 @@ update_room_message (struct GNUNET_MESSENGER_SrvRoom *room,
 
 extern void
 callback_room_handle_message (struct GNUNET_MESSENGER_SrvRoom *room,
-                              struct GNUNET_MESSENGER_SrvHandle *handle,
                               const struct GNUNET_MESSENGER_Message *message,
                               const struct GNUNET_HashCode *hash);
 
@@ -223,7 +222,7 @@ handle_tunnel_message (void *cls, const struct 
GNUNET_MessageHeader *header)
   if (GNUNET_YES == forward_message)
   {
     forward_srv_room_message (tunnel->room, tunnel, &message, &hash);
-    callback_room_handle_message (tunnel->room, NULL, &message, &hash);
+    callback_room_handle_message (tunnel->room, &message, &hash);
   }
 
 receive_done:
@@ -349,7 +348,7 @@ forward_tunnel_message (struct GNUNET_MESSENGER_SrvTunnel 
*tunnel,
   GNUNET_assert((tunnel) && (message) && (hash));
 
   struct GNUNET_MESSENGER_Message *copy = copy_message(message);
-  struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, 
GNUNET_MESSENGER_PACK_MODE_ENVELOPE);
+  struct GNUNET_MQ_Envelope *env = pack_message (copy, NULL, NULL, 
GNUNET_MESSENGER_PACK_MODE_ENVELOPE, NULL);
 
   destroy_message(copy);
 
diff --git a/src/messenger/messenger_api.c b/src/messenger/messenger_api.c
index 610c979c4..82fc0d1eb 100644
--- a/src/messenger/messenger_api.c
+++ b/src/messenger/messenger_api.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -24,12 +24,15 @@
  */
 
 #include "platform.h"
+#include "gnunet_identity_service.h"
 #include "gnunet_messenger_service.h"
 
 #include "gnunet-service-messenger.h"
 
 #include "messenger_api_handle.h"
 #include "messenger_api_message.h"
+#include "messenger_api_message_kind.h"
+#include "messenger_api_room.h"
 #include "messenger_api_util.h"
 
 const char*
@@ -72,135 +75,107 @@ GNUNET_MESSENGER_name_of_kind (enum 
GNUNET_MESSENGER_MessageKind kind)
   }
 }
 
-static int
-check_get_name (void *cls,
-                const struct GNUNET_MESSENGER_NameMessage *msg)
-{
-  GNUNET_MQ_check_zero_termination(msg);
-  return GNUNET_OK;
-}
+static enum GNUNET_GenericReturnValue
+dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room);
 
 static void
-handle_get_name (void *cls,
-                 const struct GNUNET_MESSENGER_NameMessage *msg)
+handle_room_open (void *cls,
+                  const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
   struct GNUNET_MESSENGER_Handle *handle = cls;
 
-  const char *name = ((const char*) msg) + sizeof(*msg);
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set name of handle: %s\n", name);
-
-  set_handle_name (handle, strlen (name) > 0 ? name : NULL);
-}
-
-static int
-check_get_key (void *cls,
-               const struct GNUNET_MESSENGER_KeyMessage *msg)
-{
-  const uint16_t full_length = ntohs (msg->header.size);
+  const struct GNUNET_HashCode *key = &(msg->key);
 
-  if (full_length < sizeof(*msg))
-    return GNUNET_NO;
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
 
-  const uint16_t length = full_length - sizeof(*msg);
-  const char *buffer = ((const char*) msg) + sizeof(*msg);
+  open_handle_room (handle, key);
 
-  struct GNUNET_IDENTITY_PublicKey pubkey;
-  size_t read;
-  if (GNUNET_SYSERR ==
-      GNUNET_IDENTITY_read_public_key_from_buffer(buffer, length,
-                                                  &pubkey, &read))
-    return GNUNET_NO;
+  struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
 
-  return GNUNET_OK;
+  if (room)
+    dequeue_messages_from_room (room);
 }
 
 static void
-handle_get_key (void *cls,
-                const struct GNUNET_MESSENGER_KeyMessage *msg)
+handle_room_entry (void *cls,
+                   const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
   struct GNUNET_MESSENGER_Handle *handle = cls;
 
-  const uint16_t length = ntohs (msg->header.size) - sizeof(*msg);
-  const char *buffer = ((const char*) msg) + sizeof(*msg);
+  const struct GNUNET_PeerIdentity *door = &(msg->door);
+  const struct GNUNET_HashCode *key = &(msg->key);
 
-  struct GNUNET_IDENTITY_PublicKey pubkey;
-  size_t read;
-  if (GNUNET_SYSERR ==
-      GNUNET_IDENTITY_read_public_key_from_buffer(buffer, length,
-                                                  &pubkey, &read))
-    return;
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
 
-  char* str = GNUNET_IDENTITY_public_key_to_string (&pubkey);
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set key of handle: %s\n", str);
-  GNUNET_free(str);
+  entry_handle_room_at (handle, door, key);
 
-  set_handle_key (handle, &pubkey);
+  struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
 
-  if (handle->identity_callback)
-    handle->identity_callback (handle->identity_cls, handle);
+  if (room)
+    dequeue_messages_from_room (room);
 }
 
 static void
-handle_member_id (void *cls,
-                  const struct GNUNET_MESSENGER_MemberMessage *msg)
+handle_room_close (void *cls,
+                   const struct GNUNET_MESSENGER_RoomMessage *msg)
 {
   struct GNUNET_MESSENGER_Handle *handle = cls;
 
   const struct GNUNET_HashCode *key = &(msg->key);
-  const struct GNUNET_ShortHashCode *id = &(msg->id);
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set id of handle in room: %s\n", 
GNUNET_h2s (key));
-
-  struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get 
(handle->rooms, key);
+  struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
 
   if (room)
-  {
-    if (!room->contact_id)
-      room->contact_id = GNUNET_new(struct GNUNET_ShortHashCode);
+    dequeue_messages_from_room (room);
 
-    GNUNET_memcpy(room->contact_id, id, sizeof(*id));
-  }
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
+
+  close_handle_room (handle, key);
 }
 
 static void
-handle_room_open (void *cls,
-                  const struct GNUNET_MESSENGER_RoomMessage *msg)
-{
-  struct GNUNET_MESSENGER_Handle *handle = cls;
-
-  const struct GNUNET_HashCode *key = &(msg->key);
-
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Opened room: %s\n", GNUNET_h2s (key));
-
-  open_handle_room (handle, key);
-}
+enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room,
+                         struct GNUNET_MESSENGER_Message *message);
 
 static void
-handle_room_entry (void *cls,
-                   const struct GNUNET_MESSENGER_RoomMessage *msg)
+handle_member_id (void *cls,
+                  const struct GNUNET_MESSENGER_MemberMessage *msg)
 {
   struct GNUNET_MESSENGER_Handle *handle = cls;
 
-  const struct GNUNET_PeerIdentity *door = &(msg->door);
   const struct GNUNET_HashCode *key = &(msg->key);
+  const struct GNUNET_ShortHashCode *id = &(msg->id);
+  const uint32_t reset = msg->reset;
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Entered room: %s\n", GNUNET_h2s (key));
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Changed member id in room: %s\n", 
GNUNET_h2s (key));
 
-  entry_handle_room_at (handle, door, key);
-}
+  struct GNUNET_MESSENGER_Room *room = get_handle_room (handle, key);
 
-static void
-handle_room_close (void *cls,
-                   const struct GNUNET_MESSENGER_RoomMessage *msg)
-{
-  struct GNUNET_MESSENGER_Handle *handle = cls;
+  if (!room)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Room is unknown to handle: %s\n", 
GNUNET_h2s (key));
+    return;
+  }
 
-  const struct GNUNET_HashCode *key = &(msg->key);
+  struct GNUNET_MESSENGER_Message *message;
+  switch (reset)
+  {
+  case GNUNET_YES:
+    set_room_sender_id(room, id);
+    message = create_message_join (get_handle_key (handle));
+    break;
+  case GNUNET_NO:
+    message = create_message_id (id);
+    break;
+  default:
+    break;
+  }
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Closed room: %s\n", GNUNET_h2s (key));
+  if (!message)
+    return;
 
-  close_handle_room (handle, key);
+  enqueue_message_to_room (room, message);
+  destroy_message (message);
 }
 
 static int
@@ -210,7 +185,10 @@ check_recv_message (void *cls,
   const uint16_t full_length = ntohs (msg->header.size);
 
   if (full_length < sizeof(*msg))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Receiving failed: Message 
invalid!\n");
     return GNUNET_NO;
+  }
 
   const uint16_t length = full_length - sizeof(*msg);
   const char *buffer = ((const char*) msg) + sizeof(*msg);
@@ -218,10 +196,16 @@ check_recv_message (void *cls,
   struct GNUNET_MESSENGER_Message message;
 
   if (length < get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, 
GNUNET_YES))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Receiving failed: Message too 
short!\n");
     return GNUNET_NO;
+  }
 
   if (GNUNET_YES != decode_message (&message, length, buffer, GNUNET_YES, 
NULL))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR, "Receiving failed: Message decoding 
failed!\n");
     return GNUNET_NO;
+  }
 
   cleanup_message(&message);
   return GNUNET_OK;
@@ -237,7 +221,8 @@ handle_recv_message (void *cls,
   const struct GNUNET_HashCode *sender = &(msg->sender);
   const struct GNUNET_HashCode *context = &(msg->context);
   const struct GNUNET_HashCode *hash = &(msg->hash);
-  const enum GNUNET_MESSENGER_MessageFlags flags = (
+
+  enum GNUNET_MESSENGER_MessageFlags flags = (
       (enum GNUNET_MESSENGER_MessageFlags) (msg->flags)
   );
 
@@ -247,22 +232,38 @@ handle_recv_message (void *cls,
   struct GNUNET_MESSENGER_Message message;
   decode_message (&message, length, buffer, GNUNET_YES, NULL);
 
-  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n", 
GNUNET_MESSENGER_name_of_kind (message.header.kind));
+  struct GNUNET_MESSENGER_Message *private_message = NULL;
+  if (GNUNET_MESSENGER_KIND_PRIVATE == message.header.kind)
+  {
+    private_message = copy_message(&message);
 
-  struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get 
(handle->rooms, key);
+    if (GNUNET_YES != decrypt_message(private_message, get_handle_key(handle)))
+    {
+      destroy_message(private_message);
+      private_message = NULL;
+    }
+  }
+
+  if (private_message)
+    flags |= GNUNET_MESSENGER_FLAG_PRIVATE;
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Receiving message: %s\n",
+             GNUNET_MESSENGER_name_of_kind (private_message ? 
private_message->header.kind : message.header.kind));
+
+  struct GNUNET_MESSENGER_Room *room = get_handle_room(handle, key);
 
   if (room)
   {
     struct GNUNET_MESSENGER_ContactStore *store = 
get_handle_contact_store(handle);
 
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: 
(%s : %s)\n",
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Raw contact from sender and context: 
(%s : %s)\n",
                GNUNET_h2s(sender), GNUNET_h2s_full(context));
 
     struct GNUNET_MESSENGER_Contact *contact = get_store_contact_raw(
         store, context, sender
     );
 
-    contact = handle_room_message (room, contact, &message, hash);
+    contact = handle_room_message (room, contact, private_message ? 
private_message : &message, hash, flags);
 
     const struct GNUNET_MESSENGER_Message *stored_message = 
get_room_message(room, hash);
 
@@ -270,9 +271,42 @@ handle_recv_message (void *cls,
       handle->msg_callback (handle->msg_cls, room, contact, stored_message, 
hash, flags);
   }
   else
-    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", 
GNUNET_h2s (key));
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Unknown room for this client: %s\n", 
GNUNET_h2s (key));
 
   cleanup_message(&message);
+
+  if (private_message)
+    destroy_message(private_message);
+}
+
+static void
+handle_miss_message (void *cls,
+                     const struct GNUNET_MESSENGER_GetMessage *msg)
+{
+  struct GNUNET_MESSENGER_Handle *handle = cls;
+
+  const struct GNUNET_HashCode *key = &(msg->key);
+  const struct GNUNET_HashCode *hash = &(msg->hash);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Missing message in room: %s\n", 
GNUNET_h2s (hash));
+
+  struct GNUNET_MESSENGER_Room *room = get_handle_room(handle, key);
+
+  if (!room)
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Miss in unknown room for this 
client: %s\n", GNUNET_h2s (key));
+    return;
+  }
+
+  if (!get_room_sender_id(room))
+    return;
+
+  struct GNUNET_MESSENGER_Message *message = create_message_request (hash);
+  if (!message)
+    return;
+
+  enqueue_message_to_room (room, message);
+  destroy_message (message);
 }
 
 static void
@@ -282,11 +316,25 @@ static void
 send_open_room (struct GNUNET_MESSENGER_Handle *handle,
                 struct GNUNET_MESSENGER_Room *room)
 {
+  const struct GNUNET_IDENTITY_PublicKey *key = get_handle_pubkey(handle);
+
   struct GNUNET_MESSENGER_RoomMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
-  env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Open room (%s) by member using key: 
%s\n",
+              GNUNET_h2s (&(room->key)),
+              GNUNET_IDENTITY_public_key_to_string (key));
+
+  const ssize_t len = GNUNET_IDENTITY_public_key_get_length(key);
+
+  env = GNUNET_MQ_msg_extra(msg, len > 0 ? len : 0, 
GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_OPEN);
   GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
+
+  char *msg_buffer = ((char*) msg) + sizeof(*msg);
+
+  if (len > 0)
+    GNUNET_IDENTITY_write_public_key_to_buffer(key, msg_buffer, len);
+
   GNUNET_MQ_send (handle->mq, env);
 }
 
@@ -295,12 +343,27 @@ send_enter_room (struct GNUNET_MESSENGER_Handle *handle,
                  struct GNUNET_MESSENGER_Room *room,
                  const struct GNUNET_PeerIdentity *door)
 {
+  const struct GNUNET_IDENTITY_PublicKey *key = get_handle_pubkey(handle);
+
   struct GNUNET_MESSENGER_RoomMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
-  env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Enter room (%s) via door: %s (%s)\n",
+              GNUNET_h2s (&(room->key)),
+              GNUNET_i2s (door),
+              GNUNET_IDENTITY_public_key_to_string (key));
+
+  const ssize_t len = GNUNET_IDENTITY_public_key_get_length(key);
+
+  env = GNUNET_MQ_msg_extra(msg, len > 0 ? len : 0, 
GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_ENTRY);
   GNUNET_memcpy(&(msg->door), door, sizeof(*door));
   GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
+
+  char *msg_buffer = ((char*) msg) + sizeof(*msg);
+
+  if (len > 0)
+    GNUNET_IDENTITY_write_public_key_to_buffer(key, msg_buffer, len);
+
   GNUNET_MQ_send (handle->mq, env);
 }
 
@@ -311,6 +374,9 @@ send_close_room (struct GNUNET_MESSENGER_Handle *handle,
   struct GNUNET_MESSENGER_RoomMessage *msg;
   struct GNUNET_MQ_Envelope *env;
 
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Close room (%s)!\n",
+              GNUNET_h2s (&(room->key)));
+
   env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_CLOSE);
   GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
   GNUNET_MQ_send (handle->mq, env);
@@ -349,8 +415,9 @@ callback_reconnect (void *cls)
   struct GNUNET_MESSENGER_Handle *handle = cls;
 
   handle->reconnect_task = NULL;
-  handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time)
-  ;
+  handle->reconnect_time = GNUNET_TIME_STD_BACKOFF(handle->reconnect_time);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Reconnect messenger!\n");
 
   reconnect (handle);
 
@@ -394,14 +461,6 @@ reconnect (struct GNUNET_MESSENGER_Handle *handle)
 {
   const struct GNUNET_MQ_MessageHandler handlers[] =
   {
-   GNUNET_MQ_hd_var_size(
-        get_name, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_NAME,
-        struct GNUNET_MESSENGER_NameMessage, handle
-   ),
-   GNUNET_MQ_hd_var_size(
-       get_key, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_GET_KEY,
-       struct GNUNET_MESSENGER_KeyMessage, handle
-   ),
    GNUNET_MQ_hd_fixed_size(
        member_id,
        GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_MEMBER_ID,
@@ -427,6 +486,11 @@ reconnect (struct GNUNET_MESSENGER_Handle *handle)
        GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_RECV_MESSAGE,
        struct GNUNET_MESSENGER_RecvMessage, handle
    ),
+   GNUNET_MQ_hd_fixed_size(
+       miss_message,
+       GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_GET_MESSAGE,
+       struct GNUNET_MESSENGER_GetMessage, handle
+   ),
    GNUNET_MQ_handler_end()
   };
 
@@ -436,31 +500,25 @@ reconnect (struct GNUNET_MESSENGER_Handle *handle)
 struct GNUNET_MESSENGER_Handle*
 GNUNET_MESSENGER_connect (const struct GNUNET_CONFIGURATION_Handle *cfg,
                           const char *name,
-                          GNUNET_MESSENGER_IdentityCallback identity_callback,
-                          void *identity_cls,
+                          const struct GNUNET_IDENTITY_PrivateKey *key,
                           GNUNET_MESSENGER_MessageCallback msg_callback,
                           void *msg_cls)
 {
-  struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, 
identity_callback, identity_cls, msg_callback, msg_cls);
+  struct GNUNET_MESSENGER_Handle *handle = create_handle (cfg, msg_callback, 
msg_cls);
 
   reconnect (handle);
 
   if (handle->mq)
   {
-    const uint16_t name_len = name ? strlen (name) : 0;
+    set_handle_name (handle, name);
+
+    if ((!key) || (0 < GNUNET_IDENTITY_private_key_get_length (key)))
+      set_handle_key (handle, key);
 
     struct GNUNET_MESSENGER_CreateMessage *msg;
     struct GNUNET_MQ_Envelope *env;
 
-    env = GNUNET_MQ_msg_extra(msg, name_len + 1, 
GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
-
-    char *extra = ((char*) msg) + sizeof(*msg);
-
-    if (name_len)
-      GNUNET_memcpy(extra, name, name_len);
-
-    extra[name_len] = '\0';
-
+    env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_CREATE);
     GNUNET_MQ_send (handle->mq, env);
     return handle;
   }
@@ -471,20 +529,6 @@ GNUNET_MESSENGER_connect (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
   }
 }
 
-int
-GNUNET_MESSENGER_update (struct GNUNET_MESSENGER_Handle *handle)
-{
-  if ((!handle) || (!get_handle_name (handle)))
-    return GNUNET_SYSERR;
-
-  struct GNUNET_MESSENGER_UpdateMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
-
-  env = GNUNET_MQ_msg(msg, GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_UPDATE);
-  GNUNET_MQ_send (handle->mq, env);
-  return GNUNET_OK;
-}
-
 void
 GNUNET_MESSENGER_disconnect (struct GNUNET_MESSENGER_Handle *handle)
 {
@@ -500,6 +544,81 @@ GNUNET_MESSENGER_disconnect (struct 
GNUNET_MESSENGER_Handle *handle)
   destroy_handle (handle);
 }
 
+static void
+send_message_to_room (struct GNUNET_MESSENGER_Room *room,
+                      struct GNUNET_MESSENGER_Message *message,
+                      const struct GNUNET_IDENTITY_PrivateKey *key)
+{
+  const struct GNUNET_ShortHashCode *sender_id = get_room_sender_id (room);
+
+  message->header.timestamp = GNUNET_TIME_absolute_hton 
(GNUNET_TIME_absolute_get ());
+
+  GNUNET_memcpy (&(message->header.sender_id), sender_id, 
sizeof(message->header.sender_id));
+  GNUNET_memcpy (&(message->header.previous), &(room->last_message), 
sizeof(message->header.previous));
+
+  message->header.signature.type = key->type;
+
+  const uint16_t msg_length = get_message_size (message, GNUNET_YES);
+
+  struct GNUNET_MESSENGER_SendMessage *msg;
+  struct GNUNET_MQ_Envelope *env;
+
+  env = GNUNET_MQ_msg_extra(
+      msg, msg_length,
+      GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
+  );
+
+  GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
+
+  char *msg_buffer = ((char*) msg) + sizeof(*msg);
+  encode_message (message, msg_length, msg_buffer, GNUNET_YES);
+
+  struct GNUNET_HashCode hash;
+  hash_message (message, msg_length, msg_buffer, &hash);
+  sign_message (message, msg_length, msg_buffer, &hash, key);
+
+  GNUNET_memcpy (&(room->last_message), &hash, sizeof(room->last_message));
+
+  GNUNET_MQ_send (room->handle->mq, env);
+}
+
+static void
+enqueue_message_to_room (struct GNUNET_MESSENGER_Room *room,
+                         struct GNUNET_MESSENGER_Message *message)
+{
+  const struct GNUNET_IDENTITY_PrivateKey *key = get_handle_key (room->handle);
+
+  if (GNUNET_YES == is_room_available (room))
+  {
+    dequeue_messages_from_room (room);
+    send_message_to_room (room, message, key);
+  }
+  else
+    enqueue_to_messages(&(room->queue), key, message);
+}
+
+static enum GNUNET_GenericReturnValue
+dequeue_messages_from_room (struct GNUNET_MESSENGER_Room *room)
+{
+  struct GNUNET_MESSENGER_Message *message = NULL;
+  struct GNUNET_IDENTITY_PrivateKey key;
+
+  if (GNUNET_YES != is_room_available (room))
+    return room->queue.head ? GNUNET_NO : GNUNET_YES;
+
+  do {
+    if (message)
+      destroy_message(message);
+
+    message = dequeue_from_messages(&(room->queue), &key);
+
+    if (message)
+      send_message_to_room(room, message, &key);
+  } while (message);
+
+  return GNUNET_YES;
+}
+
 const char*
 GNUNET_MESSENGER_get_name (const struct GNUNET_MESSENGER_Handle *handle)
 {
@@ -509,35 +628,47 @@ GNUNET_MESSENGER_get_name (const struct 
GNUNET_MESSENGER_Handle *handle)
   return get_handle_name (handle);
 }
 
-int
-GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
-                           const char *name)
+static int
+iterate_send_name_to_room (void* cls,
+                           struct GNUNET_MESSENGER_Room *room,
+                           const struct GNUNET_MESSENGER_Contact *contact)
 {
-  if (!handle)
-    return GNUNET_SYSERR;
+  const struct GNUNET_MESSENGER_Handle *handle = cls;
 
-  const uint16_t name_len = name ? strlen (name) : 0;
+  if (GNUNET_YES != room->use_handle_name)
+    return GNUNET_YES;
 
-  struct GNUNET_MESSENGER_NameMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
+  const char *name = get_handle_name(handle);
 
-  env = GNUNET_MQ_msg_extra(msg, name_len + 1, 
GNUNET_MESSAGE_TYPE_MESSENGER_CONNECTION_SET_NAME);
+  if (!name)
+    return GNUNET_YES;
 
-  char *extra = ((char*) msg) + sizeof(*msg);
+  struct GNUNET_MESSENGER_Message *message = create_message_name (name);
 
-  if (name_len)
-    GNUNET_memcpy(extra, name, name_len);
+  if (!message)
+    return GNUNET_NO;
 
-  extra[name_len] = '\0';
+  enqueue_message_to_room (room, message);
+  destroy_message (message);
+  return GNUNET_YES;
+}
 
-  GNUNET_MQ_send (handle->mq, env);
+int
+GNUNET_MESSENGER_set_name (struct GNUNET_MESSENGER_Handle *handle,
+                           const char *name)
+{
+  if (!handle)
+    return GNUNET_SYSERR;
+
+  set_handle_name (handle, strlen (name) > 0 ? name : NULL);
+  GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_name_to_room, 
handle);
   return GNUNET_YES;
 }
 
 static const struct GNUNET_IDENTITY_PublicKey*
 get_non_anonymous_key (const struct GNUNET_IDENTITY_PublicKey* public_key)
 {
-  if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key()))
+  if (0 == GNUNET_memcmp(public_key, get_anonymous_public_key ()))
     return NULL;
 
   return public_key;
@@ -549,7 +680,49 @@ GNUNET_MESSENGER_get_key (const struct 
GNUNET_MESSENGER_Handle *handle)
   if (!handle)
     return NULL;
 
-  return get_non_anonymous_key (get_handle_key (handle));
+  return get_non_anonymous_key (get_handle_pubkey (handle));
+}
+
+static int
+iterate_send_key_to_room (void* cls,
+                          struct GNUNET_MESSENGER_Room *room,
+                          const struct GNUNET_MESSENGER_Contact *contact)
+{
+  const struct GNUNET_IDENTITY_PrivateKey *key = cls;
+
+  struct GNUNET_MESSENGER_Message *message = create_message_key (key);
+
+  if (!message)
+    return GNUNET_NO;
+
+  enqueue_message_to_room (room, message);
+  destroy_message (message);
+  return GNUNET_YES;
+}
+
+int
+GNUNET_MESSENGER_set_key (struct GNUNET_MESSENGER_Handle *handle,
+                          const struct GNUNET_IDENTITY_PrivateKey *key)
+{
+  if (!handle)
+    return GNUNET_SYSERR;
+  
+  if (!key)
+  {
+    GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, NULL);
+    set_handle_key (handle, NULL);
+    return GNUNET_YES;
+  }
+
+  if (0 >= GNUNET_IDENTITY_private_key_get_length (key))
+    return GNUNET_SYSERR;
+
+  struct GNUNET_IDENTITY_PrivateKey priv;
+  GNUNET_memcpy (&priv, key, sizeof (priv));
+
+  GNUNET_MESSENGER_find_rooms (handle, NULL, iterate_send_key_to_room, &priv);
+  set_handle_key (handle, &priv);
+  return GNUNET_YES;
 }
 
 struct GNUNET_MESSENGER_Room*
@@ -609,6 +782,14 @@ GNUNET_MESSENGER_close_room (struct GNUNET_MESSENGER_Room 
*room)
   if (!room)
     return;
 
+  struct GNUNET_MESSENGER_Message *message = create_message_leave();
+
+  if (message)
+  {
+    enqueue_message_to_room (room, message);
+    destroy_message (message);
+  }
+
   send_close_room (room->handle, room);
 }
 
@@ -699,7 +880,7 @@ GNUNET_MESSENGER_contact_get_key (const struct 
GNUNET_MESSENGER_Contact *contact
 
 void
 GNUNET_MESSENGER_send_message (struct GNUNET_MESSENGER_Room *room,
-                               const struct GNUNET_MESSENGER_Message *message,
+                               struct GNUNET_MESSENGER_Message *message,
                                const struct GNUNET_MESSENGER_Contact *contact)
 {
   if ((!room) || (!message))
@@ -717,53 +898,61 @@ GNUNET_MESSENGER_send_message (struct 
GNUNET_MESSENGER_Room *room,
     break;
   }
 
-  ssize_t key_length = 0;
+  char* original_name;
+  char* changed_name = NULL;
 
-  if (contact)
-  {
-    const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key 
(
-        get_contact_key(contact)
-    );
+  if (GNUNET_MESSENGER_KIND_NAME != message->header.kind)
+    goto skip_naming;
 
-    if (public_key)
-      key_length = GNUNET_IDENTITY_public_key_get_length(public_key);
-    else
-      key_length = -1;
-  }
+  original_name = message->body.name.name;
+  GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Apply rule for using handle name in 
room: %s\n", GNUNET_h2s (&(room->key)));
 
-  if (key_length < 0)
+  const char* handle_name = get_handle_name (room->handle);
+
+  if ((handle_name) && (GNUNET_YES == room->use_handle_name) &&
+      ((!original_name) || (0 == strlen (original_name))))
   {
-    GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid 
key!\n");
-    return;
+    changed_name = GNUNET_strdup (handle_name);
+    message->body.name.name = changed_name;
   }
 
-  const uint16_t msg_length = get_message_size (message, GNUNET_NO);
+skip_naming:
+  if (contact)
+  {
+    const struct GNUNET_IDENTITY_PublicKey *public_key = get_non_anonymous_key 
(
+        get_contact_key (contact)
+    );
 
-  struct GNUNET_MESSENGER_SendMessage *msg;
-  struct GNUNET_MQ_Envelope *env;
+    if (!public_key)
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_WARNING, "Sending message aborted: Invalid 
key!\n");
+      goto reset_naming;
+    }
 
-  const uint16_t length = (uint16_t) key_length + msg_length;
+    struct GNUNET_MESSENGER_Message *original = message;
+    message = copy_message(original);
 
-  env = GNUNET_MQ_msg_extra(
-      msg, length,
-      GNUNET_MESSAGE_TYPE_MESSENGER_ROOM_SEND_MESSAGE
-  );
+    if (GNUNET_YES != encrypt_message (message, public_key))
+    {
+      GNUNET_log(GNUNET_ERROR_TYPE_ERROR, "Sending message aborted: Encryption 
failed!\n");
 
-  GNUNET_memcpy(&(msg->key), &(room->key), sizeof(msg->key));
+      destroy_message(message);
+      message = original;
 
-  msg->flags = (uint32_t) (
-      contact? GNUNET_MESSENGER_FLAG_PRIVATE : GNUNET_MESSENGER_FLAG_NONE
-  );
+      goto reset_naming;
+    }
+  }
 
-  char *buffer = ((char*) msg) + sizeof(*msg);
-  char *msg_buffer = buffer + key_length;
+  enqueue_message_to_room (room, message);
 
-  if (key_length > 0)
-    GNUNET_IDENTITY_write_public_key_to_buffer(get_contact_key(contact), 
buffer, key_length);
+reset_naming:
+  if (changed_name)
+    GNUNET_free (changed_name);
 
-  encode_message (message, msg_length, msg_buffer, GNUNET_NO);
+  if (GNUNET_MESSENGER_KIND_NAME != message->header.kind)
+    return;
 
-  GNUNET_MQ_send (room->handle->mq, env);
+  message->body.name.name = original_name;
 }
 
 const struct GNUNET_MESSENGER_Message*
diff --git a/src/messenger/messenger_api_handle.c 
b/src/messenger/messenger_api_handle.c
index ec8d3dc7a..abede8e21 100644
--- a/src/messenger/messenger_api_handle.c
+++ b/src/messenger/messenger_api_handle.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -26,12 +26,11 @@
 #include "platform.h"
 #include "messenger_api_handle.h"
 
+#include "messenger_api_room.h"
 #include "messenger_api_util.h"
 
 struct GNUNET_MESSENGER_Handle*
 create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg,
-               GNUNET_MESSENGER_IdentityCallback identity_callback,
-               void *identity_cls,
                GNUNET_MESSENGER_MessageCallback msg_callback,
                void *msg_cls)
 {
@@ -42,13 +41,11 @@ create_handle (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
   handle->cfg = cfg;
   handle->mq = NULL;
 
-  handle->identity_callback = identity_callback;
-  handle->identity_cls = identity_cls;
-
   handle->msg_callback = msg_callback;
   handle->msg_cls = msg_cls;
 
   handle->name = NULL;
+  handle->key = NULL;
   handle->pubkey = NULL;
 
   handle->reconnect_time = GNUNET_TIME_relative_get_zero_ ();
@@ -87,6 +84,9 @@ destroy_handle (struct GNUNET_MESSENGER_Handle *handle)
   if (handle->name)
     GNUNET_free(handle->name);
 
+  if (handle->key)
+    GNUNET_free(handle->key);
+
   if (handle->pubkey)
     GNUNET_free(handle->pubkey);
 
@@ -106,12 +106,12 @@ void
 set_handle_name (struct GNUNET_MESSENGER_Handle *handle,
                  const char *name)
 {
-  GNUNET_assert(handle);
+  GNUNET_assert (handle);
 
   if (handle->name)
-    GNUNET_free(handle->name);
+    GNUNET_free (handle->name);
 
-  handle->name = name ? GNUNET_strdup(name) : NULL;
+  handle->name = name ? GNUNET_strdup (name) : NULL;
 }
 
 const char*
@@ -124,21 +124,49 @@ get_handle_name (const struct GNUNET_MESSENGER_Handle 
*handle)
 
 void
 set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
-                const struct GNUNET_IDENTITY_PublicKey *pubkey)
+                const struct GNUNET_IDENTITY_PrivateKey *key)
 {
-  GNUNET_assert(handle);
+  GNUNET_assert (handle);
+
+  if (!key)
+  {
+    if (handle->key)
+      GNUNET_free (handle->key);
+
+    if (handle->pubkey)
+      GNUNET_free (handle->pubkey);
+
+    handle->key = NULL;
+    handle->pubkey = NULL;
+    return;
+  }
+
+  if (!handle->key)
+    handle->key = GNUNET_new (struct GNUNET_IDENTITY_PrivateKey);
 
   if (!handle->pubkey)
-    handle->pubkey = GNUNET_new(struct GNUNET_IDENTITY_PublicKey);
+    handle->pubkey = GNUNET_new (struct GNUNET_IDENTITY_PublicKey);
 
-  GNUNET_memcpy(handle->pubkey, pubkey, sizeof(*pubkey));
+  GNUNET_memcpy (handle->key, key, sizeof(*key));
+  GNUNET_IDENTITY_key_get_public (key, handle->pubkey);
 }
 
-const struct GNUNET_IDENTITY_PublicKey*
+const struct GNUNET_IDENTITY_PrivateKey*
 get_handle_key (const struct GNUNET_MESSENGER_Handle *handle)
 {
   GNUNET_assert(handle);
 
+  if (handle->key)
+    return handle->key;
+
+  return get_anonymous_private_key();
+}
+
+const struct GNUNET_IDENTITY_PublicKey*
+get_handle_pubkey (const struct GNUNET_MESSENGER_Handle *handle)
+{
+  GNUNET_assert(handle);
+
   if (handle->pubkey)
     return handle->pubkey;
 
@@ -161,13 +189,19 @@ get_handle_contact (struct GNUNET_MESSENGER_Handle 
*handle,
 
   struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get 
(handle->rooms, key);
 
-  if ((!room) || (!(room->contact_id)))
+  if (!room)
+    return NULL;
+
+  const struct GNUNET_ShortHashCode *contact_id = get_room_sender_id (room);
+
+  if (!contact_id)
     return NULL;
 
   struct GNUNET_HashCode context;
-  get_context_from_member (key, room->contact_id, &context);
+  get_context_from_member (key, contact_id, &context);
 
-  return get_store_contact(get_handle_contact_store(handle), &context, 
get_handle_key(handle));
+  return get_store_contact (get_handle_contact_store (handle), &context,
+                            get_handle_pubkey (handle));
 }
 
 void
@@ -192,7 +226,7 @@ entry_handle_room_at (struct GNUNET_MESSENGER_Handle 
*handle,
   struct GNUNET_MESSENGER_Room *room = GNUNET_CONTAINER_multihashmap_get 
(handle->rooms, key);
 
   if (room)
-    add_to_list_tunnels (&(room->entries), door);
+    add_to_list_tunnels (&(room->entries), door, NULL);
 }
 
 void
@@ -206,3 +240,12 @@ close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
   if ((room) && (GNUNET_YES == GNUNET_CONTAINER_multihashmap_remove 
(handle->rooms, key, room)))
     destroy_room (room);
 }
+
+struct GNUNET_MESSENGER_Room*
+get_handle_room (struct GNUNET_MESSENGER_Handle *handle,
+                 const struct GNUNET_HashCode *key)
+{
+  GNUNET_assert((handle) && (key));
+
+  return GNUNET_CONTAINER_multihashmap_get (handle->rooms, key);
+}
diff --git a/src/messenger/messenger_api_handle.h 
b/src/messenger/messenger_api_handle.h
index d246855ff..2a97a45db 100644
--- a/src/messenger/messenger_api_handle.h
+++ b/src/messenger/messenger_api_handle.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -34,7 +34,6 @@
 #include "gnunet_messenger_service.h"
 
 #include "messenger_api_contact_store.h"
-#include "messenger_api_room.h"
 
 struct GNUNET_MESSENGER_Handle
 {
@@ -42,13 +41,11 @@ struct GNUNET_MESSENGER_Handle
 
   struct GNUNET_MQ_Handle *mq;
 
-  GNUNET_MESSENGER_IdentityCallback identity_callback;
-  void *identity_cls;
-
   GNUNET_MESSENGER_MessageCallback msg_callback;
   void *msg_cls;
 
   char *name;
+  struct GNUNET_IDENTITY_PrivateKey *key;
   struct GNUNET_IDENTITY_PublicKey *pubkey;
 
   struct GNUNET_TIME_Relative reconnect_time;
@@ -70,8 +67,6 @@ struct GNUNET_MESSENGER_Handle
  */
 struct GNUNET_MESSENGER_Handle*
 create_handle (const struct GNUNET_CONFIGURATION_Handle *cfg,
-               GNUNET_MESSENGER_IdentityCallback identity_callback,
-               void *identity_cls,
                GNUNET_MESSENGER_MessageCallback msg_callback,
                void *msg_cls);
 
@@ -103,14 +98,23 @@ const char*
 get_handle_name (const struct GNUNET_MESSENGER_Handle *handle);
 
 /**
- * Sets the public key of a given <i>handle</i> to a specific public key.
+ * Sets the keypair of a given <i>handle</i> to the keypair of a specific 
private <i>key</i>.
  *
  * @param[in,out] handle Handle
- * @param[in] pubkey Public key
+ * @param[in] key Private key or NULL
  */
 void
 set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
-                const struct GNUNET_IDENTITY_PublicKey *pubkey);
+                const struct GNUNET_IDENTITY_PrivateKey *key);
+
+/**
+ * Returns the private key of a given <i>handle</i>.
+ *
+ * @param[in] handle Handle
+ * @return Private key of the handle
+ */
+const struct GNUNET_IDENTITY_PrivateKey*
+get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
 
 /**
  * Returns the public key of a given <i>handle</i>.
@@ -119,7 +123,7 @@ set_handle_key (struct GNUNET_MESSENGER_Handle *handle,
  * @return Public key of the handle
  */
 const struct GNUNET_IDENTITY_PublicKey*
-get_handle_key (const struct GNUNET_MESSENGER_Handle *handle);
+get_handle_pubkey (const struct GNUNET_MESSENGER_Handle *handle);
 
 /**
  * Returns the used contact store of a given <i>handle</i>.
@@ -175,4 +179,15 @@ void
 close_handle_room (struct GNUNET_MESSENGER_Handle *handle,
                    const struct GNUNET_HashCode *key);
 
+/**
+ * Returns the room known to a <i>handle</i> identified by a given <i>key</i>.
+ *
+ * @param[in,out] handle handle Handle
+ * @param[in] key Key of room
+ * @return Room or NULL
+ */
+struct GNUNET_MESSENGER_Room*
+get_handle_room (struct GNUNET_MESSENGER_Handle *handle,
+                 const struct GNUNET_HashCode *key);
+
 #endif //GNUNET_MESSENGER_API_HANDLE_H
diff --git a/src/messenger/messenger_api_list_tunnels.c 
b/src/messenger/messenger_api_list_tunnels.c
index a4126c286..4d0deb95d 100644
--- a/src/messenger/messenger_api_list_tunnels.c
+++ b/src/messenger/messenger_api_list_tunnels.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -41,13 +41,7 @@ clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels 
*tunnels)
   GNUNET_assert(tunnels);
 
   struct GNUNET_MESSENGER_ListTunnel *element;
-
-  for (element = tunnels->head; element; element = tunnels->head)
-  {
-    GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
-    GNUNET_PEER_change_rc (element->peer, -1);
-    GNUNET_free(element);
-  }
+  for (element = tunnels->head; element; element = 
remove_from_list_tunnels(tunnels, element))
 
   tunnels->head = NULL;
   tunnels->tail = NULL;
@@ -63,13 +57,15 @@ compare_list_tunnels (void *cls,
 
 void
 add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
-                     const struct GNUNET_PeerIdentity *peer)
+                     const struct GNUNET_PeerIdentity *peer,
+                     const struct GNUNET_HashCode *hash)
 {
   GNUNET_assert((tunnels) && (peer));
 
   struct GNUNET_MESSENGER_ListTunnel *element = GNUNET_new(struct 
GNUNET_MESSENGER_ListTunnel);
 
   element->peer = GNUNET_PEER_intern (peer);
+  element->hash = hash ? GNUNET_memdup(hash, sizeof(struct GNUNET_HashCode)) : 
NULL;
 
   GNUNET_CONTAINER_DLL_insert_sorted(struct GNUNET_MESSENGER_ListTunnel, 
compare_list_tunnels, NULL, tunnels->head,
                                      tunnels->tail, element);
@@ -102,6 +98,31 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels 
*tunnels,
   return NULL;
 }
 
+void
+update_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
+                        const struct GNUNET_PeerIdentity *peer,
+                        const struct GNUNET_HashCode *hash)
+{
+  GNUNET_assert((tunnels) && (peer));
+
+  struct GNUNET_MESSENGER_ListTunnel* element = find_list_tunnels(tunnels, 
peer, NULL);
+  if (!element)
+    return;
+
+  if (element->hash)
+  {
+    if (hash)
+      GNUNET_memcpy(element->hash, hash, sizeof(struct GNUNET_HashCode));
+    else
+    {
+      GNUNET_free(element->hash);
+      element->hash = NULL;
+    }
+  }
+  else if (hash)
+    element->hash = GNUNET_memdup(hash, sizeof(struct GNUNET_HashCode));
+}
+
 int
 contains_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
                        const struct GNUNET_PeerIdentity *peer)
@@ -119,7 +140,12 @@ remove_from_list_tunnels (struct 
GNUNET_MESSENGER_ListTunnels *tunnels,
 
   struct GNUNET_MESSENGER_ListTunnel *next = element->next;
 
-  GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
+  if ((tunnels->head) && (tunnels->tail))
+    GNUNET_CONTAINER_DLL_remove(tunnels->head, tunnels->tail, element);
+
+  if (element->hash)
+    GNUNET_free(element->hash);
+
   GNUNET_PEER_change_rc (element->peer, -1);
   GNUNET_free(element);
 
@@ -155,7 +181,7 @@ load_list_tunnels (struct GNUNET_MESSENGER_ListTunnels 
*tunnels,
     if (len != sizeof(peer))
       break;
 
-    add_to_list_tunnels(tunnels, &peer);
+    add_to_list_tunnels(tunnels, &peer, NULL);
   } while (len == sizeof(peer));
 
   GNUNET_DISK_file_close(handle);
diff --git a/src/messenger/messenger_api_list_tunnels.h 
b/src/messenger/messenger_api_list_tunnels.h
index d2ceeafc2..212f2ae21 100644
--- a/src/messenger/messenger_api_list_tunnels.h
+++ b/src/messenger/messenger_api_list_tunnels.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -35,6 +35,7 @@ struct GNUNET_MESSENGER_ListTunnel
   struct GNUNET_MESSENGER_ListTunnel *next;
 
   GNUNET_PEER_Id peer;
+  struct GNUNET_HashCode *hash;
 };
 
 struct GNUNET_MESSENGER_ListTunnels
@@ -62,12 +63,16 @@ clear_list_tunnels (struct GNUNET_MESSENGER_ListTunnels 
*tunnels);
 /**
  * Adds a specific <i>peer</i> from a tunnel to the end of the list.
  *
+ * Optionally adds the <i>hash</i> of the peer message from the specific 
<i>peer</i>.
+ *
  * @param[in,out] tunnels List of peer identities
  * @param[in] peer Peer identity of tunnel
+ * @param[in] hash Hash of peer message or NULL
  */
 void
 add_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
-                     const struct GNUNET_PeerIdentity *peer);
+                     const struct GNUNET_PeerIdentity *peer,
+                     const struct GNUNET_HashCode *hash);
 
 /**
  * Searches linearly through the list of tunnels peer identities for matching a
@@ -89,6 +94,22 @@ find_list_tunnels (struct GNUNET_MESSENGER_ListTunnels 
*tunnels,
                    const struct GNUNET_PeerIdentity *peer,
                    size_t *index);
 
+/**
+ * Updates a specific <i>peer</i> from a tunnel in the list.
+ *
+ * This function exists to add the <i>hash</i> of a newer peer message
+ * from the specific <i>peer</i> to the list element. It can also remove
+ * the hash when NULL is provided as new <i>hash</i> value.
+ *
+ * @param[in,out] tunnels List of peer identities
+ * @param[in] peer Peer identity of tunnel
+ * @param[in] hash Hash of peer message or NULL
+ */
+void
+update_to_list_tunnels (struct GNUNET_MESSENGER_ListTunnels *tunnels,
+                        const struct GNUNET_PeerIdentity *peer,
+                        const struct GNUNET_HashCode *hash);
+
 /**
  * Tests linearly if the list of tunnels peer identities contains a specific
  * <i>peer</i> identity and returns #GNUNET_YES on success, otherwise 
#GNUNET_NO.
diff --git a/src/messenger/messenger_api_message.c 
b/src/messenger/messenger_api_message.c
index 31d0c94b8..3d9e125a4 100644
--- a/src/messenger/messenger_api_message.c
+++ b/src/messenger/messenger_api_message.c
@@ -41,8 +41,7 @@ struct GNUNET_MESSENGER_ShortMessage
 struct GNUNET_MESSENGER_Message*
 create_message (enum GNUNET_MESSENGER_MessageKind kind)
 {
-  struct GNUNET_MESSENGER_Message *message = GNUNET_new (struct
-                                                         
GNUNET_MESSENGER_Message);
+  struct GNUNET_MESSENGER_Message *message = GNUNET_new(struct 
GNUNET_MESSENGER_Message);
 
   message->header.kind = kind;
 
@@ -68,36 +67,32 @@ create_message (enum GNUNET_MESSENGER_MessageKind kind)
   return message;
 }
 
-
 struct GNUNET_MESSENGER_Message*
 copy_message (const struct GNUNET_MESSENGER_Message *message)
 {
-  GNUNET_assert (message);
+  GNUNET_assert(message);
 
-  struct GNUNET_MESSENGER_Message *copy = GNUNET_new (struct
-                                                      
GNUNET_MESSENGER_Message);
+  struct GNUNET_MESSENGER_Message *copy = GNUNET_new(struct 
GNUNET_MESSENGER_Message);
 
-  GNUNET_memcpy (copy, message, sizeof(struct GNUNET_MESSENGER_Message));
+  GNUNET_memcpy(copy, message, sizeof(struct GNUNET_MESSENGER_Message));
 
   switch (message->header.kind)
   {
   case GNUNET_MESSENGER_KIND_NAME:
-    copy->body.name.name = GNUNET_strdup (message->body.name.name);
+    copy->body.name.name = GNUNET_strdup(message->body.name.name);
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
-    copy->body.text.text = GNUNET_strdup (message->body.text.text);
+    copy->body.text.text = GNUNET_strdup(message->body.text.text);
     break;
   case GNUNET_MESSENGER_KIND_FILE:
-    copy->body.file.uri = GNUNET_strdup (message->body.file.uri);
+    copy->body.file.uri = GNUNET_strdup(message->body.file.uri);
     break;
   case GNUNET_MESSENGER_KIND_PRIVATE:
-    copy->body.privacy.data = copy->body.privacy.length ? GNUNET_malloc (
-      copy->body.privacy.length) : NULL;
+    copy->body.privacy.data = copy->body.privacy.length ? 
GNUNET_malloc(copy->body.privacy.length) : NULL;
 
     if (copy->body.privacy.data)
     {
-      GNUNET_memcpy (copy->body.privacy.data, message->body.privacy.data,
-                     copy->body.privacy.length);
+      GNUNET_memcpy(copy->body.privacy.data, message->body.privacy.data, 
copy->body.privacy.length);
     }
 
     break;
@@ -108,7 +103,6 @@ copy_message (const struct GNUNET_MESSENGER_Message 
*message)
   return copy;
 }
 
-
 static void
 destroy_message_body (enum GNUNET_MESSENGER_MessageKind kind,
                       struct GNUNET_MESSENGER_MessageBody *body)
@@ -116,47 +110,44 @@ destroy_message_body (enum GNUNET_MESSENGER_MessageKind 
kind,
   switch (kind)
   {
   case GNUNET_MESSENGER_KIND_NAME:
-    GNUNET_free (body->name.name);
+    GNUNET_free(body->name.name);
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
-    GNUNET_free (body->text.text);
+    GNUNET_free(body->text.text);
     break;
   case GNUNET_MESSENGER_KIND_FILE:
-    GNUNET_free (body->file.uri);
+    GNUNET_free(body->file.uri);
     break;
   case GNUNET_MESSENGER_KIND_PRIVATE:
-    GNUNET_free (body->privacy.data);
+    GNUNET_free(body->privacy.data);
     break;
   default:
     break;
   }
 }
 
-
 void
 cleanup_message (struct GNUNET_MESSENGER_Message *message)
 {
-  GNUNET_assert (message);
+  GNUNET_assert(message);
 
   destroy_message_body (message->header.kind, &(message->body));
 }
 
-
 void
 destroy_message (struct GNUNET_MESSENGER_Message *message)
 {
-  GNUNET_assert (message);
+  GNUNET_assert(message);
 
   destroy_message_body (message->header.kind, &(message->body));
 
-  GNUNET_free (message);
+  GNUNET_free(message);
 }
 
-
 int
 is_message_session_bound (const struct GNUNET_MESSENGER_Message *message)
 {
-  GNUNET_assert (message);
+  GNUNET_assert(message);
 
   if ((GNUNET_MESSENGER_KIND_JOIN == message->header.kind) ||
       (GNUNET_MESSENGER_KIND_LEAVE == message->header.kind) ||
@@ -168,18 +159,15 @@ is_message_session_bound (const struct 
GNUNET_MESSENGER_Message *message)
     return GNUNET_NO;
 }
 
-
 static void
 fold_short_message (const struct GNUNET_MESSENGER_Message *message,
                     struct GNUNET_MESSENGER_ShortMessage *shortened)
 {
   shortened->kind = message->header.kind;
 
-  GNUNET_memcpy (&(shortened->body), &(message->body), sizeof(struct
-                                                              
GNUNET_MESSENGER_MessageBody));
+  GNUNET_memcpy(&(shortened->body), &(message->body), sizeof(struct 
GNUNET_MESSENGER_MessageBody));
 }
 
-
 static void
 unfold_short_message (struct GNUNET_MESSENGER_ShortMessage *shortened,
                       struct GNUNET_MESSENGER_Message *message)
@@ -188,11 +176,9 @@ unfold_short_message (struct GNUNET_MESSENGER_ShortMessage 
*shortened,
 
   message->header.kind = shortened->kind;
 
-  GNUNET_memcpy (&(message->body), &(shortened->body), sizeof(struct
-                                                              
GNUNET_MESSENGER_MessageBody));
+  GNUNET_memcpy(&(message->body), &(shortened->body), sizeof(struct 
GNUNET_MESSENGER_MessageBody));
 }
 
-
 #define member_size(type, member) sizeof(((type*) NULL)->member)
 
 static uint16_t
@@ -203,40 +189,40 @@ get_message_body_kind_size (enum 
GNUNET_MESSENGER_MessageKind kind)
   switch (kind)
   {
   case GNUNET_MESSENGER_KIND_INFO:
-    length += member_size (struct GNUNET_MESSENGER_Message,
-                           body.info.messenger_version);
+    length += member_size(struct GNUNET_MESSENGER_Message, 
body.info.messenger_version);
     break;
   case GNUNET_MESSENGER_KIND_PEER:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.peer.peer);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.peer.peer);
     break;
   case GNUNET_MESSENGER_KIND_ID:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.id.id);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.id.id);
     break;
   case GNUNET_MESSENGER_KIND_MISS:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.miss.peer);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.miss.peer);
     break;
   case GNUNET_MESSENGER_KIND_MERGE:
-    length += member_size (struct GNUNET_MESSENGER_Message,
-                           body.merge.previous);
+    length += member_size(struct GNUNET_MESSENGER_Message, 
body.merge.previous);
     break;
   case GNUNET_MESSENGER_KIND_REQUEST:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.request.hash);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.request.hash);
     break;
   case GNUNET_MESSENGER_KIND_INVITE:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.invite.door);
-    length += member_size (struct GNUNET_MESSENGER_Message, body.invite.key);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.invite.door);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.invite.key);
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
     break;
   case GNUNET_MESSENGER_KIND_FILE:
-    length += member_size (struct GNUNET_MESSENGER_Message, body.file.key);
-    length += member_size (struct GNUNET_MESSENGER_Message, body.file.hash);
-    length += member_size (struct GNUNET_MESSENGER_Message, body.file.name);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.file.key);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.file.hash);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.file.name);
+    break;
+  case GNUNET_MESSENGER_KIND_PRIVATE:
+    length += member_size(struct GNUNET_MESSENGER_Message, body.privacy.key);
     break;
   case GNUNET_MESSENGER_KIND_DELETE:
-    length += member_size (struct GNUNET_MESSENGER_Message, 
body.deletion.hash);
-    length += member_size (struct GNUNET_MESSENGER_Message,
-                           body.deletion.delay);
+    length += member_size(struct GNUNET_MESSENGER_Message, body.deletion.hash);
+    length += member_size(struct GNUNET_MESSENGER_Message, 
body.deletion.delay);
     break;
   default:
     break;
@@ -245,7 +231,6 @@ get_message_body_kind_size (enum 
GNUNET_MESSENGER_MessageKind kind)
   return length;
 }
 
-
 typedef uint32_t kind_t;
 
 uint16_t
@@ -256,9 +241,9 @@ get_message_kind_size (enum GNUNET_MESSENGER_MessageKind 
kind,
 
   if (GNUNET_YES == include_header)
   {
-    length += member_size (struct GNUNET_MESSENGER_Message, header.timestamp);
-    length += member_size (struct GNUNET_MESSENGER_Message, header.sender_id);
-    length += member_size (struct GNUNET_MESSENGER_Message, header.previous);
+    length += member_size(struct GNUNET_MESSENGER_Message, header.timestamp);
+    length += member_size(struct GNUNET_MESSENGER_Message, header.sender_id);
+    length += member_size(struct GNUNET_MESSENGER_Message, header.previous);
   }
 
   length += sizeof(kind_t);
@@ -266,7 +251,6 @@ get_message_kind_size (enum GNUNET_MESSENGER_MessageKind 
kind,
   return length + get_message_body_kind_size (kind);
 }
 
-
 static uint16_t
 get_message_body_size (enum GNUNET_MESSENGER_MessageKind kind,
                        const struct GNUNET_MESSENGER_MessageBody *body)
@@ -275,17 +259,14 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind 
kind,
 
   switch (kind)
   {
-  case GNUNET_MESSENGER_KIND_INFO:
-    length += GNUNET_IDENTITY_public_key_get_length (&(body->info.host_key));
-    break;
   case GNUNET_MESSENGER_KIND_JOIN:
-    length += GNUNET_IDENTITY_public_key_get_length (&(body->join.key));
+    length += GNUNET_IDENTITY_public_key_get_length(&(body->join.key));
     break;
   case GNUNET_MESSENGER_KIND_NAME:
     length += (body->name.name ? strlen (body->name.name) : 0);
     break;
   case GNUNET_MESSENGER_KIND_KEY:
-    length += GNUNET_IDENTITY_public_key_get_length (&(body->key.key));
+    length += GNUNET_IDENTITY_public_key_get_length(&(body->key.key));
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
     length += strlen (body->text.text);
@@ -303,18 +284,16 @@ get_message_body_size (enum GNUNET_MESSENGER_MessageKind 
kind,
   return length;
 }
 
-
 uint16_t
 get_message_size (const struct GNUNET_MESSENGER_Message *message,
                   int include_header)
 {
-  GNUNET_assert (message);
+  GNUNET_assert(message);
 
   uint16_t length = 0;
 
   if (GNUNET_YES == include_header)
-    length += GNUNET_IDENTITY_signature_get_length (
-      &(message->header.signature));
+    length += 
GNUNET_IDENTITY_signature_get_length(&(message->header.signature));
 
   length += get_message_kind_size (message->header.kind, include_header);
   length += get_message_body_size (message->header.kind, &(message->body));
@@ -322,7 +301,6 @@ get_message_size (const struct GNUNET_MESSENGER_Message 
*message,
   return length;
 }
 
-
 static uint16_t
 get_short_message_size (const struct GNUNET_MESSENGER_ShortMessage *message,
                         int include_body)
@@ -331,24 +309,19 @@ get_short_message_size (const struct 
GNUNET_MESSENGER_ShortMessage *message,
 
   if (message)
     return minimum_size + get_message_body_kind_size (message->kind)
-           + (include_body == GNUNET_YES? get_message_body_size (message->kind,
-                                                                 
&(message->body))
-    : 0);
+           + (include_body == GNUNET_YES? get_message_body_size 
(message->kind, &(message->body)) : 0);
   else
     return minimum_size;
 }
 
-
 static uint16_t
 calc_usual_padding ()
 {
   uint16_t padding = 0;
   uint16_t kind_size;
 
-  for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++)
-  {
-    kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i,
-                                       GNUNET_YES);
+  for (int i = 0; i <= GNUNET_MESSENGER_KIND_MAX; i++) {
+    kind_size = get_message_kind_size ((enum GNUNET_MESSENGER_MessageKind) i, 
GNUNET_YES);
 
     if (kind_size > padding)
       padding = kind_size;
@@ -357,7 +330,6 @@ calc_usual_padding ()
   return padding + GNUNET_MESSENGER_PADDING_MIN;
 }
 
-
 #define max(x, y) (x > y? x : y)
 
 static uint16_t
@@ -365,13 +337,13 @@ calc_padded_length (uint16_t length)
 {
   static uint16_t usual_padding = 0;
 
-  if (! usual_padding)
-    usual_padding = calc_usual_padding ();
+  if (!usual_padding)
+    usual_padding = calc_usual_padding();
 
-  const uint16_t padded_length = max (
-    length + GNUNET_MESSENGER_PADDING_MIN,
-    usual_padding
-    );
+  const uint16_t padded_length = max(
+      length + GNUNET_MESSENGER_PADDING_MIN,
+      usual_padding
+  );
 
   if (padded_length <= GNUNET_MESSENGER_PADDING_LEVEL0)
     return GNUNET_MESSENGER_PADDING_LEVEL0;
@@ -386,35 +358,34 @@ calc_padded_length (uint16_t length)
 
 }
 
-
 #define min(x, y) (x < y? x : y)
 
 #define encode_step_ext(dst, offset, src, size) do { \
-    GNUNET_memcpy (dst + offset, src, size);            \
-    offset += size;                                    \
+       GNUNET_memcpy(dst + offset, src, size);                        \
+       offset += size;                                                \
 } while (0)
 
 #define encode_step(dst, offset, src) do {         \
-    encode_step_ext (dst, offset, src, sizeof(*src)); \
+  encode_step_ext(dst, offset, src, sizeof(*src)); \
 } while (0)
 
 #define encode_step_key(dst, offset, src, length) do {  \
-    ssize_t result = GNUNET_IDENTITY_write_public_key_to_buffer ( \
+  ssize_t result = GNUNET_IDENTITY_write_public_key_to_buffer( \
       src, dst + offset, length - offset                \
-      );                                                    \
-    if (result < 0)                                       \
+  );                                                    \
+  if (result < 0)                                       \
     GNUNET_break (0);                                   \
-    else                                                  \
+  else                                                  \
     offset += result;                                   \
 } while (0)
 
 #define encode_step_signature(dst, offset, src, length) do {  \
-    ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer ( \
+  ssize_t result = GNUNET_IDENTITY_write_signature_to_buffer( \
       src, dst + offset, length - offset                      \
-      );                                                          \
-    if (result < 0)                                             \
+  );                                                          \
+  if (result < 0)                                             \
     GNUNET_break (0);                                         \
-    else                                                        \
+  else                                                        \
     offset += result;                                         \
 } while (0)
 
@@ -429,63 +400,55 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind 
kind,
   switch (kind)
   {
   case GNUNET_MESSENGER_KIND_INFO:
-    version = GNUNET_htobe32 (body->info.messenger_version);
+    version = GNUNET_htobe32(body->info.messenger_version);
 
-    encode_step_key (buffer, offset, &(body->info.host_key), length);
-    encode_step (buffer, offset, &version);
+    encode_step(buffer, offset, &version);
     break;
   case GNUNET_MESSENGER_KIND_JOIN:
-    encode_step_key (buffer, offset, &(body->join.key), length);
+    encode_step_key(buffer, offset, &(body->join.key), length);
     break;
   case GNUNET_MESSENGER_KIND_NAME:
     if (body->name.name)
-      encode_step_ext (buffer, offset, body->name.name, min (length - offset,
-                                                             strlen (
-                                                               
body->name.name)));
+      encode_step_ext(buffer, offset, body->name.name, min(length - offset, 
strlen(body->name.name)));
     break;
   case GNUNET_MESSENGER_KIND_KEY:
-    encode_step_key (buffer, offset, &(body->key.key), length);
+    encode_step_key(buffer, offset, &(body->key.key), length);
     break;
   case GNUNET_MESSENGER_KIND_PEER:
-    encode_step (buffer, offset, &(body->peer.peer));
+    encode_step(buffer, offset, &(body->peer.peer));
     break;
   case GNUNET_MESSENGER_KIND_ID:
-    encode_step (buffer, offset, &(body->id.id));
+    encode_step(buffer, offset, &(body->id.id));
     break;
   case GNUNET_MESSENGER_KIND_MISS:
-    encode_step (buffer, offset, &(body->miss.peer));
+    encode_step(buffer, offset, &(body->miss.peer));
     break;
   case GNUNET_MESSENGER_KIND_MERGE:
-    encode_step (buffer, offset, &(body->merge.previous));
+    encode_step(buffer, offset, &(body->merge.previous));
     break;
   case GNUNET_MESSENGER_KIND_REQUEST:
-    encode_step (buffer, offset, &(body->request.hash));
+    encode_step(buffer, offset, &(body->request.hash));
     break;
   case GNUNET_MESSENGER_KIND_INVITE:
-    encode_step (buffer, offset, &(body->invite.door));
-    encode_step (buffer, offset, &(body->invite.key));
+    encode_step(buffer, offset, &(body->invite.door));
+    encode_step(buffer, offset, &(body->invite.key));
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
-    encode_step_ext (buffer, offset, body->text.text, min (length - offset,
-                                                           strlen (
-                                                             
body->text.text)));
+    encode_step_ext(buffer, offset, body->text.text, min(length - offset, 
strlen(body->text.text)));
     break;
   case GNUNET_MESSENGER_KIND_FILE:
-    encode_step (buffer, offset, &(body->file.key));
-    encode_step (buffer, offset, &(body->file.hash));
-    encode_step_ext (buffer, offset, body->file.name, sizeof(body->file.name));
-    encode_step_ext (buffer, offset, body->file.uri, min (length - offset,
-                                                          strlen (
-                                                            body->file.uri)));
+    encode_step(buffer, offset, &(body->file.key));
+    encode_step(buffer, offset, &(body->file.hash));
+    encode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
+    encode_step_ext(buffer, offset, body->file.uri, min(length - offset, 
strlen(body->file.uri)));
     break;
   case GNUNET_MESSENGER_KIND_PRIVATE:
-    encode_step_ext (buffer, offset, body->privacy.data, min (length - offset,
-                                                              body->privacy.
-                                                              length));
+    encode_step(buffer, offset, &(body->privacy.key));
+    encode_step_ext(buffer, offset, body->privacy.data, min(length - offset, 
body->privacy.length));
     break;
   case GNUNET_MESSENGER_KIND_DELETE:
-    encode_step (buffer, offset, &(body->deletion.hash));
-    encode_step (buffer, offset, &(body->deletion.delay));
+    encode_step(buffer, offset, &(body->deletion.hash));
+    encode_step(buffer, offset, &(body->deletion.delay));
     break;
   default:
     break;
@@ -497,48 +460,43 @@ encode_message_body (enum GNUNET_MESSENGER_MessageKind 
kind,
   const uint16_t padding = length - offset;
   const uint16_t used_padding = sizeof(padding) + sizeof(char);
 
-  GNUNET_assert (padding >= used_padding);
+  GNUNET_assert(padding >= used_padding);
 
   buffer[offset++] = '\0';
 
   if (padding > used_padding)
-    GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset,
-                                padding - used_padding);
+    GNUNET_CRYPTO_random_block(GNUNET_CRYPTO_QUALITY_WEAK, buffer + offset, 
padding - used_padding);
 
-  GNUNET_memcpy (buffer + length - sizeof(padding), &padding, sizeof(padding));
+  GNUNET_memcpy(buffer + length - sizeof(padding), &padding, sizeof(padding));
 }
 
-
 void
 encode_message (const struct GNUNET_MESSENGER_Message *message,
                 uint16_t length,
                 char *buffer,
                 int include_header)
 {
-  GNUNET_assert ((message) && (buffer));
+  GNUNET_assert((message) && (buffer));
 
   uint16_t offset = 0;
 
   if (GNUNET_YES == include_header)
-    encode_step_signature (buffer, offset, &(message->header.signature),
-                           length);
+    encode_step_signature(buffer, offset, &(message->header.signature), 
length);
 
-  const kind_t kind = GNUNET_htobe32 ((kind_t) message->header.kind);
+  const kind_t kind = GNUNET_htobe32((kind_t) message->header.kind);
 
   if (GNUNET_YES == include_header)
   {
-    encode_step (buffer, offset, &(message->header.timestamp));
-    encode_step (buffer, offset, &(message->header.sender_id));
-    encode_step (buffer, offset, &(message->header.previous));
+    encode_step(buffer, offset, &(message->header.timestamp));
+    encode_step(buffer, offset, &(message->header.sender_id));
+    encode_step(buffer, offset, &(message->header.previous));
   }
 
-  encode_step (buffer, offset, &kind);
+  encode_step(buffer, offset, &kind);
 
-  encode_message_body (message->header.kind, &(message->body), length, buffer,
-                       offset);
+  encode_message_body (message->header.kind, &(message->body), length, buffer, 
offset);
 }
 
-
 static void
 encode_short_message (const struct GNUNET_MESSENGER_ShortMessage *message,
                       uint16_t length,
@@ -547,46 +505,45 @@ encode_short_message (const struct 
GNUNET_MESSENGER_ShortMessage *message,
   struct GNUNET_HashCode hash;
   uint16_t offset = sizeof(hash);
 
-  const kind_t kind = GNUNET_htobe32 ((kind_t) message->kind);
+  const kind_t kind = GNUNET_htobe32((kind_t) message->kind);
 
-  encode_step (buffer, offset, &kind);
+  encode_step(buffer, offset, &kind);
 
   encode_message_body (message->kind, &(message->body), length, buffer, 
offset);
 
-  GNUNET_CRYPTO_hash (
-    buffer + sizeof(hash),
-    length - sizeof(hash),
-    &hash
-    );
+  GNUNET_CRYPTO_hash(
+      buffer + sizeof(hash),
+      length - sizeof(hash),
+      &hash
+  );
 
-  GNUNET_memcpy (buffer, &hash, sizeof(hash));
+  GNUNET_memcpy(buffer, &hash, sizeof(hash));
 }
 
-
 #define decode_step_ext(src, offset, dst, size) do { \
-    GNUNET_memcpy (dst, src + offset, size);            \
-    offset += size;                                    \
+       GNUNET_memcpy(dst, src + offset, size);                              \
+       offset += size;                                                      \
 } while (0)
 
-#define decode_step(src, offset, dst) do {         \
-    decode_step_ext (src, offset, dst, sizeof(*dst)); \
+#define decode_step(src, offset, dst) do {                              \
+  decode_step_ext(src, offset, dst, sizeof(*dst)); \
 } while (0)
 
-#define decode_step_malloc(src, offset, dst, size, zero) do { \
-    dst = GNUNET_malloc (size + zero);                           \
-    if (zero) dst[size] = 0;                                    \
-    decode_step_ext (src, offset, dst, size);                    \
+#define decode_step_malloc(src, offset, dst, size, zero) do {  \
+       dst = GNUNET_malloc(size + zero);                           \
+  if (zero) dst[size] = 0;                                                     
                                  \
+       decode_step_ext(src, offset, dst, size);                                
                  \
 } while (0)
 
 #define decode_step_key(src, offset, dst, length) do {   \
-    enum GNUNET_GenericReturnValue result;                 \
-    size_t read;                                           \
-    result = GNUNET_IDENTITY_read_public_key_from_buffer (  \
-      src + offset, length - offset, dst, &read            \
-      );                                                     \
-    if (GNUNET_SYSERR == result)                                        \
-    GNUNET_break (0);                                     \
-    else                                                   \
+  enum GNUNET_GenericReturnValue result;                 \
+  size_t read;                                           \
+  result = GNUNET_IDENTITY_read_public_key_from_buffer(  \
+    src + offset, length - offset, dst, &read            \
+  );                                                     \
+  if (GNUNET_SYSERR == result)                                        \
+    GNUNET_break(0);                                     \
+  else                                                   \
     offset += read;                                    \
 } while (0)
 
@@ -599,7 +556,7 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind 
*kind,
 {
   uint16_t padding = 0;
 
-  GNUNET_memcpy (&padding, buffer + length - sizeof(padding), sizeof(padding));
+  GNUNET_memcpy(&padding, buffer + length - sizeof(padding), sizeof(padding));
 
   if (padding > length - offset)
     padding = 0;
@@ -615,58 +572,59 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind 
*kind,
   switch (*kind)
   {
   case GNUNET_MESSENGER_KIND_INFO: {
-      decode_step_key (buffer, offset, &(body->info.host_key), length);
-      decode_step (buffer, offset, &version);
-
-      body->info.messenger_version = GNUNET_be32toh (version);
-      break;
-    } case GNUNET_MESSENGER_KIND_JOIN: {
-      decode_step_key (buffer, offset, &(body->join.key), length);
-      break;
-    } case GNUNET_MESSENGER_KIND_NAME:
+    decode_step(buffer, offset, &version);
+
+    body->info.messenger_version = GNUNET_be32toh(version);
+    break;
+  } case GNUNET_MESSENGER_KIND_JOIN: {
+    decode_step_key(buffer, offset, &(body->join.key), length);
+    break;
+  } case GNUNET_MESSENGER_KIND_NAME:
     if (length - offset > 0)
-      decode_step_malloc (buffer, offset, body->name.name, length - offset, 1);
+      decode_step_malloc(buffer, offset, body->name.name, length - offset, 1);
     else
       body->name.name = NULL;
     break;
   case GNUNET_MESSENGER_KIND_KEY:
-    decode_step_key (buffer, offset, &(body->key.key), length);
+    decode_step_key(buffer, offset, &(body->key.key), length);
     break;
   case GNUNET_MESSENGER_KIND_PEER:
-    decode_step (buffer, offset, &(body->peer.peer));
+    decode_step(buffer, offset, &(body->peer.peer));
     break;
   case GNUNET_MESSENGER_KIND_ID:
-    decode_step (buffer, offset, &(body->id.id));
+    decode_step(buffer, offset, &(body->id.id));
     break;
   case GNUNET_MESSENGER_KIND_MISS:
-    decode_step (buffer, offset, &(body->miss.peer));
+    decode_step(buffer, offset, &(body->miss.peer));
     break;
   case GNUNET_MESSENGER_KIND_MERGE:
-    decode_step (buffer, offset, &(body->merge.previous));
+    decode_step(buffer, offset, &(body->merge.previous));
     break;
   case GNUNET_MESSENGER_KIND_REQUEST:
-    decode_step (buffer, offset, &(body->request.hash));
+    decode_step(buffer, offset, &(body->request.hash));
     break;
   case GNUNET_MESSENGER_KIND_INVITE:
-    decode_step (buffer, offset, &(body->invite.door));
-    decode_step (buffer, offset, &(body->invite.key));
+    decode_step(buffer, offset, &(body->invite.door));
+    decode_step(buffer, offset, &(body->invite.key));
     break;
   case GNUNET_MESSENGER_KIND_TEXT:
-    decode_step_malloc (buffer, offset, body->text.text, length - offset, 1);
+    decode_step_malloc(buffer, offset, body->text.text, length - offset, 1);
     break;
   case GNUNET_MESSENGER_KIND_FILE:
-    decode_step (buffer, offset, &(body->file.key));
-    decode_step (buffer, offset, &(body->file.hash));
-    decode_step_ext (buffer, offset, body->file.name, sizeof(body->file.name));
-    decode_step_malloc (buffer, offset, body->file.uri, length - offset, 1);
+    decode_step(buffer, offset, &(body->file.key));
+    decode_step(buffer, offset, &(body->file.hash));
+    decode_step_ext(buffer, offset, body->file.name, sizeof(body->file.name));
+    decode_step_malloc(buffer, offset, body->file.uri, length - offset, 1);
     break;
   case GNUNET_MESSENGER_KIND_PRIVATE:
+    decode_step(buffer, offset, &(body->privacy.key));
+
     body->privacy.length = (length - offset);
-    decode_step_malloc (buffer, offset, body->privacy.data, length - offset, 
0);
+    decode_step_malloc(buffer, offset, body->privacy.data, length - offset, 0);
     break;
   case GNUNET_MESSENGER_KIND_DELETE:
-    decode_step (buffer, offset, &(body->deletion.hash));
-    decode_step (buffer, offset, &(body->deletion.delay));
+    decode_step(buffer, offset, &(body->deletion.hash));
+    decode_step(buffer, offset, &(body->deletion.delay));
     break;
   default:
     *kind = GNUNET_MESSENGER_KIND_UNKNOWN;
@@ -676,7 +634,6 @@ decode_message_body (enum GNUNET_MESSENGER_MessageKind 
*kind,
   return padding;
 }
 
-
 int
 decode_message (struct GNUNET_MESSENGER_Message *message,
                 uint16_t length,
@@ -684,20 +641,19 @@ decode_message (struct GNUNET_MESSENGER_Message *message,
                 int include_header,
                 uint16_t *padding)
 {
-  GNUNET_assert (
-    (message) &&
-    (buffer) &&
-    (length >= get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
-                                      include_header))
-    );
+  GNUNET_assert(
+      (message) &&
+      (buffer) &&
+      (length >= get_message_kind_size(GNUNET_MESSENGER_KIND_UNKNOWN, 
include_header))
+  );
 
   uint16_t offset = 0;
 
   if (GNUNET_YES == include_header)
   {
-    ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer (
-      &(message->header.signature), buffer, length - offset
-      );
+    ssize_t result = GNUNET_IDENTITY_read_signature_from_buffer(
+        &(message->header.signature), buffer, length - offset
+    );
 
     if (result < 0)
       return GNUNET_NO;
@@ -707,30 +663,26 @@ decode_message (struct GNUNET_MESSENGER_Message *message,
 
   const uint16_t count = length - offset;
 
-  if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN,
-                                     include_header))
+  if (count < get_message_kind_size (GNUNET_MESSENGER_KIND_UNKNOWN, 
include_header))
     return GNUNET_NO;
 
   kind_t kind;
 
   if (GNUNET_YES == include_header)
   {
-    decode_step (buffer, offset, &(message->header.timestamp));
-    decode_step (buffer, offset, &(message->header.sender_id));
-    decode_step (buffer, offset, &(message->header.previous));
+    decode_step(buffer, offset, &(message->header.timestamp));
+    decode_step(buffer, offset, &(message->header.sender_id));
+    decode_step(buffer, offset, &(message->header.previous));
   }
 
-  decode_step (buffer, offset, &kind);
+  decode_step(buffer, offset, &kind);
 
-  message->header.kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh (
-    kind);
+  message->header.kind = (enum GNUNET_MESSENGER_MessageKind) 
GNUNET_be32toh(kind);
 
   if (count < get_message_kind_size (message->header.kind, include_header))
     return GNUNET_NO;
 
-  const uint16_t result = decode_message_body (&(message->header.kind),
-                                               &(message->body), length, 
buffer,
-                                               offset);
+  const uint16_t result = decode_message_body (&(message->header.kind), 
&(message->body), length, buffer, offset);
 
   if (padding)
     *padding = result;
@@ -738,7 +690,6 @@ decode_message (struct GNUNET_MESSENGER_Message *message,
   return GNUNET_YES;
 }
 
-
 static int
 decode_short_message (struct GNUNET_MESSENGER_ShortMessage *message,
                       uint16_t length,
@@ -750,28 +701,27 @@ decode_short_message (struct 
GNUNET_MESSENGER_ShortMessage *message,
   if (length < get_short_message_size (NULL, GNUNET_NO))
     return GNUNET_NO;
 
-  GNUNET_memcpy (&hash, buffer, sizeof(hash));
+  GNUNET_memcpy(&hash, buffer, sizeof(hash));
 
-  GNUNET_CRYPTO_hash (
-    buffer + sizeof(hash),
-    length - sizeof(hash),
-    &expected
-    );
+  GNUNET_CRYPTO_hash(
+      buffer + sizeof(hash),
+      length - sizeof(hash),
+      &expected
+  );
 
-  if (0 != GNUNET_CRYPTO_hash_cmp (&hash, &expected))
+  if (0 != GNUNET_CRYPTO_hash_cmp(&hash, &expected))
     return GNUNET_NO;
 
   kind_t kind;
 
-  decode_step (buffer, offset, &kind);
+  decode_step(buffer, offset, &kind);
 
-  message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh (kind);
+  message->kind = (enum GNUNET_MESSENGER_MessageKind) GNUNET_be32toh(kind);
 
   if (length < get_short_message_size (message, GNUNET_NO))
     return GNUNET_NO;
 
-  decode_message_body (&(message->kind), &(message->body), length, buffer,
-                       offset);
+  decode_message_body (&(message->kind), &(message->body), length, buffer, 
offset);
 
   if (GNUNET_MESSENGER_KIND_UNKNOWN == message->kind)
     return GNUNET_NO;
@@ -779,53 +729,81 @@ decode_short_message (struct 
GNUNET_MESSENGER_ShortMessage *message,
   return GNUNET_YES;
 }
 
-
 void
 hash_message (const struct GNUNET_MESSENGER_Message *message,
               uint16_t length,
               const char *buffer,
               struct GNUNET_HashCode *hash)
 {
-  GNUNET_assert ((message) && (buffer) && (hash));
+  GNUNET_assert((message) && (buffer) && (hash));
 
-  const ssize_t offset = GNUNET_IDENTITY_signature_get_length (
-    &(message->header.signature)
-    );
+  const ssize_t offset = GNUNET_IDENTITY_signature_get_length(
+      &(message->header.signature)
+  );
 
   GNUNET_CRYPTO_hash (buffer + offset, length - offset, hash);
 }
 
-
 void
 sign_message (struct GNUNET_MESSENGER_Message *message,
               uint16_t length,
               char *buffer,
               const struct GNUNET_HashCode *hash,
-              const struct GNUNET_MESSENGER_Ego *ego)
+              const struct GNUNET_IDENTITY_PrivateKey *key)
 {
-  GNUNET_assert ((message) && (buffer) && (hash) && (ego));
+  GNUNET_assert((message) && (buffer) && (hash) && (key));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sign message by member: %s\n",
+              GNUNET_h2s (hash));
 
   struct GNUNET_MESSENGER_MessageSignature signature;
 
   signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
   signature.purpose.size = htonl (sizeof(signature));
 
-  GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
-  GNUNET_IDENTITY_sign (&(ego->priv), &signature, 
&(message->header.signature));
+  GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
+  GNUNET_IDENTITY_sign(key, &signature, &(message->header.signature));
+
+  message->header.signature.type = key->type;
 
   uint16_t offset = 0;
-  encode_step_signature (buffer, offset, &(message->header.signature), length);
+  encode_step_signature(buffer, offset, &(message->header.signature), length);
 }
 
+void
+sign_message_by_peer (struct GNUNET_MESSENGER_Message *message,
+                      uint16_t length,
+                      char *buffer,
+                      const struct GNUNET_HashCode *hash,
+                      const struct GNUNET_CONFIGURATION_Handle* cfg)
+{
+  GNUNET_assert((message) && (buffer) && (hash) && (cfg));
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Sign message by peer: %s\n",
+              GNUNET_h2s (hash));
+
+  struct GNUNET_MESSENGER_MessageSignature signature;
+
+  signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
+  signature.purpose.size = htonl (sizeof(signature));
+
+  GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
+  GNUNET_CRYPTO_sign_by_peer_identity(cfg, &signature.purpose, 
&(message->header.signature.eddsa_signature));
+
+  message->header.signature.type = htonl (GNUNET_IDENTITY_TYPE_EDDSA);
+
+  uint16_t offset = 0;
+  encode_step_signature(buffer, offset, &(message->header.signature), length);
+}
 
 int
 verify_message (const struct GNUNET_MESSENGER_Message *message,
                 const struct GNUNET_HashCode *hash,
                 const struct GNUNET_IDENTITY_PublicKey *key)
 {
-  GNUNET_assert ((message) && (hash) && (key));
+  GNUNET_assert((message) && (hash) && (key));
 
-  if (ntohl (key->type) != ntohl (message->header.signature.type))
+  if (key->type != message->header.signature.type)
     return GNUNET_SYSERR;
 
   struct GNUNET_MESSENGER_MessageSignature signature;
@@ -833,19 +811,41 @@ verify_message (const struct GNUNET_MESSENGER_Message 
*message,
   signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
   signature.purpose.size = htonl (sizeof(signature));
 
-  GNUNET_memcpy (&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
+  GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
 
-  return GNUNET_IDENTITY_signature_verify (
-    GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
-    &(message->header.signature), key);
+  return GNUNET_IDENTITY_signature_verify 
(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature,
+                                           &(message->header.signature), key);
 }
 
+int
+verify_message_by_peer (const struct GNUNET_MESSENGER_Message *message,
+                        const struct GNUNET_HashCode *hash,
+                        const struct GNUNET_PeerIdentity *identity)
+{
+  GNUNET_assert((message) && (hash) && (identity));
+
+  if (ntohl (GNUNET_IDENTITY_TYPE_EDDSA) != message->header.signature.type)
+    return GNUNET_SYSERR;
+
+  struct GNUNET_MESSENGER_MessageSignature signature;
+
+  signature.purpose.purpose = htonl (GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE);
+  signature.purpose.size = htonl (sizeof(signature));
+
+  GNUNET_memcpy(&(signature.hash), hash, sizeof(struct GNUNET_HashCode));
+
+  return GNUNET_CRYPTO_verify_peer_identity 
(GNUNET_SIGNATURE_PURPOSE_CHAT_MESSAGE, &signature.purpose,
+                                             
&(message->header.signature.eddsa_signature), identity);
+}
 
 int
 encrypt_message (struct GNUNET_MESSENGER_Message *message,
                  const struct GNUNET_IDENTITY_PublicKey *key)
 {
-  GNUNET_assert ((message) && (key));
+  GNUNET_assert((message) && (key));
+
+  if (GNUNET_YES == is_service_message(message))
+    return GNUNET_NO;
 
   struct GNUNET_MESSENGER_ShortMessage shortened;
 
@@ -854,7 +854,7 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message,
   const uint16_t length = get_short_message_size (&shortened, GNUNET_YES);
   const uint16_t padded_length = calc_padded_length (
     length + GNUNET_IDENTITY_ENCRYPT_OVERHEAD_BYTES
-    );
+  );
 
   message->header.kind = GNUNET_MESSENGER_KIND_PRIVATE;
   message->body.privacy.data = GNUNET_malloc (padded_length);
@@ -862,7 +862,7 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message,
 
   const uint16_t encoded_length = (
     padded_length - GNUNET_IDENTITY_ENCRYPT_OVERHEAD_BYTES
-    );
+  );
 
   encode_short_message (&shortened, encoded_length, 
message->body.privacy.data);
 
@@ -882,7 +882,6 @@ encrypt_message (struct GNUNET_MESSENGER_Message *message,
   return GNUNET_YES;
 }
 
-
 int
 decrypt_message (struct GNUNET_MESSENGER_Message *message,
                  const struct GNUNET_IDENTITY_PrivateKey *key)
@@ -901,7 +900,7 @@ decrypt_message (struct GNUNET_MESSENGER_Message *message,
 
   const uint16_t encoded_length = (
     padded_length - GNUNET_IDENTITY_ENCRYPT_OVERHEAD_BYTES
-    );
+  );
 
   if (GNUNET_OK != GNUNET_IDENTITY_decrypt (message->body.privacy.data,
                                             padded_length,
@@ -930,34 +929,29 @@ decrypt_message (struct GNUNET_MESSENGER_Message *message,
   return GNUNET_YES;
 }
 
-
 struct GNUNET_MQ_Envelope*
 pack_message (struct GNUNET_MESSENGER_Message *message,
               struct GNUNET_HashCode *hash,
-              const struct GNUNET_MESSENGER_Ego *ego,
-              int mode)
+              const GNUNET_MESSENGER_SignFunction sign,
+              int mode,
+              const void *cls)
 {
-  GNUNET_assert (message);
-
-  if (ego)
-    message->header.signature.type = ego->priv.type;
+  GNUNET_assert(message);
 
-  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG,
-              "Packing message kind=%u and sender: %s\n",
-              message->header.kind, GNUNET_sh2s 
(&(message->header.sender_id)));
+  GNUNET_log(GNUNET_ERROR_TYPE_INFO, "Packing message kind=%u and sender: 
%s\n",
+             message->header.kind, GNUNET_sh2s(&(message->header.sender_id)));
 
   struct GNUNET_MessageHeader *header;
 
   const uint16_t length = get_message_size (message, GNUNET_YES);
-  const uint16_t padded_length = calc_padded_length (length);
+  const uint16_t padded_length = calc_padded_length(length);
 
   struct GNUNET_MQ_Envelope *env;
   char *buffer;
 
   if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE == mode)
   {
-    env = GNUNET_MQ_msg_extra (header, padded_length,
-                               GNUNET_MESSAGE_TYPE_CADET_CLI);
+    env = GNUNET_MQ_msg_extra(header, padded_length, 
GNUNET_MESSAGE_TYPE_CADET_CLI);
 
     buffer = (char*) &(header[1]);
   }
@@ -965,7 +959,7 @@ pack_message (struct GNUNET_MESSENGER_Message *message,
   {
     env = NULL;
 
-    buffer = GNUNET_malloc (padded_length);
+    buffer = GNUNET_malloc(padded_length);
   }
 
   encode_message (message, padded_length, buffer, GNUNET_YES);
@@ -974,20 +968,80 @@ pack_message (struct GNUNET_MESSENGER_Message *message,
   {
     hash_message (message, length, buffer, hash);
 
-    if (ego)
-      sign_message (message, length, buffer, hash, ego);
+    if (sign)
+      sign (cls, message, length, buffer, hash);
   }
 
   if (GNUNET_MESSENGER_PACK_MODE_ENVELOPE != mode)
-    GNUNET_free (buffer);
+    GNUNET_free(buffer);
 
   return env;
 }
 
+int
+is_peer_message (const struct GNUNET_MESSENGER_Message *message)
+{
+  switch (message->header.kind)
+  {
+  case GNUNET_MESSENGER_KIND_INFO:
+  case GNUNET_MESSENGER_KIND_PEER:
+  case GNUNET_MESSENGER_KIND_MISS:
+  case GNUNET_MESSENGER_KIND_MERGE:
+    return GNUNET_YES;
+  default:
+    return GNUNET_NO;
+  }
+}
+
+int
+is_service_message (const struct GNUNET_MESSENGER_Message *message)
+{
+  if (GNUNET_YES == is_peer_message(message))
+    return GNUNET_YES;
+
+  switch (message->header.kind)
+  {
+  case GNUNET_MESSENGER_KIND_INFO:
+    return GNUNET_YES; // Reserved for connection handling only!
+  case GNUNET_MESSENGER_KIND_JOIN:
+    return GNUNET_YES; // Reserved for member handling only!
+  case GNUNET_MESSENGER_KIND_LEAVE:
+    return GNUNET_YES; // Reserved for member handling only!
+  case GNUNET_MESSENGER_KIND_NAME:
+    return GNUNET_YES; // Reserved for member name handling only!
+  case GNUNET_MESSENGER_KIND_KEY:
+    return GNUNET_YES; // Reserved for member key handling only!
+  case GNUNET_MESSENGER_KIND_PEER:
+    return GNUNET_YES; // Reserved for connection handling only!
+  case GNUNET_MESSENGER_KIND_ID:
+    return GNUNET_YES; // Reserved for member id handling only!
+  case GNUNET_MESSENGER_KIND_MISS:
+    return GNUNET_YES; // Reserved for connection handling only!
+  case GNUNET_MESSENGER_KIND_MERGE:
+    return GNUNET_YES; // Reserved for peers only!
+  case GNUNET_MESSENGER_KIND_REQUEST:
+    return GNUNET_YES; // Requests should not apply individually! (inefficieny)
+  case GNUNET_MESSENGER_KIND_INVITE:
+    return GNUNET_NO;
+  case GNUNET_MESSENGER_KIND_TEXT:
+    return GNUNET_NO;
+  case GNUNET_MESSENGER_KIND_FILE:
+    return GNUNET_NO;
+  case GNUNET_MESSENGER_KIND_PRIVATE:
+    return GNUNET_YES; // Prevent duplicate encryption breaking all access!
+  case GNUNET_MESSENGER_KIND_DELETE:
+    return GNUNET_YES; // Deletion should not apply individually! (inefficieny)
+  default:
+    return GNUNET_SYSERR;
+  }
+}
 
 int
 filter_message_sending (const struct GNUNET_MESSENGER_Message *message)
 {
+  if (GNUNET_YES == is_peer_message(message))
+    return GNUNET_SYSERR; // Requires signature of peer rather than ego!
+
   switch (message->header.kind)
   {
   case GNUNET_MESSENGER_KIND_INFO:
@@ -999,15 +1053,15 @@ filter_message_sending (const struct 
GNUNET_MESSENGER_Message *message)
   case GNUNET_MESSENGER_KIND_NAME:
     return GNUNET_YES;
   case GNUNET_MESSENGER_KIND_KEY:
-    return GNUNET_NO; // Use #GNUNET_MESSENGER_update(...) instead!
+    return GNUNET_NO; // Use #GNUNET_MESSENGER_set_key_by_ego(...) instead!
   case GNUNET_MESSENGER_KIND_PEER:
-    return GNUNET_NO; // Use #GNUNET_MESSENGER_open_room(...) instead!
+    return GNUNET_SYSERR; // Use #GNUNET_MESSENGER_open_room(...) instead!
   case GNUNET_MESSENGER_KIND_ID:
-    return GNUNET_SYSERR; // Reserved for member id handling only!
+    return GNUNET_NO; // Reserved for member id handling only!
   case GNUNET_MESSENGER_KIND_MISS:
     return GNUNET_SYSERR; // Reserved for connection handling only!
   case GNUNET_MESSENGER_KIND_MERGE:
-    return GNUNET_YES;
+    return GNUNET_SYSERR; // Reserved for peers only!
   case GNUNET_MESSENGER_KIND_REQUEST:
     return GNUNET_YES;
   case GNUNET_MESSENGER_KIND_INVITE:
diff --git a/src/messenger/messenger_api_message.h 
b/src/messenger/messenger_api_message.h
index 688c72994..3544993f9 100644
--- a/src/messenger/messenger_api_message.h
+++ b/src/messenger/messenger_api_message.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -33,8 +33,6 @@
 
 #include "gnunet_messenger_service.h"
 
-#include "messenger_api_ego.h"
-
 #define GNUNET_MESSENGER_MAX_MESSAGE_SIZE (GNUNET_MAX_MESSAGE_SIZE - 
GNUNET_MIN_MESSAGE_SIZE)
 
 #define GNUNET_MESSENGER_PADDING_MIN (sizeof(uint16_t) + sizeof(char))
@@ -166,14 +164,31 @@ hash_message (const struct GNUNET_MESSENGER_Message 
*message,
  * @param[in] length Length of buffer
  * @param[out] buffer Buffer
  * @param[in] hash Hash of message
- * @param[in] ego EGO
+ * @param[in] key Private key of EGO
  */
 void
 sign_message (struct GNUNET_MESSENGER_Message *message,
               uint16_t length,
               char *buffer,
               const struct GNUNET_HashCode *hash,
-              const struct GNUNET_MESSENGER_Ego *ego);
+              const struct GNUNET_IDENTITY_PrivateKey *key);
+
+/**
+ * Signs the <i>hash</i> of a <i>message</i> with the peer identity of a given 
<i>config</i>
+ * and writes the signature into the <i>buffer</i> as well.
+ *
+ * @param[in,out] message Message
+ * @param[in] length Length of buffer
+ * @param[out] buffer Buffer
+ * @param[in] hash Hash of message
+ * @param[in] cfg Peer configuration
+ */
+void
+sign_message_by_peer (struct GNUNET_MESSENGER_Message *message,
+                      uint16_t length,
+                      char *buffer,
+                      const struct GNUNET_HashCode *hash,
+                      const struct GNUNET_CONFIGURATION_Handle* cfg);
 
 /**
  * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a 
specific
@@ -190,6 +205,21 @@ verify_message (const struct GNUNET_MESSENGER_Message 
*message,
                 const struct GNUNET_HashCode *hash,
                 const struct GNUNET_IDENTITY_PublicKey *key);
 
+/**
+ * Verifies the signature of a given <i>message</i> and its <i>hash</i> with a 
specific
+ * peer's <i>identity</i>. The function returns #GNUNET_OK if the signature 
was valid,
+ * otherwise #GNUNET_SYSERR.
+ *
+ * @param[in] message Message
+ * @param[in] hash Hash of message
+ * @param[in] identity Peer identity
+ * @return #GNUNET_OK on success, otherwise #GNUNET_SYSERR
+ */
+int
+verify_message_by_peer (const struct GNUNET_MESSENGER_Message *message,
+                        const struct GNUNET_HashCode *hash,
+                        const struct GNUNET_PeerIdentity *identity);
+
 /**
  * Encrypts a <i>message</i> using a given public <i>key</i> and replaces its 
body
  * and kind with the now private encrypted <i>message</i>. The function returns
@@ -216,33 +246,69 @@ int
 decrypt_message (struct GNUNET_MESSENGER_Message *message,
                  const struct GNUNET_IDENTITY_PrivateKey *key);
 
+typedef void (*GNUNET_MESSENGER_SignFunction)(
+  const void *cls,
+  struct GNUNET_MESSENGER_Message *message,
+  uint16_t length,
+  char *buffer,
+  const struct GNUNET_HashCode *hash
+);
+
 #define GNUNET_MESSENGER_PACK_MODE_ENVELOPE 0x1
 #define GNUNET_MESSENGER_PACK_MODE_UNKNOWN 0x0
 
 /**
  * Encodes the <i>message</i> to pack it into a newly allocated envelope if 
<i>mode</i>
  * is equal to #GNUNET_MESSENGER_PACK_MODE_ENVELOPE. Independent of the mode 
the message
- * will be hashed if <i>hash</i> is not NULL and it will be signed if the 
<i>ego</i> is
- * not NULL.
+ * will be hashed if <i>hash</i> is not NULL and it will be signed if the 
<i>sign</i>
+ * function is not NULL.
  *
  * @param[out] message Message
  * @param[out] hash Hash of message
- * @param[in] ego EGO to sign
+ * @param[in] sign Function to sign
  * @param[in] mode Mode of packing
+ * @param[in,out] cls Closure for signing
  * @return Envelope or NULL
  */
 struct GNUNET_MQ_Envelope*
 pack_message (struct GNUNET_MESSENGER_Message *message,
               struct GNUNET_HashCode *hash,
-              const struct GNUNET_MESSENGER_Ego *ego,
-              int mode);
+              const GNUNET_MESSENGER_SignFunction sign,
+              int mode,
+              const void *cls);
+
+/**
+ * Returns whether a specific kind of message can be sent by the service 
without usage of a
+ * clients EGO. The function returns #GNUNET_YES if the kind of message can be 
signed
+ * via a peer's identity, otherwise #GNUNET_NO.
+ *
+ * @param[in] message Message
+ * @return #GNUNET_YES if sending is allowed, #GNUNET_NO otherwise
+ */
+int
+is_peer_message (const struct GNUNET_MESSENGER_Message *message);
+
+/**
+ * Returns whether a specific kind of message contains service critical 
information. That kind
+ * of information should not be encrypted via private messages for example to 
guarantee the
+ * service to work properly. The function returns #GNUNET_YES if the kind of 
message needs to
+ * be transferred accessible to all peers and their running service. It 
returns #GNUNET_NO
+ * if the message can be encrypted to specific subgroups of members without 
issues. If the kind
+ * of message is unknown it returns #GNUNET_SYSERR.
+ *
+ * @param[in] message Message
+ * @return #GNUNET_YES if encrypting is disallowed, #GNUNET_NO or 
#GNUNET_SYSERR otherwise
+ */
+int
+is_service_message (const struct GNUNET_MESSENGER_Message *message);
 
 /**
- * Returns if a specific kind of message should be sent by a client. The 
function returns
+ * Returns whether a specific kind of message should be sent by a client. The 
function returns
  * #GNUNET_YES or #GNUNET_NO for recommendations and #GNUNET_SYSERR for 
specific kinds
  * of messages which should not be sent manually at all.
  *
  * @param[in] message Message
+ * @return #GNUNET_YES if sending is allowed, #GNUNET_NO or #GNUNET_SYSERR 
otherwise
  */
 int
 filter_message_sending (const struct GNUNET_MESSENGER_Message *message);
diff --git a/src/messenger/gnunet-service-messenger_message_kind.c 
b/src/messenger/messenger_api_message_kind.c
similarity index 68%
copy from src/messenger/gnunet-service-messenger_message_kind.c
copy to src/messenger/messenger_api_message_kind.c
index 828e84d4f..97eaa061b 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.c
+++ b/src/messenger/messenger_api_message_kind.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -23,33 +23,15 @@
  * @brief GNUnet MESSENGER service
  */
 
-#include "platform.h"
-#include "gnunet-service-messenger_message_kind.h"
+#include "messenger_api_message_kind.h"
 
+#include "platform.h"
 #include "messenger_api_util.h"
 
 struct GNUNET_MESSENGER_Message*
-create_message_info (const struct GNUNET_MESSENGER_Ego *ego)
-{
-  if (!ego)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_INFO);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.info.host_key), &(ego->pub), sizeof(ego->pub));
-
-  message->body.info.messenger_version = GNUNET_MESSENGER_VERSION;
-
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
+create_message_join (const struct GNUNET_IDENTITY_PrivateKey *key)
 {
-  if (!ego)
+  if (!key)
     return NULL;
 
   struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_JOIN);
@@ -57,8 +39,7 @@ create_message_join (const struct GNUNET_MESSENGER_Ego *ego)
   if (!message)
     return NULL;
 
-  GNUNET_memcpy(&(message->body.join.key), &(ego->pub), sizeof(ego->pub));
-
+  GNUNET_IDENTITY_key_get_public (key, &(message->body.join.key));
   return message;
 }
 
@@ -98,26 +79,6 @@ create_message_key (const struct GNUNET_IDENTITY_PrivateKey 
*key)
   return message;
 }
 
-struct GNUNET_MESSENGER_Message*
-create_message_peer (const struct GNUNET_MESSENGER_Service *service)
-{
-  if (!service)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_PEER);
-
-  if (!message)
-    return NULL;
-
-  if (GNUNET_OK == get_service_peer_identity (service, 
&(message->body.peer.peer)))
-    return message;
-  else
-  {
-    destroy_message (message);
-    return NULL;
-  }
-}
-
 struct GNUNET_MESSENGER_Message*
 create_message_id (const struct GNUNET_ShortHashCode *unique_id)
 {
@@ -134,40 +95,6 @@ create_message_id (const struct GNUNET_ShortHashCode 
*unique_id)
   return message;
 }
 
-struct GNUNET_MESSENGER_Message*
-create_message_miss (const struct GNUNET_PeerIdentity *peer)
-{
-  if (!peer)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_MISS);
-
-  if (!message)
-  {
-    return NULL;
-  }
-
-  GNUNET_memcpy(&(message->body.miss.peer), peer, sizeof(struct 
GNUNET_PeerIdentity));
-
-  return message;
-}
-
-struct GNUNET_MESSENGER_Message*
-create_message_merge (const struct GNUNET_HashCode *previous)
-{
-  if (!previous)
-    return NULL;
-
-  struct GNUNET_MESSENGER_Message *message = create_message 
(GNUNET_MESSENGER_KIND_MERGE);
-
-  if (!message)
-    return NULL;
-
-  GNUNET_memcpy(&(message->body.merge.previous), previous, sizeof(struct 
GNUNET_HashCode));
-
-  return message;
-}
-
 struct GNUNET_MESSENGER_Message*
 create_message_request (const struct GNUNET_HashCode *hash)
 {
diff --git a/src/messenger/gnunet-service-messenger_message_kind.h 
b/src/messenger/messenger_api_message_kind.h
similarity index 71%
copy from src/messenger/gnunet-service-messenger_message_kind.h
copy to src/messenger/messenger_api_message_kind.h
index 102a70e33..9369e2a9a 100644
--- a/src/messenger/gnunet-service-messenger_message_kind.h
+++ b/src/messenger/messenger_api_message_kind.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -33,28 +33,16 @@
 
 #include "messenger_api_message.h"
 #include "gnunet-service-messenger_service.h"
-#include "messenger_api_ego.h"
 
 /**
- * Creates and allocates a new info message containing the hosts EGO public 
key and a newly generated unique member id.
+ * Creates and allocates a new join message containing the clients EGO public 
<i>key</i>.
  * (all values are stored as copy)
  *
- * @param[in] ego EGO of the host
- * @param[in] members Map of all assigned member ids
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_info (const struct GNUNET_MESSENGER_Ego *ego);
-
-/**
- * Creates and allocates a new join message containing the clients EGO public 
key.
- * (all values are stored as copy)
- *
- * @param[in] ego EGO of the client
+ * @param[in] key Private key of EGO
  * @return New message
  */
 struct GNUNET_MESSENGER_Message*
-create_message_join (const struct GNUNET_MESSENGER_Ego *ego);
+create_message_join (const struct GNUNET_IDENTITY_PrivateKey *key);
 
 /**
  * Creates and allocates a new leave message.
@@ -84,16 +72,6 @@ create_message_name (const char *name);
 struct GNUNET_MESSENGER_Message*
 create_message_key (const struct GNUNET_IDENTITY_PrivateKey *key);
 
-/**
- * Creates and allocates a new peer message containing a services peer 
identity.
- * (all values are stored as copy)
- *
- * @param[in] service Service
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_peer (const struct GNUNET_MESSENGER_Service *service);
-
 /**
  * Creates and allocates a new id message containing the unique member id to 
change to.
  * (all values are stored as copy)
@@ -104,27 +82,6 @@ create_message_peer (const struct GNUNET_MESSENGER_Service 
*service);
 struct GNUNET_MESSENGER_Message*
 create_message_id (const struct GNUNET_ShortHashCode *unique_id);
 
-/**
- * Creates and allocates a new miss message containing the missing <i>peer</i> 
identity.
- * (all values are stored as copy)
- *
- * @param[in] peer Missing peer identity
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_miss (const struct GNUNET_PeerIdentity *peer);
-
-/**
- * Creates and allocates a new merge message containing the hash of a second 
<i>previous</i> message
- * besides the regular previous message mentioned in a messages header.
- * (all values are stored as copy)
- *
- * @param[in] previous Hash of message
- * @return New message
- */
-struct GNUNET_MESSENGER_Message*
-create_message_merge (const struct GNUNET_HashCode *previous);
-
 /**
  * Creates and allocates a new request message containing the <i>hash</i> of a 
missing message.
  * (all values are stored as copy)
diff --git a/src/messenger/messenger_api_peer_store.c 
b/src/messenger/messenger_api_peer_store.c
new file mode 100644
index 000000000..f0b9eb0bb
--- /dev/null
+++ b/src/messenger/messenger_api_peer_store.c
@@ -0,0 +1,180 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2023 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Tobias Frisch
+ * @file src/messenger/messenger_api_peer_store.c
+ * @brief messenger api: client implementation of GNUnet MESSENGER service
+ */
+
+#include "platform.h"
+#include "messenger_api_peer_store.h"
+
+#include "messenger_api_message.h"
+#include "messenger_api_util.h"
+
+void
+init_peer_store (struct GNUNET_MESSENGER_PeerStore *store)
+{
+  GNUNET_assert (store);
+
+  store->peers = GNUNET_CONTAINER_multishortmap_create (4, GNUNET_NO);
+}
+
+static enum GNUNET_GenericReturnValue
+iterate_destroy_peers (void *cls, const struct GNUNET_ShortHashCode *id, void 
*value)
+{
+  struct GNUNET_PeerIdentity* peer = value;
+  GNUNET_free (peer);
+  return GNUNET_YES;
+}
+
+void
+clear_peer_store (struct GNUNET_MESSENGER_PeerStore *store)
+{
+  GNUNET_assert ((store) && (store->peers));
+
+  GNUNET_CONTAINER_multishortmap_iterate (store->peers, iterate_destroy_peers, 
NULL);
+  GNUNET_CONTAINER_multishortmap_destroy (store->peers);
+
+  store->peers = NULL;
+}
+
+struct GNUNET_MESSENGER_ClosureVerifyPeer
+{
+  const struct GNUNET_MESSENGER_Message *message;
+  const struct GNUNET_HashCode *hash;
+  struct GNUNET_PeerIdentity *sender;
+};
+
+static enum GNUNET_GenericReturnValue
+verify_store_peer(void *cls, const struct GNUNET_ShortHashCode *id, void 
*value)
+{
+  struct GNUNET_MESSENGER_ClosureVerifyPeer *verify = cls;
+  struct GNUNET_PeerIdentity* peer = value;
+
+  if ((peer) && (GNUNET_OK == verify_message_by_peer (verify->message, 
verify->hash, peer)))
+  {
+    verify->sender = peer;
+    return GNUNET_NO;
+  }
+
+  return GNUNET_YES;
+}
+
+struct GNUNET_PeerIdentity*
+get_store_peer_of (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_MESSENGER_Message *message,
+                   const struct GNUNET_HashCode *hash)
+{
+  GNUNET_assert ((store) && (store->peers) && (message) && (hash));
+
+  if (GNUNET_YES != is_peer_message (message))
+    return NULL;
+
+  if ((GNUNET_MESSENGER_KIND_PEER == message->header.kind) &&
+      (GNUNET_OK == verify_message_by_peer (message, hash, 
&(message->body.peer.peer))))
+  {
+    struct GNUNET_ShortHashCode peer_id;
+    convert_peer_identity_to_id (&(message->body.peer.peer), &peer_id);
+
+    if (0 == GNUNET_memcmp (&peer_id, &(message->header.sender_id)))
+      update_store_peer (store, &(message->body.peer.peer));
+    else
+      GNUNET_log (GNUNET_ERROR_TYPE_WARNING, "Sender id does not match peer 
identity\n");
+  }
+
+  struct GNUNET_MESSENGER_ClosureVerifyPeer verify;
+  verify.message = message;
+  verify.hash = hash;
+  verify.sender = NULL;
+
+  GNUNET_CONTAINER_multishortmap_get_multiple (store->peers, 
&(message->header.sender_id),
+                                               verify_store_peer, &verify);
+
+  return verify.sender;
+}
+
+struct GNUNET_MESSENGER_ClosureFindPeer
+{
+  const struct GNUNET_PeerIdentity *requested;
+  struct GNUNET_PeerIdentity *match;
+};
+
+static enum GNUNET_GenericReturnValue
+find_store_peer(void *cls, const struct GNUNET_ShortHashCode *id, void *value)
+{
+  struct GNUNET_MESSENGER_ClosureFindPeer *find = cls;
+  struct GNUNET_PeerIdentity* peer = value;
+
+  if ((peer) && (0 == GNUNET_memcmp (find->requested, peer)))
+  {
+    find->match = peer;
+    return GNUNET_NO;
+  }
+
+  return GNUNET_YES;
+}
+
+void
+update_store_peer (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_PeerIdentity* peer)
+{
+  GNUNET_assert ((store) && (store->peers) && (peer));
+
+  struct GNUNET_ShortHashCode peer_id;
+  convert_peer_identity_to_id (peer, &peer_id);
+
+  struct GNUNET_MESSENGER_ClosureFindPeer find;
+  find.requested = peer;
+  find.match = NULL;
+
+  GNUNET_CONTAINER_multishortmap_get_multiple (store->peers, &peer_id,
+                                               find_store_peer, &find);
+
+  if (find.match)
+    return;
+
+  struct GNUNET_PeerIdentity* copy = GNUNET_memdup (peer, sizeof (struct 
GNUNET_PeerIdentity));
+  GNUNET_CONTAINER_multishortmap_put (store->peers, &peer_id, copy,
+                                      
GNUNET_CONTAINER_MULTIHASHMAPOPTION_MULTIPLE);
+}
+
+void
+remove_store_peer (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_PeerIdentity *peer)
+{
+  GNUNET_assert ((store) && (store->peers) && (peer));
+
+  struct GNUNET_ShortHashCode peer_id;
+  convert_peer_identity_to_id (peer, &peer_id);
+
+  struct GNUNET_MESSENGER_ClosureFindPeer find;
+  find.requested = peer;
+  find.match = NULL;
+
+  GNUNET_CONTAINER_multishortmap_get_multiple (store->peers, &peer_id,
+                                               find_store_peer, &find);
+
+  if (!find.match)
+    return;
+
+  if (GNUNET_YES == GNUNET_CONTAINER_multishortmap_remove (store->peers, 
&peer_id, find.match))
+    GNUNET_free(find.match);
+}
diff --git a/src/messenger/messenger_api_peer_store.h 
b/src/messenger/messenger_api_peer_store.h
new file mode 100644
index 000000000..526a1ca57
--- /dev/null
+++ b/src/messenger/messenger_api_peer_store.h
@@ -0,0 +1,93 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2023 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Tobias Frisch
+ * @file src/messenger/messenger_api_peer_store.h
+ * @brief messenger api: client implementation of GNUnet MESSENGER service
+ */
+
+#ifndef GNUNET_MESSENGER_API_PEER_STORE_H
+#define GNUNET_MESSENGER_API_PEER_STORE_H
+
+#include "platform.h"
+#include "gnunet_util_lib.h"
+
+struct GNUNET_MESSENGER_Message;
+
+struct GNUNET_MESSENGER_PeerStore
+{
+  struct GNUNET_CONTAINER_MultiShortmap *peers;
+};
+
+/**
+ * Initializes a peer store as fully empty.
+ *
+ * @param[out] store Peer store
+ */
+void
+init_peer_store (struct GNUNET_MESSENGER_PeerStore *store);
+
+/**
+ * Clears a peer store, wipes its content and deallocates its memory.
+ *
+ * @param[in,out] store Peer store
+ */
+void
+clear_peer_store (struct GNUNET_MESSENGER_PeerStore *store);
+
+/**
+ * Returns the peer identity inside the <i>store</i> which verifies the
+ * signature of a given <i>message</i> as valid. The specific peer identity
+ * has to be added to the <i>store</i> previously. Otherwise the function
+ * returns NULL.
+ *
+ * @param[in,out] store Peer store
+ * @param[in] message Message
+ * @param[in] hash Hash of message
+ * @return Peer identity or NULL
+ */
+struct GNUNET_PeerIdentity*
+get_store_peer_of (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_MESSENGER_Message *message,
+                   const struct GNUNET_HashCode *hash);
+
+/**
+ * Adds a <i>peer</i> identity to the <i>store</i> if necessary. It ensures
+ * that the given <i>peer</i> can be verified as sender of a message
+ * afterwards by the <i>store</i>.
+ *
+ * @param[in,out] store Peer store
+ * @param[in] peer Peer identity
+ */
+void
+update_store_peer (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_PeerIdentity* peer);
+
+/**
+ * Removes a <i>peer</i> identity from the <i>store</i> entirely.
+ *
+ * @param[in,out] store Peer store
+ * @param[in] peer Peer identity
+ */
+void
+remove_store_peer (struct GNUNET_MESSENGER_PeerStore *store,
+                   const struct GNUNET_PeerIdentity *peer);
+
+#endif //GNUNET_MESSENGER_API_PEER_STORE_H
diff --git a/src/messenger/messenger_api_queue_messages.c 
b/src/messenger/messenger_api_queue_messages.c
new file mode 100644
index 000000000..bd99698cd
--- /dev/null
+++ b/src/messenger/messenger_api_queue_messages.c
@@ -0,0 +1,104 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2023 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Tobias Frisch
+ * @file src/messenger/messenger_api_queue_messages.c
+ * @brief messenger api: client implementation of GNUnet MESSENGER service
+ */
+
+#include "messenger_api_queue_messages.h"
+
+void
+init_queue_messages (struct GNUNET_MESSENGER_QueueMessages *messages)
+{
+  GNUNET_assert (messages);
+
+  messages->head = NULL;
+  messages->tail = NULL;
+}
+
+void
+clear_queue_messages (struct GNUNET_MESSENGER_QueueMessages *messages)
+{
+  GNUNET_assert (messages);
+
+  while (messages->head)
+  {
+    struct GNUNET_MESSENGER_QueueMessage *element = messages->head;
+
+    GNUNET_CONTAINER_DLL_remove (messages->head, messages->tail, element);
+
+    if (element->message)
+      destroy_message (element->message);
+
+    GNUNET_free (element);
+  }
+
+  messages->head = NULL;
+  messages->tail = NULL;
+}
+
+void
+enqueue_to_messages (struct GNUNET_MESSENGER_QueueMessages *messages,
+                     const struct GNUNET_IDENTITY_PrivateKey *sender,
+                     const struct GNUNET_MESSENGER_Message *message)
+{
+  GNUNET_assert ((messages) && (message));
+
+  struct GNUNET_MESSENGER_QueueMessage *element = GNUNET_new (struct 
GNUNET_MESSENGER_QueueMessage);
+
+  if (!element)
+    return;
+
+  element->message = copy_message (message);
+
+  if (sender)
+    GNUNET_memcpy (&(element->sender), sender, sizeof (element->sender));
+
+  if (!element->message)
+  {
+    GNUNET_free (element);
+    return;
+  }
+
+  GNUNET_CONTAINER_DLL_insert_tail (messages->head, messages->tail, element);
+}
+
+struct GNUNET_MESSENGER_Message*
+dequeue_from_messages (struct GNUNET_MESSENGER_QueueMessages *messages,
+                       struct GNUNET_IDENTITY_PrivateKey *sender)
+{
+  GNUNET_assert (messages);
+
+  struct GNUNET_MESSENGER_QueueMessage *element = messages->head;
+
+  if (!element)
+    return NULL;
+
+  struct GNUNET_MESSENGER_Message *message = element->message;
+
+  GNUNET_CONTAINER_DLL_remove (messages->head, messages->tail, element);
+
+  if (sender)
+    GNUNET_memcpy (sender, &(element->sender), sizeof (*sender));
+
+  GNUNET_free (element);
+  return message;
+}
diff --git a/src/messenger/messenger_api_queue_messages.h 
b/src/messenger/messenger_api_queue_messages.h
new file mode 100644
index 000000000..8fb2d8098
--- /dev/null
+++ b/src/messenger/messenger_api_queue_messages.h
@@ -0,0 +1,89 @@
+/*
+   This file is part of GNUnet.
+   Copyright (C) 2023 GNUnet e.V.
+
+   GNUnet is free software: you can redistribute it and/or modify it
+   under the terms of the GNU Affero General Public License as published
+   by the Free Software Foundation, either version 3 of the License,
+   or (at your option) any later version.
+
+   GNUnet is distributed in the hope that it will be useful, but
+   WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Affero General Public License for more details.
+
+   You should have received a copy of the GNU Affero General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+   SPDX-License-Identifier: AGPL3.0-or-later
+ */
+/**
+ * @author Tobias Frisch
+ * @file src/messenger/messenger_api_queue_messages.h
+ * @brief messenger api: client implementation of GNUnet MESSENGER service
+ */
+
+#ifndef GNUNET_MESSENGER_API_QUEUE_MESSAGES_H
+#define GNUNET_MESSENGER_API_QUEUE_MESSAGES_H
+
+#include "platform.h"
+#include "gnunet_identity_service.h"
+#include "gnunet_util_lib.h"
+
+#include "messenger_api_message.h"
+
+struct GNUNET_MESSENGER_QueueMessage
+{
+  struct GNUNET_MESSENGER_QueueMessage *prev;
+  struct GNUNET_MESSENGER_QueueMessage *next;
+
+  struct GNUNET_IDENTITY_PrivateKey sender;
+  struct GNUNET_MESSENGER_Message *message;
+};
+
+struct GNUNET_MESSENGER_QueueMessages
+{
+  struct GNUNET_MESSENGER_QueueMessage *head;
+  struct GNUNET_MESSENGER_QueueMessage *tail;
+};
+
+/**
+ * Initializes queue of messages as empty queue.
+ *
+ * @param[out] messages Queue of messages
+ */
+void
+init_queue_messages (struct GNUNET_MESSENGER_QueueMessages *messages);
+
+/**
+ * Clears the queue of messages.
+ *
+ * @param[in,out] messages Queue of messages
+ */
+void
+clear_queue_messages (struct GNUNET_MESSENGER_QueueMessages *messages);
+
+/**
+ * Adds a specific <i>message</i> to the end of the queue.
+ *
+ * @param[in,out] messages Queue of messages
+ * @param[in] sender Private sender key
+ * @param[in] message Message
+ */
+void
+enqueue_to_messages (struct GNUNET_MESSENGER_QueueMessages *messages,
+                     const struct GNUNET_IDENTITY_PrivateKey *sender,
+                     const struct GNUNET_MESSENGER_Message *message);
+
+/**
+ * Remove the message from the front of the queue and returns it.
+ *
+ * @param[in,out] messages Queue of messages
+ * @param[out] sender Private sender key
+ * @return Message from front or NULL
+ */
+struct GNUNET_MESSENGER_Message*
+dequeue_from_messages (struct GNUNET_MESSENGER_QueueMessages *messages,
+                       struct GNUNET_IDENTITY_PrivateKey *sender);
+
+#endif //GNUNET_MESSENGER_API_QUEUE_MESSAGES_H
diff --git a/src/messenger/messenger_api_room.c 
b/src/messenger/messenger_api_room.c
index c3e8bc957..fb4e11fd4 100644
--- a/src/messenger/messenger_api_room.c
+++ b/src/messenger/messenger_api_room.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -39,14 +39,19 @@ create_room (struct GNUNET_MESSENGER_Handle *handle,
   room->handle = handle;
   GNUNET_memcpy(&(room->key), key, sizeof(*key));
 
+  memset(&(room->last_message), 0, sizeof(room->last_message));
+
   room->opened = GNUNET_NO;
-  room->contact_id = NULL;
+  room->use_handle_name = GNUNET_YES;
+  room->sender_id = NULL;
 
   init_list_tunnels (&(room->entries));
 
   room->messages = GNUNET_CONTAINER_multihashmap_create (8, GNUNET_NO);
   room->members = GNUNET_CONTAINER_multishortmap_create (8, GNUNET_NO);
 
+  init_queue_messages (&(room->queue));
+
   return room;
 }
 
@@ -68,6 +73,7 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
 {
   GNUNET_assert(room);
 
+  clear_queue_messages(&(room->queue));
   clear_list_tunnels (&(room->entries));
 
   if (room->messages)
@@ -80,12 +86,57 @@ destroy_room (struct GNUNET_MESSENGER_Room *room)
   if (room->members)
     GNUNET_CONTAINER_multishortmap_destroy (room->members);
 
-  if (room->contact_id)
-    GNUNET_free(room->contact_id);
+  if (room->sender_id)
+    GNUNET_free(room->sender_id);
 
   GNUNET_free(room);
 }
 
+enum GNUNET_GenericReturnValue
+is_room_available (const struct GNUNET_MESSENGER_Room *room)
+{
+  GNUNET_assert (room);
+
+  if (!get_room_sender_id(room))
+    return GNUNET_NO;
+
+  if ((GNUNET_YES == room->opened) || (room->entries.head))
+    return GNUNET_YES;
+  else
+    return GNUNET_NO;
+}
+
+const struct GNUNET_ShortHashCode*
+get_room_sender_id (const struct GNUNET_MESSENGER_Room *room)
+{
+  GNUNET_assert (room);
+
+  return room->sender_id;
+}
+
+void
+set_room_sender_id (struct GNUNET_MESSENGER_Room *room,
+                    const struct GNUNET_ShortHashCode *id)
+{
+  GNUNET_assert (room);
+
+  GNUNET_log (GNUNET_ERROR_TYPE_DEBUG, "Set member id for room: %s\n", 
GNUNET_h2s (&(room->key)));
+
+  if (!id)
+  {
+    if (room->sender_id)
+      GNUNET_free (room->sender_id);
+
+    room->sender_id = NULL;
+    return;
+  }
+
+  if (!room->sender_id)
+    room->sender_id = GNUNET_new (struct GNUNET_ShortHashCode);
+
+  GNUNET_memcpy (room->sender_id, id, sizeof(struct GNUNET_ShortHashCode));
+}
+
 const struct GNUNET_MESSENGER_Message*
 get_room_message (const struct GNUNET_MESSENGER_Room *room,
                   const struct GNUNET_HashCode *hash)
@@ -146,9 +197,6 @@ handle_leave_message (struct GNUNET_MESSENGER_Room *room,
       (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, 
&(message->header.sender_id), sender)))
     return;
 
-  struct GNUNET_HashCode context;
-  get_context_from_member(&(room->key), &(message->header.sender_id), 
&context);
-
   if (GNUNET_YES == decrease_contact_rc(sender))
     GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "A contact does not share any room 
with you anymore!\n");
 }
@@ -157,8 +205,19 @@ static void
 handle_name_message (struct GNUNET_MESSENGER_Room *room,
                      struct GNUNET_MESSENGER_Contact *sender,
                      const struct GNUNET_MESSENGER_Message *message,
-                     const struct GNUNET_HashCode *hash)
+                     const struct GNUNET_HashCode *hash,
+                     enum GNUNET_MESSENGER_MessageFlags flags)
 {
+  if (GNUNET_MESSENGER_FLAG_SENT & flags)
+  {
+    GNUNET_log(GNUNET_ERROR_TYPE_DEBUG, "Set rule for using handle name in 
room: %s\n", GNUNET_h2s (&(room->key)));
+
+    const char* handle_name = get_handle_name (room->handle);
+
+    if ((handle_name) && (0 == strcmp (handle_name, message->body.name.name)))
+      room->use_handle_name = GNUNET_YES;
+  }
+
   if (!sender)
     return;
 
@@ -186,8 +245,12 @@ static void
 handle_id_message (struct GNUNET_MESSENGER_Room *room,
                    struct GNUNET_MESSENGER_Contact *sender,
                    const struct GNUNET_MESSENGER_Message *message,
-                   const struct GNUNET_HashCode *hash)
+                   const struct GNUNET_HashCode *hash,
+                   enum GNUNET_MESSENGER_MessageFlags flags)
 {
+  if (GNUNET_MESSENGER_FLAG_SENT & flags)
+    set_room_sender_id (room, &(message->body.id.id));
+
   if ((!sender) ||
       (GNUNET_YES != GNUNET_CONTAINER_multishortmap_remove(room->members, 
&(message->header.sender_id), sender)) ||
       (GNUNET_OK != GNUNET_CONTAINER_multishortmap_put(room->members, 
&(message->body.id.id), sender,
@@ -207,9 +270,10 @@ static void
 handle_miss_message (struct GNUNET_MESSENGER_Room *room,
                      struct GNUNET_MESSENGER_Contact *sender,
                      const struct GNUNET_MESSENGER_Message *message,
-                     const struct GNUNET_HashCode *hash)
+                     const struct GNUNET_HashCode *hash,
+                     enum GNUNET_MESSENGER_MessageFlags flags)
 {
-  if ((room->contact_id) && (0 == GNUNET_memcmp(&(message->header.sender_id), 
room->contact_id)))
+  if (GNUNET_MESSENGER_FLAG_SENT & flags)
   {
     struct GNUNET_MESSENGER_ListTunnel *match = find_list_tunnels 
(&(room->entries), &(message->body.miss.peer), NULL);
 
@@ -240,7 +304,8 @@ struct GNUNET_MESSENGER_Contact*
 handle_room_message (struct GNUNET_MESSENGER_Room *room,
                      struct GNUNET_MESSENGER_Contact *sender,
                      const struct GNUNET_MESSENGER_Message *message,
-                     const struct GNUNET_HashCode *hash)
+                     const struct GNUNET_HashCode *hash,
+                     enum GNUNET_MESSENGER_MessageFlags flags)
 {
   if (GNUNET_NO != GNUNET_CONTAINER_multihashmap_contains (room->messages, 
hash))
     return sender;
@@ -254,16 +319,16 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room,
     handle_leave_message (room, sender, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_NAME:
-    handle_name_message (room, sender, message, hash);
+    handle_name_message (room, sender, message, hash, flags);
     break;
   case GNUNET_MESSENGER_KIND_KEY:
     handle_key_message (room, sender, message, hash);
     break;
   case GNUNET_MESSENGER_KIND_ID:
-    handle_id_message (room, sender, message, hash);
+    handle_id_message (room, sender, message, hash, flags);
     break;
   case GNUNET_MESSENGER_KIND_MISS:
-    handle_miss_message (room, sender, message, hash);
+    handle_miss_message (room, sender, message, hash, flags);
     break;
   case GNUNET_MESSENGER_KIND_DELETE:
     handle_delete_message (room, sender, message, hash);
@@ -287,6 +352,7 @@ handle_room_message (struct GNUNET_MESSENGER_Room *room,
     GNUNET_free(entry);
   }
 
+  GNUNET_memcpy (&(room->last_message), hash, sizeof(room->last_message));
   return sender;
 }
 
diff --git a/src/messenger/messenger_api_room.h 
b/src/messenger/messenger_api_room.h
index d5ffc5c4b..62e4711d0 100644
--- a/src/messenger/messenger_api_room.h
+++ b/src/messenger/messenger_api_room.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -34,6 +34,7 @@
 #include "messenger_api_list_tunnels.h"
 #include "messenger_api_contact.h"
 #include "messenger_api_message.h"
+#include "messenger_api_queue_messages.h"
 
 struct GNUNET_MESSENGER_RoomMessageEntry {
   struct GNUNET_MESSENGER_Contact* sender;
@@ -45,14 +46,19 @@ struct GNUNET_MESSENGER_Room
   struct GNUNET_MESSENGER_Handle *handle;
   struct GNUNET_HashCode key;
 
-  int opened;
+  struct GNUNET_HashCode last_message;
 
-  struct GNUNET_ShortHashCode *contact_id;
+  enum GNUNET_GenericReturnValue opened;
+  enum GNUNET_GenericReturnValue use_handle_name;
+
+  struct GNUNET_ShortHashCode *sender_id;
 
   struct GNUNET_MESSENGER_ListTunnels entries;
 
   struct GNUNET_CONTAINER_MultiHashMap *messages;
   struct GNUNET_CONTAINER_MultiShortmap *members;
+
+  struct GNUNET_MESSENGER_QueueMessages queue;
 };
 
 /**
@@ -74,6 +80,34 @@ create_room (struct GNUNET_MESSENGER_Handle *handle,
 void
 destroy_room (struct GNUNET_MESSENGER_Room *room);
 
+/**
+ * Checks whether a room is available to send messages.
+ *
+ * @param[in] room Room
+ * @return GNUNET_YES if the room is available, otherwise GNUNET_NO
+ */
+enum GNUNET_GenericReturnValue
+is_room_available (const struct GNUNET_MESSENGER_Room *room);
+
+/**
+ * Returns the member id of the <i>room</i>'s sender.
+ *
+ * @param[in] room Room
+ * @return Member id or NULL
+ */
+const struct GNUNET_ShortHashCode*
+get_room_sender_id (const struct GNUNET_MESSENGER_Room *room);
+
+/**
+ * Sets the member id of the <i>room</i>'s sender to a specific <i>id</i> or 
NULL.
+ *
+ * @param[in,out] room Room
+ * @param[in] id Member id or NULL
+ */
+void
+set_room_sender_id (struct GNUNET_MESSENGER_Room *room,
+                    const struct GNUNET_ShortHashCode *id);
+
 /**
  * Returns a message locally stored from a map for a given <i>hash</i> in a 
<i>room</i>. If no matching
  * message is found, NULL gets returned.
@@ -109,13 +143,15 @@ get_room_sender (const struct GNUNET_MESSENGER_Room *room,
  * @param[in,out] sender Contact of sender
  * @param[in] message Message
  * @param[in] hash Hash of message
+ * @param[in] flags Flags of message
  * @return Contact of sender
  */
 struct GNUNET_MESSENGER_Contact*
 handle_room_message (struct GNUNET_MESSENGER_Room *room,
                      struct GNUNET_MESSENGER_Contact *sender,
                      const struct GNUNET_MESSENGER_Message *message,
-                     const struct GNUNET_HashCode *hash);
+                     const struct GNUNET_HashCode *hash,
+                     enum GNUNET_MESSENGER_MessageFlags flags);
 
 /**
  * Iterates through all members of a given <i>room</i> to forward each of them 
to a selected
diff --git a/src/messenger/messenger_api_util.c 
b/src/messenger/messenger_api_util.c
index f56e2e201..2fc58ed75 100644
--- a/src/messenger/messenger_api_util.c
+++ b/src/messenger/messenger_api_util.c
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -70,6 +70,13 @@ generate_free_member_id (struct GNUNET_ShortHashCode *id,
   return GNUNET_NO;
 }
 
+const struct GNUNET_IDENTITY_PrivateKey*
+get_anonymous_private_key ()
+{
+  const struct GNUNET_IDENTITY_Ego* ego = GNUNET_IDENTITY_ego_get_anonymous();
+  return GNUNET_IDENTITY_ego_get_private_key(ego);
+}
+
 const struct GNUNET_IDENTITY_PublicKey*
 get_anonymous_public_key ()
 {
@@ -101,3 +108,10 @@ convert_messenger_key_to_port(const struct GNUNET_HashCode 
*key,
 
   GNUNET_CRYPTO_hash_sum(key, &version, port);
 }
+
+void
+convert_peer_identity_to_id(const struct GNUNET_PeerIdentity *identity,
+                            struct GNUNET_ShortHashCode *id)
+{
+  GNUNET_memcpy(id, identity, sizeof(struct GNUNET_ShortHashCode));
+}
diff --git a/src/messenger/messenger_api_util.h 
b/src/messenger/messenger_api_util.h
index 3d68505a8..f50abf445 100644
--- a/src/messenger/messenger_api_util.h
+++ b/src/messenger/messenger_api_util.h
@@ -1,6 +1,6 @@
 /*
    This file is part of GNUnet.
-   Copyright (C) 2020--2021 GNUnet e.V.
+   Copyright (C) 2020--2023 GNUnet e.V.
 
    GNUnet is free software: you can redistribute it and/or modify it
    under the terms of the GNU Affero General Public License as published
@@ -52,6 +52,15 @@ int
 generate_free_member_id (struct GNUNET_ShortHashCode *id,
                          const struct GNUNET_CONTAINER_MultiShortmap *members);
 
+/**
+ * Returns the private identity key of #GNUNET_IDENTITY_ego_get_anonymous() 
without
+ * recalculating it every time.
+ *
+ * @return anonymous private key
+ */
+const struct GNUNET_IDENTITY_PrivateKey*
+get_anonymous_private_key ();
+
 /**
  * Returns the public identity key of #GNUNET_IDENTITY_ego_get_anonymous() 
without
  * recalculating it every time.
@@ -75,4 +84,15 @@ void
 convert_messenger_key_to_port(const struct GNUNET_HashCode *key,
                               struct GNUNET_HashCode *port);
 
+/**
+ * Converts a peers identity to a short hash code which can be used
+ * as id to refer to a peer via sender id as attached in messages.
+ *
+ * @param[in] identity Peer identity
+ * @param[out] id Short peer id
+ */
+void
+convert_peer_identity_to_id(const struct GNUNET_PeerIdentity *identity,
+                            struct GNUNET_ShortHashCode *id);
+
 #endif //GNUNET_SERVICE_MESSENGER_UTIL_H
diff --git a/src/messenger/test_messenger.c b/src/messenger/test_messenger.c
index 8758ce562..9958ce19e 100644
--- a/src/messenger/test_messenger.c
+++ b/src/messenger/test_messenger.c
@@ -45,14 +45,23 @@ static int status = 1;
 
 static struct GNUNET_SCHEDULER_Task *die_task = NULL;
 static struct GNUNET_SCHEDULER_Task *op_task = NULL;
+static struct GNUNET_SCHEDULER_Task *it_task = NULL;
 
 struct GNUNET_MESSENGER_Handle *messenger = NULL;
 
+static struct GNUNET_IDENTITY_PrivateKey identity;
+
 static void
 end (void *cls)
 {
   die_task = NULL;
 
+  if (it_task)
+  {
+    GNUNET_SCHEDULER_cancel (it_task);
+    it_task = NULL;
+  }
+
   if (op_task)
   {
     GNUNET_SCHEDULER_cancel (op_task);
@@ -100,9 +109,11 @@ static int identity_counter = 0;
  * @param handle Handle of messenger service
  */
 static void
-on_identity (void *cls,
-             struct GNUNET_MESSENGER_Handle *handle)
+on_iteration (void *cls)
 {
+  struct GNUNET_MESSENGER_Handle *handle = cls;
+  it_task = NULL;
+
   if (op_task)
   {
     GNUNET_SCHEDULER_cancel (op_task);
@@ -111,7 +122,7 @@ on_identity (void *cls,
 
   const char *name = GNUNET_MESSENGER_get_name (handle);
 
-  if (0 != strcmp (name, TESTER_NAME))
+  if ((!name) || (0 != strcmp (name, TESTER_NAME)))
   {
     op_task = GNUNET_SCHEDULER_add_now (&end_operation, "name");
     return;
@@ -119,7 +130,10 @@ on_identity (void *cls,
 
   const struct GNUNET_IDENTITY_PublicKey *key = GNUNET_MESSENGER_get_key 
(handle);
 
-  if (((!identity_counter) && (key)) || ((identity_counter) && (!key)))
+  struct GNUNET_IDENTITY_PublicKey pubkey;
+  GNUNET_IDENTITY_key_get_public(&identity, &pubkey);
+
+  if (((!identity_counter) && (key)) || ((identity_counter) && ((!key) || (0 
!= GNUNET_memcmp (key, &pubkey)))))
   {
     op_task = GNUNET_SCHEDULER_add_now (&end_operation, "key");
     return;
@@ -139,8 +153,10 @@ on_identity (void *cls,
     return;
   }
 
-  GNUNET_MESSENGER_update (messenger);
+  GNUNET_MESSENGER_set_key (handle, &identity);
   identity_counter++;
+
+  it_task = GNUNET_SCHEDULER_add_now (&on_iteration, handle);
 }
 
 /**
@@ -160,7 +176,13 @@ run (void *cls,
   identity_counter = 0;
 
   op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, 
"connect");
-  messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, &on_identity, NULL, 
NULL, NULL);
+  messenger = GNUNET_MESSENGER_connect (cfg, TESTER_NAME, NULL, NULL, NULL);
+
+  identity.type = htonl (GNUNET_IDENTITY_TYPE_ECDSA);
+  GNUNET_CRYPTO_ecdsa_key_create (&(identity.ecdsa_key));
+
+  if (messenger)
+    it_task = GNUNET_SCHEDULER_add_now (&on_iteration, messenger);
 }
 
 /**
diff --git a/src/messenger/test_messenger_anonymous.c 
b/src/messenger/test_messenger_anonymous.c
index 13f2b6f0e..f95b47704 100644
--- a/src/messenger/test_messenger_anonymous.c
+++ b/src/messenger/test_messenger_anonymous.c
@@ -43,6 +43,7 @@ static int status = 1;
 
 static struct GNUNET_SCHEDULER_Task *die_task = NULL;
 static struct GNUNET_SCHEDULER_Task *op_task = NULL;
+static struct GNUNET_SCHEDULER_Task *it_task = NULL;
 
 struct GNUNET_MESSENGER_Handle *messenger = NULL;
 
@@ -51,6 +52,12 @@ end (void *cls)
 {
   die_task = NULL;
 
+  if (it_task)
+  {
+    GNUNET_SCHEDULER_cancel (it_task);
+    it_task = NULL;
+  }
+
   if (op_task)
   {
     GNUNET_SCHEDULER_cancel (op_task);
@@ -96,9 +103,12 @@ end_operation (void *cls)
  * @param handle Handle of messenger service
  */
 static void
-on_identity (void *cls,
-             struct GNUNET_MESSENGER_Handle *handle)
+on_iteration (void *cls)
 {
+  struct GNUNET_MESSENGER_Handle *handle = cls;
+
+  it_task = NULL;
+
   if (op_task)
   {
     GNUNET_SCHEDULER_cancel (op_task);
@@ -113,7 +123,10 @@ on_identity (void *cls,
     return;
   }
 
-  if (GNUNET_SYSERR != GNUNET_MESSENGER_update (handle))
+  struct GNUNET_IDENTITY_PrivateKey zero;
+  memset (&zero, 0, sizeof (zero));
+
+  if (GNUNET_SYSERR != GNUNET_MESSENGER_set_key (handle, &zero))
   {
     op_task = GNUNET_SCHEDULER_add_now (&end_operation, "update-fail");
     return;
@@ -152,7 +165,10 @@ run (void *cls,
   die_task = GNUNET_SCHEDULER_add_delayed (TOTAL_TIMEOUT, &end_badly, NULL);
 
   op_task = GNUNET_SCHEDULER_add_delayed (BASE_TIMEOUT, &end_operation, 
"connect");
-  messenger = GNUNET_MESSENGER_connect (cfg, NULL, &on_identity, NULL, NULL, 
NULL);
+  messenger = GNUNET_MESSENGER_connect (cfg, NULL, NULL, NULL, NULL);
+
+  if (messenger)
+    it_task = GNUNET_SCHEDULER_add_now (&on_iteration, messenger);
 }
 
 /**
diff --git a/src/messenger/testing_messenger_setup.c 
b/src/messenger/testing_messenger_setup.c
index 65cf12e73..dbab3e82d 100644
--- a/src/messenger/testing_messenger_setup.c
+++ b/src/messenger/testing_messenger_setup.c
@@ -53,7 +53,7 @@ struct test_peer {
   struct GNUNET_MESSENGER_Handle *handle;
   struct GNUNET_MESSENGER_Room *room;
 
-  unsigned int peer_messages;
+  struct GNUNET_CONTAINER_MultiPeerMap *map;
 
   const char *message;
 };
@@ -79,7 +79,6 @@ shutdown_cb (void *cls)
 {
   struct test_properties *properties = cls;
 
-
   for (unsigned int i = 0; i < properties->num_peer; i++)
   {
     struct test_peer *peer = &properties->peers[i];
@@ -109,6 +108,9 @@ shutdown_cb (void *cls)
     if (peer->handle)
       GNUNET_MESSENGER_disconnect (peer->handle);
 
+    if (peer->map)
+      GNUNET_CONTAINER_multipeermap_destroy (peer->map);
+
     peer->handle = NULL;
   }
 
@@ -124,8 +126,6 @@ shutdown_cb (void *cls)
   properties->barrier = NULL;
 }
 
-
-
 static void
 end_cb (void *cls)
 {
@@ -281,11 +281,13 @@ on_message (void *cls,
            GNUNET_h2s(hash));
 
   if (GNUNET_MESSENGER_KIND_PEER == message->header.kind)
-    peer->peer_messages++;
+    GNUNET_CONTAINER_multipeermap_put (peer->map, &(message->body.peer.peer), 
NULL,
+                                       
GNUNET_CONTAINER_MULTIHASHMAPOPTION_REPLACE);
 
-  if (peer->props->num_hosts == peer->peer_messages)
+  const uint32_t num_peers = GNUNET_CONTAINER_multipeermap_size (peer->map);
+  if (peer->props->num_hosts == num_peers)
     peer->wait = GNUNET_wait_barrier (peer->props->barrier, &barrier2_wait_cb, 
peer);
-  else if (peer->props->num_hosts < peer->peer_messages)
+  else if (peer->props->num_hosts < num_peers)
   {
     if (peer->wait)
       GNUNET_cancel_wait_barrier(peer->wait);
@@ -377,7 +379,7 @@ on_peer (void *cb_cls,
     return;
   }
 
-  peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, 
NULL, &on_message, peer);
+  peer->handle = GNUNET_MESSENGER_connect (pinfo->result.cfg, TEST_NAME, NULL, 
&on_message, peer);
 
   GNUNET_assert(GNUNET_OK == GNUNET_CRYPTO_get_peer_identity(
       pinfo->result.cfg, &(peer->peer_id)
@@ -427,6 +429,8 @@ run (void *cls,
 
   peer->peer = event->details.peer_start.peer;
   peer->op = GNUNET_TESTBED_peer_get_information (peer->peer, 
GNUNET_TESTBED_PIT_CONFIGURATION, on_peer, peer);
+
+  peer->map = GNUNET_CONTAINER_multipeermap_create(peer->props->num_hosts, 
GNUNET_NO);
 }
 
 static void
diff --git a/src/util/crypto_ecc_setup.c b/src/util/crypto_ecc_setup.c
index e07d1e448..dd49049bc 100644
--- a/src/util/crypto_ecc_setup.c
+++ b/src/util/crypto_ecc_setup.c
@@ -1,6 +1,6 @@
 /*
      This file is part of GNUnet.
-     Copyright (C) 2012, 2013, 2015, 2020 GNUnet e.V.
+     Copyright (C) 2012, 2013, 2015, 2020, 2023 GNUnet e.V.
 
      GNUnet is free software: you can redistribute it and/or modify it
      under the terms of the GNU Affero General Public License as published
@@ -289,6 +289,34 @@ GNUNET_CRYPTO_get_peer_identity (const struct 
GNUNET_CONFIGURATION_Handle *cfg,
 }
 
 
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_sign_by_peer_identity (const struct GNUNET_CONFIGURATION_Handle 
*cfg,
+                                     const struct 
GNUNET_CRYPTO_EccSignaturePurpose *purpose,
+                                     struct GNUNET_CRYPTO_EddsaSignature *sig)
+{
+  struct GNUNET_CRYPTO_EddsaPrivateKey *priv;
+
+  if (NULL == (priv = GNUNET_CRYPTO_eddsa_key_create_from_configuration (cfg)))
+  {
+    GNUNET_log (GNUNET_ERROR_TYPE_ERROR,
+                _ ("Could not load peer's private key\n"));
+    return GNUNET_SYSERR;
+  }
+
+  return GNUNET_CRYPTO_eddsa_sign_ (priv, purpose, sig);
+}
+
+
+enum GNUNET_GenericReturnValue
+GNUNET_CRYPTO_verify_peer_identity (uint32_t purpose,
+                                    const struct 
GNUNET_CRYPTO_EccSignaturePurpose * validate,
+                                    const struct GNUNET_CRYPTO_EddsaSignature 
*sig,
+                                    const struct GNUNET_PeerIdentity *identity)
+{
+  return GNUNET_CRYPTO_eddsa_verify_ (purpose, validate, sig, 
&identity->public_key);
+}
+
+
 /**
  * Setup a key file for a peer given the name of the
  * configuration file (!).  This function is used so that

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]