diff --git a/contrib/src/msgpack/rules.mak b/contrib/src/msgpack/rules.mak
index 0d0508ad18e7d8af90ce967a7c1362cc0de6ac3d..e35817a3774d07642721d1b2445f823b60e62c01 100644
--- a/contrib/src/msgpack/rules.mak
+++ b/contrib/src/msgpack/rules.mak
@@ -3,7 +3,7 @@ MSGPACK_VERSION := cpp-3.2.0
 MSGPACK_URL := https://github.com/msgpack/msgpack-c/archive/$(MSGPACK_VERSION).tar.gz
 
 PKGS += msgpack
-ifeq ($(call need_pkg,"msgpack >= 1.1"),)
+ifeq ($(call need_pkg,"msgpack >= 3.0.0"),)
 PKGS_FOUND += msgpack
 endif
 
diff --git a/contrib/src/opendht/SHA512SUMS b/contrib/src/opendht/SHA512SUMS
index c749f4bf0de6c8bb64a404974fa5109efdab508a..92b2b30aa4ac0c86cfdc2694f4d2daa7e5bdc799 100644
--- a/contrib/src/opendht/SHA512SUMS
+++ b/contrib/src/opendht/SHA512SUMS
@@ -1 +1 @@
-75d3da56bb9cb4ccc3afcb29b68a19f551f7a0f10193bf9a6efb2acaed2b4243c39daf96d8ab4e080596d44e15da1198a91cfaa7cd457ccdbb3d10a08f9b5fb0  opendht-2.2.0.tar.gz
\ No newline at end of file
+11cb53c1145793fb92d54a7775a00783bb8216939d87c31c9b12433a274b4f728cfa46de64bd111d14817264bee2bab12511549c8a544f863ddfdbbe2261c140  opendht-efda4af94c6310b3966dc850f20467b6309d0a43.tar.gz
diff --git a/contrib/src/opendht/package.json b/contrib/src/opendht/package.json
index caaf490eaf1821b011d046a62984d13ec6f52aab..742ac166744caec8867617a081bdc9659139c6ea 100644
--- a/contrib/src/opendht/package.json
+++ b/contrib/src/opendht/package.json
@@ -1,6 +1,6 @@
 {
     "name": "opendht",
-    "version": "2.2.0",
+    "version": "efda4af94c6310b3966dc850f20467b6309d0a43",
     "url": "https://github.com/savoirfairelinux/opendht/archive/__VERSION__.tar.gz",
     "deps": [
         "argon2",
diff --git a/contrib/src/opendht/rules.mak b/contrib/src/opendht/rules.mak
index 43e0c64fe1b8ba392bf15a2dacf74bfcceff2e8d..642383ad8d90499e314cabc45c5cb77d75b72b93 100644
--- a/contrib/src/opendht/rules.mak
+++ b/contrib/src/opendht/rules.mak
@@ -1,5 +1,5 @@
 # OPENDHT
-OPENDHT_VERSION := 2.2.0
+OPENDHT_VERSION := efda4af94c6310b3966dc850f20467b6309d0a43
 OPENDHT_URL := https://github.com/savoirfairelinux/opendht/archive/$(OPENDHT_VERSION).tar.gz
 
 PKGS += opendht
diff --git a/src/jamidht/account_manager.cpp b/src/jamidht/account_manager.cpp
index 855c13bca0a910a90902c33797bd60d5a386e074..ee5ce2b0c2e24cf0a9f4e0faaf018a808ab827be 100644
--- a/src/jamidht/account_manager.cpp
+++ b/src/jamidht/account_manager.cpp
@@ -177,7 +177,8 @@ AccountManager::useIdentity(const dht::crypto::Identity& identity,
     info->contacts = std::move(contactList);
     info->contacts->load();
     info->accountId = id;
-    info->deviceId = identity.first->getPublicKey().getId().toString();
+    info->devicePk = identity.first->getSharedPublicKey();
+    info->deviceId = info->devicePk->getLongId().toString();
     info->announce = std::move(announce);
     info->ethAccount = root["eth"].asString();
     info->username = username;
@@ -212,6 +213,7 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc
         for (const auto& crl : info_->identity.second->issuer->getRevocationLists())
             dht_->put(h, crl, dht::DoneCallback {}, {}, true);
         dht_->listen<DeviceAnnouncement>(h, [this, cb = std::move(cb)](DeviceAnnouncement&& dev) {
+            // dev.from
             findCertificate(dev.dev,
                             [this, cb](const std::shared_ptr<dht::crypto::Certificate>& crt) {
                                 foundAccountDevice(crt);
@@ -235,13 +237,13 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc
         JAMI_WARN("can't announce device: no announcement...");
     }
 
-    auto inboxKey = dht::InfoHash::get("inbox:" + info_->deviceId);
+    auto inboxKey = dht::InfoHash::get("inbox:" + info_->devicePk->getId().toString());
     dht_->listen<dht::TrustRequest>(inboxKey, [this](dht::TrustRequest&& v) {
         if (v.service != DHT_TYPE_NS)
             return true;
 
         // allowPublic always true for trust requests (only forbidden if banned)
-        onPeerMessage(v.from,
+        onPeerMessage(*v.owner,
                       true,
                       [this, v](const std::shared_ptr<dht::crypto::Certificate>&,
                                 dht::InfoHash peer_account) mutable {
@@ -251,7 +253,7 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc
                                     v.conversationId.c_str());
                           if (info_)
                               if (info_->contacts->onTrustRequest(peer_account,
-                                                                  v.from,
+                                                                  v.owner,
                                                                   time(nullptr),
                                                                   v.confirm,
                                                                   v.conversationId,
@@ -264,7 +266,7 @@ AccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnouncedCb& dc
     });
 }
 
-const std::map<dht::InfoHash, KnownDevice>&
+const std::map<dht::PkId, KnownDevice>&
 AccountManager::getKnownDevices() const
 {
     return info_->contacts->getKnownDevices();
@@ -282,14 +284,14 @@ void
 AccountManager::setAccountDeviceName(const std::string& name)
 {
     if (info_)
-        info_->contacts->setAccountDeviceName(dht::InfoHash(info_->deviceId), name);
+        info_->contacts->setAccountDeviceName(DeviceId(info_->deviceId), name);
 }
 
 std::string
 AccountManager::getAccountDeviceName() const
 {
     if (info_)
-        return info_->contacts->getAccountDeviceName(dht::InfoHash(info_->deviceId));
+        return info_->contacts->getAccountDeviceName(DeviceId(info_->deviceId));
     return {};
 }
 
@@ -334,7 +336,7 @@ AccountManager::foundPeerDevice(const std::shared_ptr<dht::crypto::Certificate>&
 }
 
 void
-AccountManager::onPeerMessage(const dht::InfoHash& peer_device,
+AccountManager::onPeerMessage(const dht::crypto::PublicKey& peer_device,
                               bool allowPublic,
                               std::function<void(const std::shared_ptr<dht::crypto::Certificate>& crt,
                                                  const dht::InfoHash& peer_account)>&& cb)
@@ -346,8 +348,8 @@ AccountManager::onPeerMessage(const dht::InfoHash& peer_device,
         return;
     }
 
-    findCertificate(peer_device,
-                    [this, peer_device, cb = std::move(cb), allowPublic](
+    findCertificate(peer_device.getId(),
+                    [this, cb = std::move(cb), allowPublic](
                         const std::shared_ptr<dht::crypto::Certificate>& cert) {
                         dht::InfoHash peer_account_id;
                         if (onPeerCertificate(cert, allowPublic, peer_account_id)) {
@@ -576,6 +578,26 @@ AccountManager::findCertificate(
     return true;
 }
 
+bool
+AccountManager::findCertificate(
+    const dht::PkId& id, std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb)
+{
+    if (auto cert = tls::CertificateStore::instance().getCertificate(id.toString())) {
+        if (cb)
+            cb(cert);
+    } else {
+        /*dht_->findCertificate(id, [cb](const std::shared_ptr<dht::crypto::Certificate>& crt) {
+            if (crt)
+                tls::CertificateStore::instance().pinCertificate(crt);
+            if (cb)
+                cb(crt);
+        });*/
+        if (cb)
+            cb(nullptr);
+    }
+    return true;
+}
+
 bool
 AccountManager::setCertificateStatus(const std::string& cert_id,
                                      tls::TrustStore::PermissionStatus status)
@@ -656,14 +678,15 @@ AccountManager::sendTrustRequest(const std::string& to,
     if (info_->contacts->addContact(toH, false, convId)) {
         syncDevices();
     }
-    forEachDevice(toH, [this, toH, convId, payload](const dht::InfoHash& dev) {
-        JAMI_WARN("sending trust request to: %s / %s",
-                  toH.toString().c_str(),
-                  dev.toString().c_str());
-        dht_->putEncrypted(dht::InfoHash::get("inbox:" + dev.toString()),
-                           dev,
-                           dht::TrustRequest(DHT_TYPE_NS, convId, payload));
-    });
+    forEachDevice(toH,
+                  [this, toH, convId, payload](const std::shared_ptr<dht::crypto::PublicKey>& dev) {
+                      JAMI_WARN("sending trust request to: %s / %s",
+                                toH.toString().c_str(),
+                                dev->getLongId().toString().c_str());
+                      dht_->putEncrypted(dht::InfoHash::get("inbox:" + dev->getId().toString()),
+                                         dev,
+                                         dht::TrustRequest(DHT_TYPE_NS, convId, payload));
+                  });
 }
 
 void
@@ -677,18 +700,21 @@ AccountManager::sendTrustRequestConfirm(const dht::InfoHash& toH, const std::str
     if (!convId.empty() && info_)
         info_->contacts->acceptConversation(convId);
 
-    forEachDevice(toH, [this, toH, answer](const dht::InfoHash& dev) {
+    forEachDevice(toH, [this, toH, answer](const std::shared_ptr<dht::crypto::PublicKey>& dev) {
         JAMI_WARN("sending trust request reply: %s / %s",
                   toH.toString().c_str(),
-                  dev.toString().c_str());
-        dht_->putEncrypted(dht::InfoHash::get("inbox:" + dev.toString()), dev, answer);
+                  dev->getLongId().toString().c_str());
+        dht_->putEncrypted(dht::InfoHash::get("inbox:" + info_->devicePk->getId().toString()),
+                           dev,
+                           answer);
     });
 }
 
 void
-AccountManager::forEachDevice(const dht::InfoHash& to,
-                              std::function<void(const dht::InfoHash&)>&& op,
-                              std::function<void(bool)>&& end)
+AccountManager::forEachDevice(
+    const dht::InfoHash& to,
+    std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
+    std::function<void(bool)>&& end)
 {
     if (not dht_) {
         JAMI_ERR("forEachDevice: no dht");
@@ -696,26 +722,63 @@ AccountManager::forEachDevice(const dht::InfoHash& to,
             end(false);
         return;
     }
-    auto treatedDevices = std::make_shared<std::set<dht::InfoHash>>();
     dht_->get<dht::crypto::RevocationList>(to, [to](dht::crypto::RevocationList&& crl) {
         tls::CertificateStore::instance().pinRevocationList(to.toString(), std::move(crl));
         return true;
     });
+
+    struct State
+    {
+        unsigned remaining {0};
+        std::set<dht::PkId> treatedDevices {};
+        std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)> onDevice;
+        std::function<void(bool)> onEnd;
+
+        void found(std::shared_ptr<dht::crypto::PublicKey> pk)
+        {
+            remaining--;
+            if (pk && *pk) {
+                auto longId = pk->getLongId();
+                if (treatedDevices.emplace(longId).second) {
+                    onDevice(pk);
+                }
+            }
+            ended();
+        }
+
+        void ended()
+        {
+            if (remaining == 0 && onEnd) {
+                JAMI_DBG("Found %lu devices", treatedDevices.size());
+                onEnd(not treatedDevices.empty());
+                onDevice = {};
+                onEnd = {};
+            }
+        }
+    };
+    auto state = std::make_shared<State>();
+    state->onDevice = std::move(op);
+    state->onEnd = std::move(end);
+
     dht_->get<DeviceAnnouncement>(
         to,
-        [to, treatedDevices, op = std::move(op)](DeviceAnnouncement&& dev) {
+        [this, to, state](DeviceAnnouncement&& dev) {
             if (dev.from != to)
                 return true;
-            if (treatedDevices->emplace(dev.dev).second) {
-                op(dev.dev);
+            if (dev.pk) {
+                state->found(std::move(dev.pk));
+            } else {
+                state->remaining++;
+                findCertificate(dev.dev,
+                                [state](const std::shared_ptr<dht::crypto::Certificate>& cert) {
+                                    state->found(cert ? std::make_shared<dht::crypto::PublicKey>(
+                                                     cert->getPublicKey())
+                                                      : std::shared_ptr<dht::crypto::PublicKey> {});
+                                });
             }
             return true;
         },
-        [=, end = std::move(end)](bool /*ok*/) {
-            JAMI_DBG("Found %lu devices for %s", treatedDevices->size(), to.to_c_str());
-            if (end)
-                end(not treatedDevices->empty());
-        });
+        [state](bool /*ok*/) { state->ended(); });
 }
 
 void
diff --git a/src/jamidht/account_manager.h b/src/jamidht/account_manager.h
index 2638004510860c7f5e037fd53a20a9a06468213a..0c751e60e7238e743f965798be4cb062ff760c97 100644
--- a/src/jamidht/account_manager.h
+++ b/src/jamidht/account_manager.h
@@ -40,6 +40,7 @@ class DhtRunner;
 
 namespace jami {
 
+using DeviceId = dht::PkId;
 struct AccountArchive;
 
 struct AccountInfo
@@ -50,6 +51,7 @@ struct AccountInfo
     std::map<std::string, ConversationRequest> conversationsRequests;
     std::string accountId;
     std::string deviceId;
+    std::shared_ptr<dht::crypto::PublicKey> devicePk;
     std::shared_ptr<dht::Value> announce;
     std::string ethAccount;
     std::string username;
@@ -166,7 +168,7 @@ public:
         return false;
     };
 
-    const std::map<dht::InfoHash, KnownDevice>& getKnownDevices() const;
+    const std::map<dht::PkId, KnownDevice>& getKnownDevices() const;
     bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt,
                             const std::string& name = {},
                             const time_point& last_sync = time_point::min());
@@ -175,12 +177,12 @@ public:
     std::string getAccountDeviceName() const;
 
     void forEachDevice(const dht::InfoHash& to,
-                       std::function<void(const dht::InfoHash&)>&& op,
+                       std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
                        std::function<void(bool)>&& end = {});
 
     using PeerCertificateCb = std::function<void(const std::shared_ptr<dht::crypto::Certificate>& crt,
                                                  const dht::InfoHash& peer_account)>;
-    void onPeerMessage(const dht::InfoHash& peer_device, bool allowPublic, PeerCertificateCb&& cb);
+    void onPeerMessage(const dht::crypto::PublicKey& peer_device, bool allowPublic, PeerCertificateCb&& cb);
     bool onPeerCertificate(const std::shared_ptr<dht::crypto::Certificate>& crt,
                            bool allowPublic,
                            dht::InfoHash& account_id);
@@ -237,6 +239,11 @@ public:
     virtual bool findCertificate(
         const dht::InfoHash& h,
         std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
+
+    virtual bool findCertificate(
+        const dht::PkId& h,
+        std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
+
     bool setCertificateStatus(const std::string& cert_id, tls::TrustStore::PermissionStatus status);
     std::vector<std::string> getCertificatesByStatus(tls::TrustStore::PermissionStatus status);
     tls::TrustStore::PermissionStatus getCertificateStatus(const std::string& cert_id) const;
diff --git a/src/jamidht/archive_account_manager.cpp b/src/jamidht/archive_account_manager.cpp
index 612c9af846d7c9e5dc9866cdd3bc12353b959f0c..28249e94e4917df8d95a92330900cf5e50dfadb7 100644
--- a/src/jamidht/archive_account_manager.cpp
+++ b/src/jamidht/archive_account_manager.cpp
@@ -341,7 +341,8 @@ ArchiveAccountManager::onArchiveLoaded(AuthContext& ctx, AccountArchive&& a)
     info->identity.first = ctx.key.get();
     info->identity.second = deviceCertificate;
     info->accountId = a.id.second->getId().toString();
-    info->deviceId = deviceCertificate->getPublicKey().getId().toString();
+    info->devicePk = info->identity.first->getSharedPublicKey();
+    info->deviceId = info->devicePk->getLongId().toString();
     if (ctx.deviceName.empty())
         ctx.deviceName = info->deviceId.substr(8);
 
@@ -399,12 +400,16 @@ ArchiveAccountManager::makeReceipt(const dht::crypto::Identity& id,
     auto devId = device.getId();
     DeviceAnnouncement announcement;
     announcement.dev = devId;
+    announcement.pk = std::make_shared<dht::crypto::PublicKey>(device.getPublicKey());
     dht::Value ann_val {announcement};
     ann_val.sign(*id.first);
 
+    auto packedAnnoucement = ann_val.getPacked();
+    JAMI_DBG("[Auth] device announcement size: %zu", packedAnnoucement.size());
+
     std::ostringstream is;
     is << "{\"id\":\"" << id.second->getId() << "\",\"dev\":\"" << devId << "\",\"eth\":\""
-       << ethAccount << "\",\"announce\":\"" << base64::encode(ann_val.getPacked()) << "\"}";
+       << ethAccount << "\",\"announce\":\"" << base64::encode(packedAnnoucement) << "\"}";
 
     // auto announce_ = ;
     return {is.str(), std::make_shared<dht::Value>(std::move(ann_val))};
@@ -444,11 +449,12 @@ ArchiveAccountManager::syncDevices()
         // don't send sync data to ourself
         if (dev.first.toString() == info_->deviceId)
             continue;
+        auto pk = std::make_shared<dht::crypto::PublicKey>(dev.second.certificate->getPublicKey());
         JAMI_DBG("sending device sync to %s %s",
                  dev.second.name.c_str(),
                  dev.first.toString().c_str());
-        auto syncDeviceKey = dht::InfoHash::get("inbox:" + dev.first.toString());
-        dht_->putEncrypted(syncDeviceKey, dev.first, sync_data);
+        auto syncDeviceKey = dht::InfoHash::get("inbox:" + pk->getId().toString());
+        dht_->putEncrypted(syncDeviceKey, pk, sync_data);
     }
 }
 
@@ -457,23 +463,26 @@ ArchiveAccountManager::startSync(const OnNewDeviceCb& cb, const OnDeviceAnnounce
 {
     AccountManager::startSync(std::move(cb), std::move(dcb));
 
-    dht_->listen<DeviceSync>(dht::InfoHash::get("inbox:" + info_->deviceId), [this](DeviceSync&& sync) {
-        // Received device sync data.
-        // check device certificate
-        findCertificate(sync.from,
-                        [this, sync](const std::shared_ptr<dht::crypto::Certificate>& cert) mutable {
-                            if (!cert or cert->getId() != sync.from) {
-                                JAMI_WARN("Can't find certificate for device %s",
-                                          sync.from.toString().c_str());
-                                return;
-                            }
-                            if (not foundAccountDevice(cert))
-                                return;
-                            onSyncData(std::move(sync));
-                        });
+    dht_->listen<DeviceSync>(
+        dht::InfoHash::get("inbox:" + info_->devicePk->getId().toString()),
+        [this](DeviceSync&& sync) {
+            // Received device sync data.
+            // check device certificate
+            findCertificate(sync.from,
+                            [this,
+                             sync](const std::shared_ptr<dht::crypto::Certificate>& cert) mutable {
+                                if (!cert or cert->getId() != sync.from) {
+                                    JAMI_WARN("Can't find certificate for device %s",
+                                              sync.from.toString().c_str());
+                                    return;
+                                }
+                                if (not foundAccountDevice(cert))
+                                    return;
+                                onSyncData(std::move(sync));
+                            });
 
-        return true;
-    });
+            return true;
+        });
 }
 
 void
@@ -482,14 +491,14 @@ ArchiveAccountManager::onSyncData(DeviceSync&& sync, bool checkDevice)
     auto sync_date = clock::time_point(clock::duration(sync.date));
     if (checkDevice) {
         // If the DHT is used, we need to check the device here
-        if (not info_->contacts->syncDevice(sync.from, sync_date)) {
+        if (not info_->contacts->syncDevice(sync.owner->getLongId(), sync_date)) {
             return;
         }
     }
 
     // Sync known devices
     JAMI_DBG("[Contacts] received device sync data (%lu devices, %lu contacts)",
-             sync.devices_known.size(),
+             sync.devices_known.size() + sync.devices.size(),
              sync.peers.size());
     for (const auto& d : sync.devices_known) {
         findCertificate(d.first, [this, d](const std::shared_ptr<dht::crypto::Certificate>& crt) {
@@ -499,6 +508,15 @@ ArchiveAccountManager::onSyncData(DeviceSync&& sync, bool checkDevice)
             foundAccountDevice(crt, d.second);
         });
     }
+    for (const auto& d : sync.devices) {
+        findCertificate(d.second.sha1,
+                        [this, d](const std::shared_ptr<dht::crypto::Certificate>& crt) {
+                            if (not crt || crt->getLongId() != d.first)
+                                return;
+                            // std::lock_guard<std::mutex> lock(deviceListMutex_);
+                            foundAccountDevice(crt, d.second.name);
+                        });
+    }
     // saveKnownDevices();
 
     // Sync contacts
@@ -702,7 +720,7 @@ ArchiveAccountManager::revokeDevice(const std::string& password,
                             tls::CertificateStore::instance().loadRevocations(*a.id.second);
 
                             this_.saveArchive(a, password);
-                            this_.info_->contacts->removeAccountDevice(crt->getId());
+                            this_.info_->contacts->removeAccountDevice(crt->getLongId());
                             cb(RevokeDeviceResult::SUCCESS);
                             this_.syncDevices();
                         });
diff --git a/src/jamidht/connectionmanager.cpp b/src/jamidht/connectionmanager.cpp
index 437bbf667c47f8714b110a0d0645d9d84539f508..a25799167035e52afead23281a2cd477ce1d570b 100644
--- a/src/jamidht/connectionmanager.cpp
+++ b/src/jamidht/connectionmanager.cpp
@@ -109,7 +109,7 @@ public:
         dht::Value::Id vid;
     };
 
-    void connectDeviceStartIce(const DeviceId& deviceId, const dht::Value::Id& vid);
+    void connectDeviceStartIce(const std::shared_ptr<dht::crypto::PublicKey>& devicePk, const dht::Value::Id& vid);
     void connectDeviceOnNegoDone(const DeviceId& deviceId,
                                  const std::string& name,
                                  const dht::Value::Id& vid,
@@ -136,7 +136,7 @@ public:
     /**
      * Triggered when a PeerConnectionRequest comes from the DHT
      */
-    void answerTo(IceTransport& ice, const dht::Value::Id& id, const DeviceId& from);
+    void answerTo(IceTransport& ice, const dht::Value::Id& id, const std::shared_ptr<dht::crypto::PublicKey>& fromPk);
     void onRequestStartIce(const PeerConnectionRequest& req);
     void onRequestOnNegoDone(const PeerConnectionRequest& req);
     void onDhtPeerRequest(const PeerConnectionRequest& req,
@@ -144,7 +144,7 @@ public:
 
     void addNewMultiplexedSocket(const DeviceId& deviceId, const dht::Value::Id& vid);
     void onPeerResponse(const PeerConnectionRequest& req);
-    void onDhtConnected(const DeviceId& deviceId);
+    void onDhtConnected(const dht::crypto::PublicKey& devicePk);
 
     /**
      * Triggered when a new TLS socket is ready to use
@@ -262,8 +262,9 @@ public:
 };
 
 void
-ConnectionManager::Impl::connectDeviceStartIce(const DeviceId& deviceId, const dht::Value::Id& vid)
+ConnectionManager::Impl::connectDeviceStartIce(const std::shared_ptr<dht::crypto::PublicKey>& devicePk, const dht::Value::Id& vid)
 {
+    auto deviceId = devicePk->getLongId();
     auto info = getInfo(deviceId, vid);
     if (!info) {
         return;
@@ -305,8 +306,8 @@ ConnectionManager::Impl::connectDeviceStartIce(const DeviceId& deviceId, const d
     // Send connection request through DHT
     JAMI_DBG() << account << "Request connection to " << deviceId;
     account.dht()->putEncrypted(dht::InfoHash::get(PeerConnectionRequest::key_prefix
-                                                   + deviceId.toString()),
-                                deviceId,
+                                                   + devicePk->getId().toString()),
+                                devicePk,
                                 value,
                                 [deviceId](bool ok) {
                                     if (!ok)
@@ -396,7 +397,7 @@ ConnectionManager::Impl::connectDevice(const DeviceId& deviceId,
                             [w = weak(), deviceId, name, cb = std::move(cb), noNewSocket](
                                 const std::shared_ptr<dht::crypto::Certificate>& cert) {
                                 if (!cert) {
-                                    JAMI_ERR("Invalid certificate found for device %s",
+                                    JAMI_ERR("No valid certificate found for device %s",
                                              deviceId.to_c_str());
                                     cb(nullptr, deviceId);
                                     return;
@@ -419,7 +420,8 @@ ConnectionManager::Impl::connectDevice(const std::shared_ptr<dht::crypto::Certif
                      cert = std::move(cert),
                      cb = std::move(cb),
                      noNewSocket] {
-        auto deviceId = cert->getId();
+        auto devicePk = std::make_shared<dht::crypto::PublicKey>(cert->getPublicKey());
+        auto deviceId = devicePk->getLongId();
         auto sthis = w.lock();
         if (!sthis || sthis->isDestroying_) {
             cb(nullptr, deviceId);
@@ -488,6 +490,7 @@ ConnectionManager::Impl::connectDevice(const std::shared_ptr<dht::crypto::Certif
         // If no socket exists, we need to initiate an ICE connection.
         sthis->account.getIceOptions([w,
                                       deviceId = std::move(deviceId),
+                                      devicePk = std::move(devicePk),
                                       name = std::move(name),
                                       cert = std::move(cert),
                                       vid,
@@ -498,6 +501,7 @@ ConnectionManager::Impl::connectDevice(const std::shared_ptr<dht::crypto::Certif
             ice_config.tcpEnable = true;
             ice_config.onInitDone = [w,
                                      deviceId = std::move(deviceId),
+                                     devicePk = std::move(devicePk),
                                      name = std::move(name),
                                      cert = std::move(cert),
                                      vid,
@@ -514,9 +518,9 @@ ConnectionManager::Impl::connectDevice(const std::shared_ptr<dht::crypto::Certif
                 }
 
                 dht::ThreadPool::io().run(
-                    [w = std::move(w), deviceId = std::move(deviceId), vid = std::move(vid)] {
+                    [w = std::move(w), devicePk = std::move(devicePk), vid = std::move(vid)] {
                         if (auto sthis = w.lock())
-                            sthis->connectDeviceStartIce(deviceId, vid);
+                            sthis->connectDeviceStartIce(devicePk, vid);
                     });
             };
             ice_config.onNegoDone = [w,
@@ -607,7 +611,7 @@ ConnectionManager::Impl::sendChannelRequest(std::shared_ptr<MultiplexedSocket>&
 void
 ConnectionManager::Impl::onPeerResponse(const PeerConnectionRequest& req)
 {
-    auto device = req.from;
+    auto device = req.owner->getLongId();
     JAMI_INFO() << account << " New response received from " << device.to_c_str();
     if (auto info = getInfo(device, req.id)) {
         std::lock_guard<std::mutex> lk {info->mutex_};
@@ -620,12 +624,12 @@ ConnectionManager::Impl::onPeerResponse(const PeerConnectionRequest& req)
 }
 
 void
-ConnectionManager::Impl::onDhtConnected(const DeviceId& deviceId)
+ConnectionManager::Impl::onDhtConnected(const dht::crypto::PublicKey& devicePk)
 {
     if (!account.dht())
         return;
     account.dht()->listen<PeerConnectionRequest>(
-        dht::InfoHash::get(PeerConnectionRequest::key_prefix + deviceId.toString()),
+        dht::InfoHash::get(PeerConnectionRequest::key_prefix + devicePk.getId().toString()),
         [w = weak()](PeerConnectionRequest&& req) {
             auto shared = w.lock();
             if (!shared)
@@ -635,9 +639,9 @@ ConnectionManager::Impl::onDhtConnected(const DeviceId& deviceId)
                 return true;
             }
             if (req.isAnswer) {
-                JAMI_DBG() << "Received request answer from " << req.from;
+                JAMI_DBG() << "Received request answer from " << req.owner->getLongId();
             } else {
-                JAMI_DBG() << "Received request from " << req.from;
+                JAMI_DBG() << "Received request from " << req.owner->getLongId();
             }
             // Hack:
             // Note: This reschedule on the io pool should not be necessary
@@ -666,7 +670,7 @@ ConnectionManager::Impl::onDhtConnected(const DeviceId& deviceId)
                             } else {
                                 JAMI_WARN()
                                     << shared->account
-                                    << "Rejected untrusted connection request from " << req.from;
+                                    << "Rejected untrusted connection request from " << req.owner->getLongId();
                             }
                         });
                 }
@@ -728,7 +732,7 @@ ConnectionManager::Impl::onTlsNegotiationDone(bool ok,
 }
 
 void
-ConnectionManager::Impl::answerTo(IceTransport& ice, const dht::Value::Id& id, const DeviceId& from)
+ConnectionManager::Impl::answerTo(IceTransport& ice, const dht::Value::Id& id, const std::shared_ptr<dht::crypto::PublicKey>& from)
 {
     // NOTE: This is a shortest version of a real SDP message to save some bits
     auto iceAttributes = ice.getLocalAttributes();
@@ -747,22 +751,23 @@ ConnectionManager::Impl::answerTo(IceTransport& ice, const dht::Value::Id& id, c
     auto value = std::make_shared<dht::Value>(std::move(val));
     value->user_type = "peer_request";
 
-    JAMI_DBG() << account << "[CNX] connection accepted, DHT reply to " << from;
+    JAMI_DBG() << account << "[CNX] connection accepted, DHT reply to " << from->getLongId();
     account.dht()->putEncrypted(
-        dht::InfoHash::get(PeerConnectionRequest::key_prefix + from.toString()),
+        dht::InfoHash::get(PeerConnectionRequest::key_prefix + from->getId().toString()),
         from,
         value,
         [from](bool ok) {
             if (!ok)
                 JAMI_ERR("Tried to answer to connection request from %s, but put failed",
-                         from.to_c_str());
+                         from->getLongId().to_c_str());
         });
 }
 
 void
 ConnectionManager::Impl::onRequestStartIce(const PeerConnectionRequest& req)
 {
-    auto info = getInfo(req.from, req.id);
+    auto deviceId = req.owner->getLongId();
+    auto info = getInfo(deviceId, req.id);
     if (!info)
         return;
 
@@ -771,17 +776,17 @@ ConnectionManager::Impl::onRequestStartIce(const PeerConnectionRequest& req)
     if (!ice) {
         JAMI_ERR("No ICE detected");
         if (connReadyCb_)
-            connReadyCb_(req.from, "", nullptr);
+            connReadyCb_(deviceId, "", nullptr);
         return;
     }
 
     auto sdp = ice->parseIceCandidates(req.ice_msg);
-    answerTo(*ice, req.id, req.from);
+    answerTo(*ice, req.id, req.owner);
     if (not ice->startIce({sdp.rem_ufrag, sdp.rem_pwd}, std::move(sdp.rem_candidates))) {
         JAMI_ERR("[Account:%s] start ICE failed - fallback to TURN", account.getAccountID().c_str());
         ice = nullptr;
         if (connReadyCb_)
-            connReadyCb_(req.from, "", nullptr);
+            connReadyCb_(deviceId, "", nullptr);
         return;
     }
 }
@@ -789,7 +794,8 @@ ConnectionManager::Impl::onRequestStartIce(const PeerConnectionRequest& req)
 void
 ConnectionManager::Impl::onRequestOnNegoDone(const PeerConnectionRequest& req)
 {
-    auto info = getInfo(req.from, req.id);
+    auto deviceId = req.owner->getLongId();
+    auto info = getInfo(deviceId, req.id);
     if (!info)
         return;
 
@@ -798,7 +804,7 @@ ConnectionManager::Impl::onRequestOnNegoDone(const PeerConnectionRequest& req)
     if (!ice) {
         JAMI_ERR("No ICE detected");
         if (connReadyCb_)
-            connReadyCb_(req.from, "", nullptr);
+            connReadyCb_(deviceId, "", nullptr);
         return;
     }
 
@@ -826,7 +832,7 @@ ConnectionManager::Impl::onRequestOnNegoDone(const PeerConnectionRequest& req)
         });
 
     info->tls_->setOnReady(
-        [w = weak(), deviceId = std::move(req.from), vid = std::move(req.id)](bool ok) {
+        [w = weak(), deviceId = std::move(deviceId), vid = std::move(req.id)](bool ok) {
             if (auto shared = w.lock())
                 shared->onTlsNegotiationDone(ok, deviceId, vid);
         });
@@ -836,39 +842,38 @@ void
 ConnectionManager::Impl::onDhtPeerRequest(const PeerConnectionRequest& req,
                                           const std::shared_ptr<dht::crypto::Certificate>& /*cert*/)
 {
-    auto deviceId = req.from.toString();
-    JAMI_INFO() << account << "New connection requested by " << deviceId.c_str();
-    if (!iceReqCb_ || !iceReqCb_(req.from)) {
+    auto deviceId = req.owner->getLongId();
+    JAMI_INFO() << account << "New connection requested by " << deviceId;
+    if (!iceReqCb_ || !iceReqCb_(deviceId)) {
         JAMI_INFO("[Account:%s] refuse connection from %s",
                   account.getAccountID().c_str(),
-                  deviceId.c_str());
+                  deviceId.toString().c_str());
         return;
     }
 
     // Because the connection is accepted, create an ICE socket.
-    account.getIceOptions([w = weak(), req](auto&& ice_config) {
-        auto deviceId = req.from.toString();
+    account.getIceOptions([w = weak(), req, deviceId](auto&& ice_config) {
         auto shared = w.lock();
         if (!shared)
             return;
         // Note: used when the ice negotiation fails to erase
         // all stored structures.
-        auto eraseInfo = [w, id = req.id, from = req.from] {
+        auto eraseInfo = [w, id = req.id, deviceId] {
             if (auto shared = w.lock()) {
                 std::lock_guard<std::mutex> lk(shared->infosMtx_);
-                shared->infos_.erase({from, id});
+                shared->infos_.erase({deviceId, id});
             }
         };
 
         ice_config.tcpEnable = true;
-        ice_config.onInitDone = [w, req, eraseInfo](bool ok) {
+        ice_config.onInitDone = [w, req, deviceId, eraseInfo](bool ok) {
             auto shared = w.lock();
             if (!shared)
                 return;
             if (!ok) {
                 JAMI_ERR("Cannot initialize ICE session.");
                 if (shared->connReadyCb_)
-                    shared->connReadyCb_(req.from, "", nullptr);
+                    shared->connReadyCb_(deviceId, "", nullptr);
                 runOnMainThread([eraseInfo = std::move(eraseInfo)] { eraseInfo(); });
                 return;
             }
@@ -881,14 +886,14 @@ ConnectionManager::Impl::onDhtPeerRequest(const PeerConnectionRequest& req,
             });
         };
 
-        ice_config.onNegoDone = [w, req, eraseInfo](bool ok) {
+        ice_config.onNegoDone = [w, req, eraseInfo, deviceId](bool ok) {
             auto shared = w.lock();
             if (!shared)
                 return;
             if (!ok) {
                 JAMI_ERR("ICE negotiation failed");
                 if (shared->connReadyCb_)
-                    shared->connReadyCb_(req.from, "", nullptr);
+                    shared->connReadyCb_(deviceId, "", nullptr);
                 runOnMainThread([eraseInfo = std::move(eraseInfo)] { eraseInfo(); });
                 return;
             }
@@ -903,11 +908,11 @@ ConnectionManager::Impl::onDhtPeerRequest(const PeerConnectionRequest& req,
         auto info = std::make_shared<ConnectionInfo>();
         {
             std::lock_guard<std::mutex> lk(shared->infosMtx_);
-            shared->infos_[{req.from, req.id}] = info;
+            shared->infos_[{deviceId, req.id}] = info;
         }
         JAMI_INFO("[Account:%s] accepting connection from %s",
                   shared->account.getAccountID().c_str(),
-                  deviceId.c_str());
+                  deviceId.toString().c_str());
         std::unique_lock<std::mutex> lk {info->mutex_};
         ice_config.streamsCount = JamiAccount::ICE_STREAMS_COUNT;
         ice_config.compCountPerStream = JamiAccount::ICE_COMP_COUNT_PER_STREAM;
@@ -918,7 +923,7 @@ ConnectionManager::Impl::onDhtPeerRequest(const PeerConnectionRequest& req,
         if (not info->ice_) {
             JAMI_ERR("Cannot initialize ICE session.");
             if (shared->connReadyCb_)
-                shared->connReadyCb_(req.from, "", nullptr);
+                shared->connReadyCb_(deviceId, "", nullptr);
             eraseInfo();
         }
     });
@@ -946,7 +951,7 @@ ConnectionManager::Impl::addNewMultiplexedSocket(const DeviceId& deviceId, const
         });
     info->socket_->onShutdown([w = weak(), deviceId, vid]() {
         // Cancel current outgoing connections
-        dht::ThreadPool::io().run([w, deviceId = dht::InfoHash(deviceId), vid] {
+        dht::ThreadPool::io().run([w, deviceId, vid] {
             auto sthis = w.lock();
             if (!sthis)
                 return;
@@ -1045,9 +1050,9 @@ ConnectionManager::closeConnectionsWith(const DeviceId& deviceId)
 }
 
 void
-ConnectionManager::onDhtConnected(const DeviceId& deviceId)
+ConnectionManager::onDhtConnected(const dht::crypto::PublicKey& devicePk)
 {
-    pimpl_->onDhtConnected(deviceId);
+    pimpl_->onDhtConnected(devicePk);
 }
 
 void
diff --git a/src/jamidht/connectionmanager.h b/src/jamidht/connectionmanager.h
index 8f2c649284908ff02de0ec0daa724dfefbc2e33f..7a7c95c5769ea7ac399f760b0eeb407c16dda7ae 100644
--- a/src/jamidht/connectionmanager.h
+++ b/src/jamidht/connectionmanager.h
@@ -114,7 +114,7 @@ public:
      * Method to call to listen to incoming requests
      * @param deviceId      Account's device
      */
-    void onDhtConnected(const DeviceId& deviceId);
+    void onDhtConnected(const dht::crypto::PublicKey& devicePk);
 
     /**
      * Add a callback to decline or accept incoming ICE connections
diff --git a/src/jamidht/contact_list.cpp b/src/jamidht/contact_list.cpp
index 36f5ba6c7de03153b0afeb2dd9f1c7272f557972..de114ca5e07c9837ac716f2243fbf80d930079e2 100644
--- a/src/jamidht/contact_list.cpp
+++ b/src/jamidht/contact_list.cpp
@@ -257,7 +257,7 @@ ContactList::loadTrustRequests()
 
 bool
 ContactList::onTrustRequest(const dht::InfoHash& peer_account,
-                            const dht::InfoHash& peer_device,
+                            const std::shared_ptr<dht::crypto::PublicKey>& peer_device,
                             time_t received,
                             bool confirm,
                             const std::string& conversationId,
@@ -383,38 +383,52 @@ ContactList::discardTrustRequest(const dht::InfoHash& from)
 void
 ContactList::loadKnownDevices()
 {
-    std::map<dht::InfoHash, std::pair<std::string, uint64_t>> knownDevices;
     try {
         // read file
-        auto file = fileutils::loadFile("knownDevicesNames", path_);
+        auto file = fileutils::loadFile("knownDevices", path_);
         // load values
         msgpack::object_handle oh = msgpack::unpack((const char*) file.data(), file.size());
+
+        std::map<dht::PkId, std::pair<std::string, uint64_t>> knownDevices;
         oh.get().convert(knownDevices);
+        for (const auto& d : knownDevices) {
+            /*JAMI_DBG("[Contacts] loading known account device %s %s",
+                    d.second.first.c_str(),
+                    d.first.toString().c_str());*/
+            if (auto crt = tls::CertificateStore::instance().getCertificate(d.first.toString())) {
+                if (not foundAccountDevice(crt, d.second.first, clock::from_time_t(d.second.second)))
+                    JAMI_WARN("[Contacts] can't add device %s", d.first.toString().c_str());
+            } else {
+                JAMI_WARN("[Contacts] can't find certificate for device %s", d.first.toString().c_str());
+            }
+        }
     } catch (const std::exception& e) {
-        JAMI_WARN("[Contacts] error loading devices: %s", e.what());
-        return;
-    }
-
-    for (const auto& d : knownDevices) {
-        /*JAMI_DBG("[Contacts] loading known account device %s %s",
-                 d.second.first.c_str(),
-                 d.first.toString().c_str());*/
-        if (auto crt = tls::CertificateStore::instance().getCertificate(d.first.toString())) {
-            if (not foundAccountDevice(crt, d.second.first, clock::from_time_t(d.second.second)))
-                JAMI_WARN("[Contacts] can't add device %s", d.first.toString().c_str());
-        } else {
-            JAMI_WARN("[Contacts] can't find certificate for device %s", d.first.toString().c_str());
+        // Legacy fallback
+        try {
+            auto file = fileutils::loadFile("knownDevicesNames", path_);
+            msgpack::object_handle oh = msgpack::unpack((const char*) file.data(), file.size());
+            std::map<dht::InfoHash, std::pair<std::string, uint64_t>> knownDevices;
+            oh.get().convert(knownDevices);
+            for (const auto& d : knownDevices) {
+                if (auto crt = tls::CertificateStore::instance().getCertificate(d.first.toString())) {
+                    if (not foundAccountDevice(crt, d.second.first, clock::from_time_t(d.second.second)))
+                        JAMI_WARN("[Contacts] can't add device %s", d.first.toString().c_str());
+                }
+            }
+        } catch (const std::exception& e) {
+            JAMI_WARN("[Contacts] error loading devices: %s", e.what());
         }
+        return;
     }
 }
 
 void
 ContactList::saveKnownDevices() const
 {
-    std::ofstream file(path_ + DIR_SEPARATOR_STR "knownDevicesNames",
+    std::ofstream file(path_ + DIR_SEPARATOR_STR "knownDevices",
                        std::ios::trunc | std::ios::binary);
 
-    std::map<dht::InfoHash, std::pair<std::string, uint64_t>> devices;
+    std::map<dht::PkId, std::pair<std::string, uint64_t>> devices;
     for (const auto& id : knownDevices_)
         devices.emplace(id.first,
                         std::make_pair(id.second.name, clock::to_time_t(id.second.last_sync)));
@@ -423,7 +437,7 @@ ContactList::saveKnownDevices() const
 }
 
 void
-ContactList::foundAccountDevice(const dht::InfoHash& device,
+ContactList::foundAccountDevice(const dht::PkId& device,
                                 const std::string& name,
                                 const time_point& updated)
 {
@@ -454,7 +468,7 @@ ContactList::foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>&
     if (not crt)
         return false;
 
-    auto id = crt->getId();
+    auto id = crt->getLongId();
 
     // match certificate chain
     auto verifyResult = accountTrust_.verify(*crt);
@@ -472,18 +486,9 @@ ContactList::foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>&
         tls::CertificateStore::instance().pinCertificate(crt);
         if (crt->ocspResponse) {
             unsigned int status = crt->ocspResponse->getCertificateStatus();
-            if (status == GNUTLS_OCSP_CERT_GOOD) {
-                JAMI_DBG("Certificate %s has good OCSP status", id.to_c_str());
-                trust_.setCertificateStatus(id.toString(),
-                                            tls::TrustStore::PermissionStatus::ALLOWED);
-            } else if (status == GNUTLS_OCSP_CERT_REVOKED) {
+            if (status == GNUTLS_OCSP_CERT_REVOKED) {
                 JAMI_ERR("Certificate %s has revoked OCSP status", id.to_c_str());
-                trust_.setCertificateStatus(id.toString(),
-                                            tls::TrustStore::PermissionStatus::BANNED);
-            } else {
-                JAMI_ERR("Certificate %s has unknown OCSP status", id.to_c_str());
-                trust_.setCertificateStatus(id.toString(),
-                                            tls::TrustStore::PermissionStatus::UNDEFINED);
+                trust_.setCertificateStatus(crt, tls::TrustStore::PermissionStatus::BANNED, false);
             }
         }
         saveKnownDevices();
@@ -501,7 +506,7 @@ ContactList::foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>&
 }
 
 bool
-ContactList::removeAccountDevice(const dht::InfoHash& device)
+ContactList::removeAccountDevice(const dht::PkId& device)
 {
     if (knownDevices_.erase(device) > 0) {
         saveKnownDevices();
@@ -511,7 +516,7 @@ ContactList::removeAccountDevice(const dht::InfoHash& device)
 }
 
 void
-ContactList::setAccountDeviceName(const dht::InfoHash& device, const std::string& name)
+ContactList::setAccountDeviceName(const dht::PkId& device, const std::string& name)
 {
     auto dev = knownDevices_.find(device);
     if (dev != knownDevices_.end()) {
@@ -523,7 +528,7 @@ ContactList::setAccountDeviceName(const dht::InfoHash& device, const std::string
 }
 
 std::string
-ContactList::getAccountDeviceName(const dht::InfoHash& device) const
+ContactList::getAccountDeviceName(const dht::PkId& device) const
 {
     auto dev = knownDevices_.find(device);
     if (dev != knownDevices_.end()) {
@@ -564,13 +569,15 @@ ContactList::getSyncData() const
     }
 
     for (const auto& dev : knownDevices_) {
-        sync_data.devices_known.emplace(dev.first, dev.second.name);
+        sync_data.devices.emplace(dev.second.certificate->getLongId(), KnownDeviceSync {
+            dev.second.name, dev.second.certificate->getId()
+        });
     }
     return sync_data;
 }
 
 bool
-ContactList::syncDevice(const dht::InfoHash& device, const time_point& syncDate)
+ContactList::syncDevice(const dht::PkId& device, const time_point& syncDate)
 {
     auto it = knownDevices_.find(device);
     if (it == knownDevices_.end()) {
diff --git a/src/jamidht/contact_list.h b/src/jamidht/contact_list.h
index d394634724db1f2daacea995e6422dc07b212a2f..7fddb6196423bafe1f7c6f6f4b4d233f39c9b1e0 100644
--- a/src/jamidht/contact_list.h
+++ b/src/jamidht/contact_list.h
@@ -44,7 +44,7 @@ public:
         void(const std::string&, const std::string&, const std::vector<uint8_t>&, time_t)>;
     using OnAcceptConversation = std::function<void(const std::string&)>;
     using OnConfirmation = std::function<void(const std::string&, const std::string&)>;
-    using OnDevicesChanged = std::function<void(const std::map<dht::InfoHash, KnownDevice>&)>;
+    using OnDevicesChanged = std::function<void(const std::map<dht::PkId, KnownDevice>&)>;
 
     struct OnChangeCallback
     {
@@ -74,6 +74,7 @@ public:
 
     bool setCertificateStatus(const std::string& cert_id,
                               const tls::TrustStore::PermissionStatus status);
+
     bool setCertificateStatus(const std::shared_ptr<crypto::Certificate>& cert,
                               tls::TrustStore::PermissionStatus status,
                               bool local = true);
@@ -112,7 +113,7 @@ public:
     /** Inform of a new contact request. Returns true if the request should be immediatly accepted
      * (already a contact) */
     bool onTrustRequest(const dht::InfoHash& peer_account,
-                        const dht::InfoHash& peer_device,
+                        const std::shared_ptr<dht::crypto::PublicKey>& peer_device,
                         time_t received,
                         bool confirm,
                         const std::string& conversationId,
@@ -127,26 +128,28 @@ public:
     void saveTrustRequests() const;
 
     /* Devices */
-    const std::map<dht::InfoHash, KnownDevice>& getKnownDevices() const { return knownDevices_; }
-    void foundAccountDevice(const dht::InfoHash& device,
+    const std::map<dht::PkId, KnownDevice>& getKnownDevices() const { return knownDevices_; }
+    void foundAccountDevice(const dht::PkId& device,
                             const std::string& name = {},
                             const time_point& last_sync = time_point::min());
     bool foundAccountDevice(const std::shared_ptr<dht::crypto::Certificate>& crt,
                             const std::string& name = {},
                             const time_point& last_sync = time_point::min());
-    bool removeAccountDevice(const dht::InfoHash& device);
-    void setAccountDeviceName(const dht::InfoHash& device, const std::string& name);
-    std::string getAccountDeviceName(const dht::InfoHash& device) const;
+    bool removeAccountDevice(const dht::PkId& device);
+    void setAccountDeviceName(const dht::PkId& device, const std::string& name);
+    std::string getAccountDeviceName(const dht::PkId& device) const;
 
     DeviceSync getSyncData() const;
-    bool syncDevice(const dht::InfoHash& device, const time_point& syncDate);
+    bool syncDevice(const dht::PkId& device, const time_point& syncDate);
     // void onSyncData(DeviceSync&& device);
 
 private:
     mutable std::mutex lock;
     std::map<dht::InfoHash, Contact> contacts_;
     std::map<dht::InfoHash, TrustRequest> trustRequests_;
-    std::map<dht::InfoHash, KnownDevice> knownDevices_;
+    std::map<dht::InfoHash, KnownDevice> knownDevicesLegacy_;
+
+    std::map<dht::PkId, KnownDevice> knownDevices_;
 
     // Trust store with account main certificate as the only CA
     dht::crypto::TrustList accountTrust_;
diff --git a/src/jamidht/conversationrepository.cpp b/src/jamidht/conversationrepository.cpp
index 28455dbd50b4aaa838d3cae9283f155bbca63a39..1442f507a4b49504d2e5de7a4978796a937295ff 100644
--- a/src/jamidht/conversationrepository.cpp
+++ b/src/jamidht/conversationrepository.cpp
@@ -238,7 +238,7 @@ add_initial_files(GitRepository& repo,
     }
 
     // /devices
-    std::string devicePath = devicesPath + "/" + cert->getId().toString() + ".crt";
+    std::string devicePath = devicesPath + "/" + deviceId + ".crt";
     file = fileutils::ofstream(devicePath, std::ios::trunc | std::ios::binary);
     if (!file.is_open()) {
         JAMI_ERR("Could not write data to %s", devicePath.c_str());
diff --git a/src/jamidht/jami_contact.h b/src/jamidht/jami_contact.h
index 357da962b2455a5eed73a26efe6130821f46f36a..2b3658d43182d9076c8de8fd1a1d40211405b36a 100644
--- a/src/jamidht/jami_contact.h
+++ b/src/jamidht/jami_contact.h
@@ -126,7 +126,7 @@ struct Contact
 
 struct TrustRequest
 {
-    dht::InfoHash device;
+    std::shared_ptr<dht::crypto::PublicKey> device;
     std::string conversationId;
     time_t received;
     std::vector<uint8_t> payload;
@@ -141,7 +141,14 @@ private:
 public:
     static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA;
     dht::InfoHash dev;
-    MSGPACK_DEFINE_MAP(dev);
+    std::shared_ptr<dht::crypto::PublicKey> pk;
+    MSGPACK_DEFINE_MAP(dev, pk)
+};
+
+struct KnownDeviceSync {
+    std::string name;
+    dht::InfoHash sha1;
+    MSGPACK_DEFINE_MAP(name, sha1)
 };
 
 struct DeviceSync : public dht::EncryptedValue<DeviceSync>
@@ -149,10 +156,11 @@ struct DeviceSync : public dht::EncryptedValue<DeviceSync>
     static const constexpr dht::ValueType& TYPE = dht::ValueType::USER_DATA;
     uint64_t date;
     std::string device_name;
-    std::map<dht::InfoHash, std::string> devices_known;
+    std::map<dht::InfoHash, std::string> devices_known; // Legacy
+    std::map<dht::PkId, KnownDeviceSync> devices;
     std::map<dht::InfoHash, Contact> peers;
     std::map<dht::InfoHash, TrustRequest> trust_requests;
-    MSGPACK_DEFINE_MAP(date, device_name, devices_known, peers, trust_requests)
+    MSGPACK_DEFINE_MAP(date, device_name, devices_known, devices, peers, trust_requests)
 };
 
 struct KnownDevice
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index d384a7be354d6cf326c217694dca49276eb8d602..d60053bd37c74b9f8a78ff914dee4b880306bcb3 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -212,7 +212,7 @@ struct JamiAccount::PendingConversationFetch
 
 struct JamiAccount::PendingMessage
 {
-    std::set<dht::InfoHash> to;
+    std::set<DeviceId> to;
 };
 
 struct AccountPeerInfo
@@ -677,15 +677,17 @@ JamiAccount::startOutgoingCall(const std::shared_ptr<SIPCall>& call, const std::
     // Find listening devices for this account
     accountManager_->forEachDevice(
         peer_account,
-        [this, devices = std::move(devices), sendRequest](const DeviceId& dev) {
+        [this, devices = std::move(devices), sendRequest](
+            const std::shared_ptr<dht::crypto::PublicKey>& dev) {
             // Test if already sent via a SIP transport
-            if (devices.find(dev) != devices.end())
+            auto deviceId = dev->getLongId();
+            if (devices.find(deviceId) != devices.end())
                 return;
             {
                 std::lock_guard<std::mutex> lk(onConnectionClosedMtx_);
-                onConnectionClosed_[dev] = sendRequest;
+                onConnectionClosed_[deviceId] = sendRequest;
             }
-            sendRequest(dev, false);
+            sendRequest(deviceId, false);
         },
         [wCall](bool ok) {
             if (not ok) {
@@ -1177,7 +1179,7 @@ JamiAccount::loadAccount(const std::string& archive_password,
                                                                                    reqMap);
             }
         },
-        [this](const std::map<dht::InfoHash, KnownDevice>& devices) {
+        [this](const std::map<DeviceId, KnownDevice>& devices) {
             std::map<std::string, std::string> ids;
             for (auto& d : devices) {
                 auto id = d.first.toString();
@@ -1927,9 +1929,21 @@ JamiAccount::trackPresence(const dht::InfoHash& h, BuddyInfo& buddy)
                               }
                           }
                       }
-                      if (needsSync)
-                          sthis->requestSIPConnection(h.toString(),
-                                                      dev.dev); // Both sides will sync conversations
+                      if (needsSync) {
+                          if (dev.pk) {
+                              sthis->requestSIPConnection(h.toString(), dev.pk->getLongId());
+                          } else {
+                              sthis->findCertificate(
+                                  dev.dev,
+                                  [sthis, h](const std::shared_ptr<dht::crypto::Certificate>& cert) {
+                                      if (cert) {
+                                          auto pk = std::make_shared<dht::crypto::PublicKey>(
+                                              cert->getPublicKey());
+                                          sthis->requestSIPConnection(h.toString(), pk->getLongId());
+                                      }
+                                  });
+                          }
+                      }
                   }
                   if (isConnected and not wasConnected) {
                       sthis->onTrackedBuddyOnline(h);
@@ -1985,7 +1999,7 @@ JamiAccount::onTrackedBuddyOffline(const dht::InfoHash& contactId)
 }
 
 void
-JamiAccount::syncConversations(const std::string& peer, const std::string& deviceId)
+JamiAccount::syncConversations(const std::string& peer, const DeviceId& deviceId)
 {
     // Sync conversations where peer is member
     std::set<std::string> toFetch;
@@ -2171,7 +2185,7 @@ JamiAccount::doRegister_()
                 [this](const std::shared_ptr<dht::crypto::Certificate>& crt) {
                     if (!crt)
                         return;
-                    auto deviceId = crt->getId().toString();
+                    auto deviceId = crt->getLongId().toString();
                     if (accountManager_->getInfo()->deviceId == deviceId)
                         return;
 
@@ -2179,7 +2193,7 @@ JamiAccount::doRegister_()
                     if (!connectionManager_)
                         connectionManager_ = std::make_unique<ConnectionManager>(*this);
                     auto channelName = "sync://" + deviceId;
-                    if (connectionManager_->isConnecting(crt->getId(), channelName)) {
+                    if (connectionManager_->isConnecting(crt->getLongId(), channelName)) {
                         JAMI_INFO("[Account %s] Already connecting to %s",
                                   getAccountID().c_str(),
                                   deviceId.c_str());
@@ -2190,7 +2204,7 @@ JamiAccount::doRegister_()
                                                       [this](std::shared_ptr<ChannelSocket> socket,
                                                              const DeviceId& deviceId) {
                                                           if (socket)
-                                                              syncWith(deviceId.toString(), socket);
+                                                              syncWith(deviceId, socket);
                                                       });
                 },
                 [this] {
@@ -2211,7 +2225,7 @@ JamiAccount::doRegister_()
         std::unique_lock<std::mutex> lkCM(connManagerMtx_);
         if (!connectionManager_)
             connectionManager_ = std::make_unique<ConnectionManager>(*this);
-        connectionManager_->onDhtConnected(DeviceId(accountManager_->getInfo()->deviceId));
+        connectionManager_->onDhtConnected(*accountManager_->getInfo()->devicePk);
         connectionManager_->onICERequest([this](const DeviceId& deviceId) {
             std::promise<bool> accept;
             std::future<bool> fut = accept.get_future();
@@ -2358,9 +2372,17 @@ JamiAccount::doRegister_()
                     auto sep = name.find_last_of('/');
                     auto conversationId = name.substr(sep + 1);
                     auto remoteDevice = name.substr(6, sep - 6);
-                    auto currentDevice = currentDeviceId();
-                    if (remoteDevice != currentDevice || currentDevice == deviceId.to_c_str()) {
-                        // Check if wanted remote it's our side (git://removeDevice/conversationId)
+
+                    auto isServer = false;
+                    if (!DeviceId(remoteDevice)) {
+                        // This means that the remoteDevice is a short Id, so with a non up-to-date client
+                        isServer = remoteDevice
+                                   == accountManager_->getInfo()->devicePk->getId().toString();
+                    } else {
+                        isServer = remoteDevice == currentDeviceId();
+                    }
+                    if (!isServer || currentDeviceId() == deviceId.to_c_str()) {
+                        // Check if wanted remote it's our side (git://remoteDevice/conversationId)
                         return;
                     }
                     JAMI_WARN("[Account %s] New channel asked from %s with name %s",
@@ -2390,7 +2412,7 @@ JamiAccount::doRegister_()
                         }
                     }
 
-                    auto sock = gitSocket(deviceId.toString(), conversationId);
+                    auto sock = gitSocket(deviceId, conversationId);
                     if (sock != std::nullopt && sock->lock() == channel) {
                         // The onConnectionReady is already used as client (for retrieving messages)
                         // So it's not the server socket
@@ -2492,29 +2514,38 @@ JamiAccount::doRegister_()
         lkCM.unlock();
 
         // Note: this code should be unused unless for DHT text messages
-        auto inboxDeviceKey = dht::InfoHash::get("inbox:" + accountManager_->getInfo()->deviceId);
+        auto inboxDeviceKey = dht::InfoHash::get(
+            "inbox:" + accountManager_->getInfo()->devicePk->getId().toString());
         dht_->listen<dht::ImMessage>(inboxDeviceKey, [this, inboxDeviceKey](dht::ImMessage&& v) {
             auto msgId = to_hex_string(v.id);
             if (isMessageTreated(msgId))
                 return true;
-            accountManager_->onPeerMessage(
-                v.from,
-                dhtPublicInCalls_,
-                [this, v, inboxDeviceKey, msgId](const std::shared_ptr<dht::crypto::Certificate>&,
-                                                 const dht::InfoHash& peer_account) {
-                    auto now = clock::to_time_t(clock::now());
-                    std::string datatype = utf8_make_valid(v.datatype);
-                    if (datatype.empty()) {
-                        datatype = "text/plain";
-                    }
-                    std::map<std::string, std::string> payloads = {
-                        {datatype, utf8_make_valid(v.msg)}};
-                    onTextMessage(msgId, peer_account.toString(), payloads);
-                    JAMI_DBG() << "Sending message confirmation " << v.id;
-                    dht_->putEncrypted(inboxDeviceKey,
-                                       v.from,
-                                       dht::ImMessage(v.id, std::string(), now));
-                });
+            accountManager_
+                ->onPeerMessage(*v.owner,
+                                dhtPublicInCalls_,
+                                [this,
+                                 v,
+                                 inboxDeviceKey,
+                                 msgId](const std::shared_ptr<dht::crypto::Certificate>& cert,
+                                        const dht::InfoHash& peer_account) {
+                                    auto now = clock::to_time_t(clock::now());
+                                    std::string datatype = utf8_make_valid(v.datatype);
+                                    if (datatype.empty()) {
+                                        datatype = "text/plain";
+                                    }
+                                    std::map<std::string, std::string> payloads = {
+                                        {datatype, utf8_make_valid(v.msg)}};
+                                    auto pk = std::make_shared<dht::crypto::PublicKey>(
+                                        cert->getPublicKey());
+                                    onTextMessage(msgId,
+                                                  peer_account.toString(),
+                                                  pk->getLongId().toString(),
+                                                  payloads);
+                                    JAMI_DBG() << "Sending message confirmation " << v.id;
+                                    dht_->putEncrypted(inboxDeviceKey,
+                                                       v.from,
+                                                       dht::ImMessage(v.id, std::string(), now));
+                                });
             return true;
         });
 
@@ -2535,11 +2566,12 @@ JamiAccount::doRegister_()
 void
 JamiAccount::onTextMessage(const std::string& id,
                            const std::string& from,
+                           const std::string& deviceId,
                            const std::map<std::string, std::string>& payloads)
 {
     try {
         const std::string fromUri {parseJamiUri(from)};
-        SIPAccountBase::onTextMessage(id, fromUri, payloads);
+        SIPAccountBase::onTextMessage(id, fromUri, deviceId, payloads);
     } catch (...) {
     }
 }
@@ -2651,6 +2683,15 @@ JamiAccount::findCertificate(
     return false;
 }
 
+bool
+JamiAccount::findCertificate(
+    const dht::PkId& id, std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb)
+{
+    if (accountManager_)
+        return accountManager_->findCertificate(id, std::move(cb));
+    return false;
+}
+
 bool
 JamiAccount::findCertificate(const std::string& crt_id)
 {
@@ -2767,7 +2808,7 @@ JamiAccount::getKnownDevices() const
     if (not accountManager_ or not accountManager_->getInfo())
         return {};
     std::map<std::string, std::string> ids;
-    for (auto& d : accountManager_->getKnownDevices()) {
+    for (const auto& d : accountManager_->getKnownDevices()) {
         auto id = d.first.toString();
         auto label = d.second.name.empty() ? id.substr(0, 8) : d.second.name;
         ids.emplace(std::move(id), std::move(label));
@@ -3166,7 +3207,7 @@ JamiAccount::sendTrustRequest(const std::string& to, const std::vector<uint8_t>&
 
 void
 JamiAccount::forEachDevice(const dht::InfoHash& to,
-                           std::function<void(const dht::InfoHash&)>&& op,
+                           std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
                            std::function<void(bool)>&& end)
 {
     accountManager_->forEachDevice(to, std::move(op), std::move(end));
@@ -3304,24 +3345,26 @@ JamiAccount::sendTextMessage(const std::string& to,
     // Find listening devices for this account
     accountManager_->forEachDevice(
         toH,
-        [this, confirm, to, token, payloads, now, devices](const dht::InfoHash& dev) {
+        [this, confirm, to, token, payloads, now, devices](
+            const std::shared_ptr<dht::crypto::PublicKey>& dev) {
             // Test if already sent
-            if (devices->find(dev) != devices->end()) {
+            auto deviceId = dev->getLongId();
+            if (devices->find(deviceId) != devices->end()) {
                 return;
             }
-            if (dev.toString() == currentDeviceId()) {
-                devices->emplace(dev);
+            if (deviceId.toString() == currentDeviceId()) {
+                devices->emplace(deviceId);
                 return;
             }
 
             // Else, ask for a channel and send a DHT message
-            requestSIPConnection(to, dev);
+            requestSIPConnection(to, deviceId);
             {
                 std::lock_guard<std::mutex> lock(messageMutex_);
-                sentMessages_[token].to.emplace(dev);
+                sentMessages_[token].to.emplace(deviceId);
             }
 
-            auto h = dht::InfoHash::get("inbox:" + dev.toString());
+            auto h = dht::InfoHash::get("inbox:" + dev->getId().toString());
             std::lock_guard<std::mutex> l(confirm->lock);
             auto list_token
                 = dht_->listen<dht::ImMessage>(h, [this, to, token, confirm](dht::ImMessage&& msg) {
@@ -3333,7 +3376,7 @@ JamiAccount::sendTextMessage(const std::string& to,
                           std::lock_guard<std::mutex> lock(messageMutex_);
                           auto e = sentMessages_.find(msg.id);
                           if (e == sentMessages_.end()
-                              or e->second.to.find(msg.from) == e->second.to.end()) {
+                              or e->second.to.find(msg.owner->getLongId()) == e->second.to.end()) {
                               JAMI_DBG() << "[Account " << getAccountID() << "] [message " << token
                                          << "] Message not found";
                               return true;
@@ -3387,7 +3430,7 @@ JamiAccount::sendTextMessage(const std::string& to,
                                });
 
             JAMI_DBG() << "[Account " << getAccountID() << "] [message " << token
-                       << "] Sending message for device " << dev.toString();
+                       << "] Sending message for device " << deviceId.toString();
         },
         [this, to, token, devices, confirm](bool ok) {
             if (devices->size() == 1 && devices->begin()->toString() == currentDeviceId()) {
@@ -3691,29 +3734,32 @@ JamiAccount::acceptConversationRequest(const std::string& conversationId)
         JAMI_WARN("Invalid member detected: %s", request->from.c_str());
         return;
     }
-    forEachDevice(memberHash, [this, request = *request](const dht::InfoHash& dev) {
-        if (dev == dht()->getId())
-            return;
-        connectionManager().connectDevice(
-            dev,
-            "git://" + dev.toString() + "/" + request.conversationId,
-            [this, request](std::shared_ptr<ChannelSocket> socket, const DeviceId& dev) {
-                if (socket) {
-                    std::unique_lock<std::mutex> lk(pendingConversationsFetchMtx_);
-                    auto& pending = pendingConversationsFetch_[request.conversationId];
-                    if (!pending.ready) {
-                        pending.ready = true;
-                        pending.deviceId = dev.toString();
-                        lk.unlock();
-                        // Save the git socket
-                        addGitSocket(dev.toString(), request.conversationId, socket);
-                    } else {
-                        lk.unlock();
-                        socket->shutdown();
-                    }
-                }
-            });
-    });
+    forEachDevice(memberHash,
+                  [this, request = *request](const std::shared_ptr<dht::crypto::PublicKey>& dev) {
+                      auto deviceId = dev->getLongId();
+                      if (deviceId == dht()->getPublicKey()->getLongId())
+                          return;
+                      connectionManager().connectDevice(
+                          deviceId,
+                          "git://" + deviceId.toString() + "/" + request.conversationId,
+                          [this, request](std::shared_ptr<ChannelSocket> socket,
+                                          const DeviceId& dev) {
+                              if (socket) {
+                                  std::unique_lock<std::mutex> lk(pendingConversationsFetchMtx_);
+                                  auto& pending = pendingConversationsFetch_[request.conversationId];
+                                  if (!pending.ready) {
+                                      pending.ready = true;
+                                      pending.deviceId = dev.toString();
+                                      lk.unlock();
+                                      // Save the git socket
+                                      addGitSocket(dev, request.conversationId, socket);
+                                  } else {
+                                      lk.unlock();
+                                      socket->shutdown();
+                                  }
+                              }
+                          });
+                  });
     accountManager_->rmConversationRequest(conversationId);
     ConvInfo info;
     info.id = conversationId;
@@ -4206,7 +4252,7 @@ JamiAccount::onNewGitCommit(const std::string& peer,
              peer.c_str(),
              conversationId.c_str(),
              commitId.c_str());
-    fetchNewCommits(peer, deviceId, conversationId, commitId);
+    fetchNewCommits(peer, DeviceId(deviceId), conversationId, commitId);
 }
 
 void
@@ -4223,14 +4269,14 @@ JamiAccount::onMessageDisplayed(const std::string& peer,
 
 void
 JamiAccount::fetchNewCommits(const std::string& peer,
-                             const std::string& deviceId,
+                             const DeviceId& deviceId,
                              const std::string& conversationId,
                              const std::string& commitId)
 {
     JAMI_DBG("[Account %s] fetch commits for peer %s on device %s",
              getAccountID().c_str(),
              peer.c_str(),
-             deviceId.c_str());
+             deviceId.to_c_str());
 
     std::unique_lock<std::mutex> lk(conversationsMtx_);
     auto conversation = conversations_.find(conversationId);
@@ -4242,10 +4288,10 @@ JamiAccount::fetchNewCommits(const std::string& peer,
                       conversationId.c_str());
             return;
         }
-        if (conversation->second->isBanned(deviceId)) {
+        if (conversation->second->isBanned(deviceId.toString())) {
             JAMI_WARN("[Account %s] %s is a banned device in conversation %s",
                       getAccountID().c_str(),
-                      deviceId.c_str(),
+                      deviceId.to_c_str(),
                       conversationId.c_str());
             return;
         }
@@ -4260,7 +4306,7 @@ JamiAccount::fetchNewCommits(const std::string& peer,
         if (hasGitSocket(deviceId, conversationId)) {
             conversation->second->sync(
                 peer,
-                deviceId,
+                deviceId.toString(),
                 [peer, deviceId, conversationId, commitId, w = weak()](bool ok) {
                     auto shared = w.lock();
                     if (!shared)
@@ -4269,12 +4315,12 @@ JamiAccount::fetchNewCommits(const std::string& peer,
                         JAMI_WARN("[Account %s] Could not fetch new commit from %s for %s, other "
                                   "peer may be disconnected",
                                   shared->getAccountID().c_str(),
-                                  deviceId.c_str(),
+                                  deviceId.to_c_str(),
                                   conversationId.c_str());
                         shared->removeGitSocket(deviceId, conversationId);
                         JAMI_INFO("[Account %s] Relaunch sync with %s for %s",
                                   shared->getAccountID().c_str(),
-                                  deviceId.c_str(),
+                                  deviceId.to_c_str(),
                                   conversationId.c_str());
                         runOnMainThread([=]() {
                             if (auto shared = w.lock())
@@ -4294,8 +4340,8 @@ JamiAccount::fetchNewCommits(const std::string& peer,
             if (!connectionManager_)
                 return;
             connectionManager_->connectDevice(
-                DeviceId(deviceId),
-                "git://" + deviceId + "/" + conversationId,
+                deviceId,
+                "git://" + deviceId.toString() + "/" + conversationId,
                 [this, conversationId, commitId, peer](std::shared_ptr<ChannelSocket> socket,
                                                        const DeviceId& deviceId) {
                     dht::ThreadPool::io().run([w = weak(),
@@ -4312,7 +4358,7 @@ JamiAccount::fetchNewCommits(const std::string& peer,
                         if (!conversation->second)
                             return;
                         if (socket) {
-                            shared->addGitSocket(deviceId.toString(), conversationId, socket);
+                            shared->addGitSocket(deviceId, conversationId, socket);
 
                             conversation->second->sync(
                                 peer,
@@ -4327,7 +4373,7 @@ JamiAccount::fetchNewCommits(const std::string& peer,
                                                   shared->getAccountID().c_str(),
                                                   deviceId.to_c_str(),
                                                   conversationId.c_str());
-                                        shared->removeGitSocket(deviceId.toString(), conversationId);
+                                        shared->removeGitSocket(deviceId, conversationId);
                                     }
                                 },
                                 commitId);
@@ -4545,7 +4591,7 @@ JamiAccount::cacheTurnServers()
 void
 JamiAccount::callConnectionClosed(const DeviceId& deviceId, bool eraseDummy)
 {
-    std::function<void(const dht::InfoHash&, bool)> cb;
+    std::function<void(const DeviceId&, bool)> cb;
     {
         std::lock_guard<std::mutex> lk(onConnectionClosedMtx_);
         auto it = onConnectionClosed_.find(deviceId);
@@ -4561,7 +4607,7 @@ JamiAccount::callConnectionClosed(const DeviceId& deviceId, bool eraseDummy)
         }
     }
     dht::ThreadPool::io().run(
-        [w = weak(), cb = std::move(cb), id = std::move(deviceId), erase = std::move(eraseDummy)] {
+        [w = weak(), cb = std::move(cb), id = deviceId, erase = std::move(eraseDummy)] {
             if (auto acc = w.lock()) {
                 if (cb)
                     cb(id, erase);
@@ -4813,7 +4859,7 @@ JamiAccount::cacheSIPConnection(std::shared_ptr<ChannelSocket>&& socket,
 
     sendProfile(deviceId.toString());
 
-    syncConversations(peerId, deviceId.toString());
+    syncConversations(peerId, deviceId);
 
     // Retry messages
     messageEngine_.onPeerOnline(peerId);
@@ -4876,16 +4922,15 @@ JamiAccount::cacheSyncConnection(std::shared_ptr<ChannelSocket>&& socket,
                                  const std::string& peerId,
                                  const DeviceId& device)
 {
-    auto deviceId = device.toString();
     std::unique_lock<std::mutex> lk(syncConnectionsMtx_);
-    syncConnections_[deviceId].emplace_back(socket);
+    syncConnections_[device].emplace_back(socket);
 
-    socket->onShutdown([w = weak(), peerId, deviceId, socket]() {
+    socket->onShutdown([w = weak(), peerId, device, socket]() {
         auto shared = w.lock();
         if (!shared)
             return;
         std::lock_guard<std::mutex> lk(shared->syncConnectionsMtx_);
-        auto& connections = shared->syncConnections_[deviceId];
+        auto& connections = shared->syncConnections_[device];
         auto conn = connections.begin();
         while (conn != connections.end()) {
             if (*conn == socket)
@@ -4895,7 +4940,7 @@ JamiAccount::cacheSyncConnection(std::shared_ptr<ChannelSocket>&& socket,
         }
     });
 
-    socket->setOnRecv([this, deviceId, peerId](const uint8_t* buf, size_t len) {
+    socket->setOnRecv([this, deviceId = device, peerId](const uint8_t* buf, size_t len) {
         if (!buf)
             return len;
 
@@ -4968,7 +5013,7 @@ JamiAccount::cacheSyncConnection(std::shared_ptr<ChannelSocket>&& socket,
             JAMI_INFO("[Account %s] New request detected for conversation %s (device %s)",
                       getAccountID().c_str(),
                       convId.c_str(),
-                      deviceId.c_str());
+                      deviceId.to_c_str());
 
             emitSignal<DRing::ConversationSignal::ConversationRequestReceived>(getAccountID(),
                                                                                convId,
@@ -4980,7 +5025,7 @@ JamiAccount::cacheSyncConnection(std::shared_ptr<ChannelSocket>&& socket,
 }
 
 void
-JamiAccount::syncWith(const std::string& deviceId, const std::shared_ptr<ChannelSocket>& socket)
+JamiAccount::syncWith(const DeviceId& deviceId, const std::shared_ptr<ChannelSocket>& socket)
 {
     if (!socket)
         return;
@@ -5249,13 +5294,13 @@ JamiAccount::monitor() const
 }
 
 void
-JamiAccount::cloneConversation(const std::string& deviceId,
+JamiAccount::cloneConversation(const DeviceId& deviceId,
                                const std::string&,
                                const std::string& convId)
 {
     JAMI_DBG("[Account %s] Clone conversation on device %s",
              getAccountID().c_str(),
-             deviceId.c_str());
+             deviceId.to_c_str());
 
     if (!isConversation(convId)) {
         {
@@ -5273,32 +5318,32 @@ JamiAccount::cloneConversation(const std::string& deviceId,
         std::lock_guard<std::mutex> lkCM(connManagerMtx_);
         if (!connectionManager_)
             return;
-        connectionManager_
-            ->connectDevice(DeviceId(deviceId),
-                            "git://" + deviceId + "/" + convId,
-                            [this, convId](std::shared_ptr<ChannelSocket> socket,
-                                           const DeviceId& deviceId) {
-                                if (socket) {
-                                    std::unique_lock<std::mutex> lk(pendingConversationsFetchMtx_);
-                                    auto& pending = pendingConversationsFetch_[convId];
-                                    if (!pending.ready) {
-                                        pending.ready = true;
-                                        pending.deviceId = deviceId.toString();
-                                        lk.unlock();
-                                        // Save the git socket
-                                        addGitSocket(deviceId.toString(), convId, socket);
-                                        checkConversationsEvents();
-                                    } else {
-                                        lk.unlock();
-                                        socket->shutdown();
-                                    }
-                                }
-                            });
+        connectionManager_->connectDevice(deviceId,
+                                          fmt::format("git://{}/{}", deviceId, convId),
+                                          [this, convId](std::shared_ptr<ChannelSocket> socket,
+                                                         const DeviceId& deviceId) {
+                                              if (socket) {
+                                                  std::unique_lock<std::mutex> lk(
+                                                      pendingConversationsFetchMtx_);
+                                                  auto& pending = pendingConversationsFetch_[convId];
+                                                  if (!pending.ready) {
+                                                      pending.ready = true;
+                                                      pending.deviceId = deviceId.toString();
+                                                      lk.unlock();
+                                                      // Save the git socket
+                                                      addGitSocket(deviceId, convId, socket);
+                                                      checkConversationsEvents();
+                                                  } else {
+                                                      lk.unlock();
+                                                      socket->shutdown();
+                                                  }
+                                              }
+                                          });
 
         JAMI_INFO("[Account %s] New conversation detected: %s. Ask device %s to clone it",
                   getAccountID().c_str(),
                   convId.c_str(),
-                  deviceId.c_str());
+                  deviceId.to_c_str());
     } else {
         JAMI_INFO("[Account %s] Already have conversation %s",
                   getAccountID().c_str(),
@@ -5480,7 +5525,9 @@ JamiAccount::askForFileChannel(const std::string& conversationId,
         for (const auto& member : members) {
             accountManager_->forEachDevice(dht::InfoHash(member),
                                            [this, tryDevice = std::move(tryDevice)](
-                                               const DeviceId& dev) { tryDevice(dev); });
+                                               const std::shared_ptr<dht::crypto::PublicKey>& dev) {
+                                               tryDevice(dev->getLongId());
+                                           });
         }
     }
 }
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index 735b9b4a3ac5fe6870870c08cbe8006f2130346d..e994994bff41385ca95a4eaeeaae2ca51ca88292 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -89,7 +89,7 @@ class SipTransport;
 class ChanneledOutgoingTransfer;
 
 using SipConnectionKey = std::pair<std::string /* accountId */, DeviceId>;
-using GitSocketList = std::map<std::string,                            /* device Id */
+using GitSocketList = std::map<DeviceId,                               /* device Id */
                                std::map<std::string,                   /* conversation */
                                         std::shared_ptr<ChannelSocket> /* related socket */
                                         >>;
@@ -282,6 +282,7 @@ public:
 
     void onTextMessage(const std::string& id,
                        const std::string& from,
+                       const std::string& deviceId,
                        const std::map<std::string, std::string>& payloads) override;
 
     virtual bool isTlsEnabled() const override { return true; }
@@ -298,6 +299,9 @@ public:
     bool findCertificate(
         const dht::InfoHash& h,
         std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
+    bool findCertificate(
+        const dht::PkId& h,
+        std::function<void(const std::shared_ptr<dht::crypto::Certificate>&)>&& cb = {});
 
     /* contact requests */
     std::vector<std::map<std::string, std::string>> getTrustRequests() const;
@@ -397,7 +401,7 @@ public:
     const std::shared_future<tls::DhParams> dhParams() const { return dhParams_; }
 
     void forEachDevice(const dht::InfoHash& to,
-                       std::function<void(const dht::InfoHash&)>&& op,
+                       std::function<void(const std::shared_ptr<dht::crypto::PublicKey>&)>&& op,
                        std::function<void(bool)>&& end = {});
 
     /**
@@ -465,7 +469,7 @@ public:
      * ConnectionManager needs the account to exists
      */
     void shutdownConnections();
-    std::optional<std::weak_ptr<ChannelSocket>> gitSocket(const std::string& deviceId,
+    std::optional<std::weak_ptr<ChannelSocket>> gitSocket(const DeviceId& deviceId,
                                                           const std::string& conversationId) const
     {
         auto deviceSockets = gitSocketList_.find(deviceId);
@@ -478,12 +482,12 @@ public:
         }
         return socketIt->second;
     }
-    bool hasGitSocket(const std::string& deviceId, const std::string& conversationId) const
+    bool hasGitSocket(const DeviceId& deviceId, const std::string& conversationId) const
     {
         return gitSocket(deviceId, conversationId) != std::nullopt;
     }
 
-    void addGitSocket(const std::string& deviceId,
+    void addGitSocket(const DeviceId& deviceId,
                       const std::string& conversationId,
                       const std::shared_ptr<ChannelSocket>& socket)
     {
@@ -491,7 +495,7 @@ public:
         deviceSockets[conversationId] = socket;
     }
 
-    void removeGitSocket(const std::string& deviceId, const std::string& conversationId)
+    void removeGitSocket(const DeviceId& deviceId, const std::string& conversationId)
     {
         auto deviceSockets = gitSocketList_.find(deviceId);
         if (deviceSockets == gitSocketList_.end()) {
@@ -581,7 +585,7 @@ public:
      * @param commitId (optional)
      */
     void fetchNewCommits(const std::string& peer,
-                         const std::string& deviceId,
+                         const DeviceId& deviceId,
                          const std::string& conversationId,
                          const std::string& commitId = "");
 
@@ -598,7 +602,7 @@ public:
      * @param deviceId
      * @param convId
      */
-    void cloneConversation(const std::string& deviceId,
+    void cloneConversation(const DeviceId& deviceId,
                            const std::string& peer,
                            const std::string& convId);
 
@@ -730,7 +734,7 @@ private:
     /**
      * Sync conversations with detected peer
      */
-    void syncConversations(const std::string& peer, const std::string& deviceId);
+    void syncConversations(const std::string& peer, const DeviceId& deviceId);
 
     /**
      * Maps require port via UPnP and other async ops
@@ -950,8 +954,7 @@ private:
 
     // Sync connections
     std::mutex syncConnectionsMtx_;
-    std::map<std::string /* deviceId */, std::vector<std::shared_ptr<ChannelSocket>>>
-        syncConnections_;
+    std::map<DeviceId /* deviceId */, std::vector<std::shared_ptr<ChannelSocket>>> syncConnections_;
 
     /**
      * Ask a device to open a channeled SIP socket
@@ -1028,7 +1031,7 @@ private:
     void checkConversationsEvents();
     bool handlePendingConversations();
 
-    void syncWith(const std::string& deviceId, const std::shared_ptr<ChannelSocket>& socket);
+    void syncWith(const DeviceId& deviceId, const std::shared_ptr<ChannelSocket>& socket);
     void syncInfos(const std::shared_ptr<ChannelSocket>& socket);
     void syncWithConnected();
 
diff --git a/src/jamidht/multiplexed_socket.h b/src/jamidht/multiplexed_socket.h
index bbee47f4d67d41103fddc7f65a9c9f66c9932194..eaac36e6703f30ebc82737db944b5b1dfe3d1030 100644
--- a/src/jamidht/multiplexed_socket.h
+++ b/src/jamidht/multiplexed_socket.h
@@ -27,7 +27,7 @@ class IceTransport;
 class ChannelSocket;
 class TlsSocketEndpoint;
 
-using DeviceId = dht::InfoHash;
+using DeviceId = dht::PkId;
 using OnConnectionRequestCb = std::function<
     bool(const DeviceId& /* device id */, const uint16_t& /* id */, const std::string& /* name */)>;
 using OnConnectionReadyCb
diff --git a/src/jamidht/p2p.cpp b/src/jamidht/p2p.cpp
index 0966e596699786589985f263c028bef01a9eb687..452b255674204aa37549bb6b9d605a31664ba3a6 100644
--- a/src/jamidht/p2p.cpp
+++ b/src/jamidht/p2p.cpp
@@ -226,7 +226,7 @@ DhtPeerConnector::requestConnection(
     }
 
     std::string channelName = "file://" + std::to_string(tid);
-    std::vector<DeviceId> devices;
+    std::vector<dht::InfoHash> contacts;
     if (!info.conversationId.empty()) {
         // TODO remove preSwarmCompat
         // In a one_to_one conv with an old version, the contact here can be in an invited
@@ -238,35 +238,35 @@ DhtPeerConnector::requestConnection(
             auto infos = acc->conversationInfos(info.conversationId);
             preSwarmCompat = infos["mode"] == "0";
         }
-        for (const auto& member : members) {
-            devices.emplace_back(DeviceId(member.at("uri")));
-        }
         if (!preSwarmCompat)
-            channelName = "data-transfer://" + info.conversationId + "/" + acc->currentDeviceId()
-                          + "/" + std::to_string(tid);
+            channelName = fmt::format("data-transfer://{}/{}/{}", info.conversationId, acc->currentDeviceId(), tid);
         // If peer is not empty this means that we want to send to one device only
         if (!info.peer.empty()) {
             acc->connectionManager().connectDevice(DeviceId(info.peer), channelName, channelReadyCb);
             return;
         }
+        for (const auto& member : members) {
+            contacts.emplace_back(dht::InfoHash(member.at("uri")));
+        }
     } else {
-        devices.emplace_back(DeviceId(info.peer));
+        contacts.emplace_back(dht::InfoHash(info.peer));
     }
 
-    for (const auto& peer_h : devices) {
+    for (const auto& peer_h : contacts) {
         acc->forEachDevice(
             peer_h,
             [this, channelName, tid, channelReadyCb = std::move(channelReadyCb)](
-                const dht::InfoHash& dev_h) {
+                const std::shared_ptr<dht::crypto::PublicKey>& dev) {
                 auto acc = pimpl_->account.lock();
                 if (!acc)
                     return;
-                if (dev_h == acc->dht()->getId()) {
+                auto deviceId = dev->getLongId();
+                if (deviceId == acc->dht()->getPublicKey()->getLongId()) {
                     // No connection to same device
                     return;
                 }
 
-                acc->connectionManager().connectDevice(dev_h, channelName, channelReadyCb);
+                acc->connectionManager().connectDevice(deviceId, channelName, channelReadyCb);
             },
 
             [peer_h, onChanneledCancelled, accId = acc->getAccountID()](bool found) {
diff --git a/src/jamidht/server_account_manager.cpp b/src/jamidht/server_account_manager.cpp
index caa903cc99ee92c01db81de61b74f03ad2f9a915..0560a63fb525634f8f1aa29c55993c3b4ac38efb 100644
--- a/src/jamidht/server_account_manager.cpp
+++ b/src/jamidht/server_account_manager.cpp
@@ -146,7 +146,8 @@ ServerAccountManager::initAuthentication(PrivateKey key,
                                     auto info = std::make_unique<AccountInfo>();
                                     info->identity.first = ctx->key.get();
                                     info->identity.second = cert;
-                                    info->deviceId = cert->getPublicKey().getId().toString();
+                                    info->devicePk = std::make_shared<dht::crypto::PublicKey>(cert->getPublicKey());
+                                    info->deviceId = info->devicePk->getLongId().toString();
                                     info->accountId = accountCert->getId().toString();
                                     info->contacts = std::make_unique<ContactList>(accountCert,
                                                                                    this_.path_,
@@ -430,7 +431,7 @@ ServerAccountManager::syncDevices()
                         } else {
                             for (unsigned i = 0, n = json.size(); i < n; i++) {
                                 const auto& e = json[i];
-                                dht::InfoHash deviceId(e["deviceId"].asString());
+                                dht::PkId deviceId(e["deviceId"].asString());
                                 if (deviceId) {
                                     this_.info_->contacts->foundAccountDevice(deviceId,
                                                                               e["alias"].asString(),
diff --git a/src/manager.cpp b/src/manager.cpp
index 9c2a1ae9759d2a9d6615bd37e20284268cea6489..25b86fed4099d65d81d30944782ff4fea22e3848 100644
--- a/src/manager.cpp
+++ b/src/manager.cpp
@@ -3460,7 +3460,7 @@ Manager::gitSocket(const std::string& accountId,
                    const std::string& conversationId)
 {
     if (const auto acc = getAccount<JamiAccount>(accountId))
-        return acc->gitSocket(deviceId, conversationId);
+        return acc->gitSocket(DeviceId(deviceId), conversationId);
     return std::nullopt;
 }
 
diff --git a/src/security/certstore.cpp b/src/security/certstore.cpp
index 288922cd32d4e7b579a664326b02c47cd2d2eda3..7864fa5d4e3f914bf1c343f59f8e4ab5a34fc67a 100644
--- a/src/security/certstore.cpp
+++ b/src/security/certstore.cpp
@@ -72,8 +72,8 @@ CertificateStore::loadLocalCertificates()
             if (id != f)
                 throw std::logic_error({});
             while (crt) {
-                auto id_str = crt->getId().toString();
-                certs_.emplace(id_str, crt);
+                certs_.emplace(crt->getId().toString(), crt);
+                certs_.emplace(crt->getLongId().toString(), crt);
                 loadRevocations(*crt);
                 crt = crt->issuer;
                 ++n;
@@ -252,6 +252,8 @@ CertificateStore::pinCertificatePath(const std::string& path,
                 scerts.emplace_back(shared);
                 auto e = certs_.emplace(shared->getId().toString(), shared);
                 ids.emplace_back(e.first->first);
+                e = certs_.emplace(shared->getLongId().toString(), shared);
+                ids.emplace_back(e.first->first);
             }
             paths_.emplace(path, std::move(scerts));
         }
@@ -308,14 +310,19 @@ CertificateStore::pinCertificate(const std::shared_ptr<crypto::Certificate>& cer
         while (c) {
             bool inserted;
             auto id = c->getId().toString();
+            auto longId = c->getLongId().toString();
             decltype(certs_)::iterator it;
             std::tie(it, inserted) = certs_.emplace(id, c);
+            if (not inserted)
+                it->second = c;
+            std::tie(it, inserted) = certs_.emplace(longId, c);
             if (not inserted)
                 it->second = c;
             if (local) {
                 for (const auto& crl : c->getRevocationLists())
                     pinRevocationList(id, *crl);
             }
+            ids.emplace_back(longId);
             ids.emplace_back(id);
             c = c->issuer;
             sig |= inserted;
diff --git a/src/sip/sipaccountbase.cpp b/src/sip/sipaccountbase.cpp
index c563cbb38dea68790520801037d4ff97c8e9e006..91d6465e79623ce2368b823641fa0753adc43d4d 100644
--- a/src/sip/sipaccountbase.cpp
+++ b/src/sip/sipaccountbase.cpp
@@ -540,6 +540,7 @@ SIPAccountBase::getIceOptions() const noexcept
 void
 SIPAccountBase::onTextMessage(const std::string& id,
                               const std::string& from,
+                              const std::string& deviceId,
                               const std::map<std::string, std::string>& payloads)
 {
     JAMI_DBG("Text message received from %s, %zu part(s)", from.c_str(), payloads.size());
@@ -641,10 +642,12 @@ SIPAccountBase::onTextMessage(const std::string& id,
             JAMI_WARN("Received indication for new commit available in conversation %s",
                       json["id"].asString().c_str());
 
-            onNewGitCommit(from,
-                           json["deviceId"].asString(),
-                           json["id"].asString(),
-                           json["commit"].asString());
+            if (deviceId.empty()) {
+                JAMI_ERR() << "Incorrect deviceId. Can't retrieve history";
+                return;
+            }
+
+            onNewGitCommit(from, deviceId, json["id"].asString(), json["commit"].asString());
             return;
         } else if (m.first == MIME_TYPE_INVITE_JSON) {
             Json::Value json;
diff --git a/src/sip/sipaccountbase.h b/src/sip/sipaccountbase.h
index a4bbb70d98930dad8d07de84773a73fbac5dabed..0f6bca8ad6d766ad25cdd5c5908381bf7ca63fa6 100644
--- a/src/sip/sipaccountbase.h
+++ b/src/sip/sipaccountbase.h
@@ -273,6 +273,7 @@ public:
 
     virtual void onTextMessage(const std::string& id,
                                const std::string& from,
+                               const std::string& deviceId,
                                const std::map<std::string, std::string>& payloads);
 
     /* Returns true if the username and/or hostname match this account */
diff --git a/src/sip/siptransport.cpp b/src/sip/siptransport.cpp
index 2220d5d0bce8d20ef3577c6e4a057bd9793c740f..ec21427189d09225b95fbbba899798adaa5fa8ef 100644
--- a/src/sip/siptransport.cpp
+++ b/src/sip/siptransport.cpp
@@ -414,7 +414,7 @@ SipTransportBroker::getChanneledTransport(const std::shared_ptr<ChannelSocket>&
                                                                 std::move(cb));
     auto tr = sips_tr->getTransportBase();
     auto sip_tr = std::make_shared<SipTransport>(tr);
-    sip_tr->setIsChanneledTransport();
+    sip_tr->setDeviceId(socket->deviceId().toString());
     sips_tr.release(); // managed by PJSIP now
 
     {
diff --git a/src/sip/siptransport.h b/src/sip/siptransport.h
index 0357e5e80ef5b06cdcbf0d5ec1313f22707cb710..c74e39f90208199a2d6ae6d7768de67b70b72dfc 100644
--- a/src/sip/siptransport.h
+++ b/src/sip/siptransport.h
@@ -113,8 +113,8 @@ public:
     /** Only makes sense for connection-oriented transports */
     bool isConnected() const noexcept { return connected_; }
 
-    void setIsIceTransport() { isIceTransport_ = true; }
-    void setIsChanneledTransport() { isChanneledTransport_ = true; }
+    inline void setDeviceId(const std::string& deviceId) { deviceId_ = deviceId; }
+    inline std::string_view deviceId() const { return deviceId_; }
     inline void setAccount(const std::shared_ptr<SIPAccountBase>& account) { account_ = account; }
     inline const std::weak_ptr<SIPAccountBase>& getAccount() const { return account_; }
 
@@ -132,8 +132,7 @@ private:
     std::weak_ptr<SIPAccountBase> account_ {};
 
     bool connected_ {false};
-    bool isIceTransport_ {false};
-    bool isChanneledTransport_ {false};
+    std::string deviceId_ {};
     TlsInfos tlsInfos_;
 };
 
diff --git a/src/sip/sipvoiplink.cpp b/src/sip/sipvoiplink.cpp
index 8e0b738320d2c30a2ed9ad31852678d1df173942..7c534838988c1d3ef0550aa0d83be143d714b8d9 100644
--- a/src/sip/sipvoiplink.cpp
+++ b/src/sip/sipvoiplink.cpp
@@ -355,7 +355,7 @@ transaction_request_cb(pjsip_rx_data* rdata)
                     } catch (...) {
                     }
                 }
-                account->onTextMessage(id, peerNumber, payloads);
+                account->onTextMessage(id, peerNumber, std::string(transport->deviceId()), payloads);
             }
             return PJ_FALSE;
         }
diff --git a/test/unitTest/conversationRepository/conversationRepository.cpp b/test/unitTest/conversationRepository/conversationRepository.cpp
index 0c54aac5bfb8a1afd36451ece01c9e49eaf8dc36..2d8fb93c29d979628a38a7794dabb0ffe029947e 100644
--- a/test/unitTest/conversationRepository/conversationRepository.cpp
+++ b/test/unitTest/conversationRepository/conversationRepository.cpp
@@ -124,7 +124,7 @@ void
 ConversationRepositoryTest::testCreateRepository()
 {
     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
-    auto aliceDeviceId = aliceAccount->currentDeviceId();
+    auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     auto uri = aliceAccount->getUsername();
 
     auto repository = ConversationRepository::createConversation(aliceAccount->weak());
@@ -152,7 +152,8 @@ ConversationRepositoryTest::testCreateRepository()
     CPPUNIT_ASSERT(aliceAccount->identity().second->getPublicKey().checkSignature(data, pk));
 
     // 2. Check created files
-    auto CRLsPath = repoPath + DIR_SEPARATOR_STR + "CRLs" + DIR_SEPARATOR_STR + aliceDeviceId;
+    auto CRLsPath = repoPath + DIR_SEPARATOR_STR + "CRLs" + DIR_SEPARATOR_STR
+                    + aliceDeviceId.toString();
     CPPUNIT_ASSERT(fileutils::isDirectory(repoPath));
 
     auto adminCrt = repoPath + DIR_SEPARATOR_STR + "admins" + DIR_SEPARATOR_STR + uri + ".crt";
@@ -167,8 +168,8 @@ ConversationRepositoryTest::testCreateRepository()
 
     CPPUNIT_ASSERT(adminCrtStr == parentCert);
 
-    auto deviceCrt = repoPath + DIR_SEPARATOR_STR + "devices" + DIR_SEPARATOR_STR + aliceDeviceId
-                     + ".crt";
+    auto deviceCrt = repoPath + DIR_SEPARATOR_STR + "devices" + DIR_SEPARATOR_STR
+                     + aliceDeviceId.toString() + ".crt";
     CPPUNIT_ASSERT(fileutils::isFile(deviceCrt));
 
     crt = std::ifstream(deviceCrt);
@@ -183,9 +184,9 @@ ConversationRepositoryTest::testCloneViaChannelSocket()
 {
     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
-    auto aliceDeviceId = std::string(aliceAccount->currentDeviceId());
+    auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     auto uri = aliceAccount->getUsername();
-    auto bobDeviceId = std::string(bobAccount->currentDeviceId());
+    auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
 
     bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
     aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
@@ -220,7 +221,7 @@ ConversationRepositoryTest::testCloneViaChannelSocket()
             rcv.notify_one();
         });
 
-    aliceAccount->connectionManager().connectDevice(DeviceId(bobDeviceId),
+    aliceAccount->connectionManager().connectDevice(bobDeviceId,
                                                     "git://*",
                                                     [&](std::shared_ptr<ChannelSocket> socket,
                                                         const DeviceId&) {
@@ -241,7 +242,7 @@ ConversationRepositoryTest::testCloneViaChannelSocket()
     GitServer gs(aliceId, repository->id(), sendSocket);
 
     auto cloned = ConversationRepository::cloneConversation(bobAccount->weak(),
-                                                            aliceDeviceId,
+                                                            aliceDeviceId.toString(),
                                                             repository->id());
     gs.stop();
 
@@ -265,7 +266,8 @@ ConversationRepositoryTest::testCloneViaChannelSocket()
     CPPUNIT_ASSERT(aliceAccount->identity().second->getPublicKey().checkSignature(data, pk));
 
     // 2. Check created files
-    auto CRLsPath = clonedPath + DIR_SEPARATOR_STR + "CRLs" + DIR_SEPARATOR_STR + aliceDeviceId;
+    auto CRLsPath = clonedPath + DIR_SEPARATOR_STR + "CRLs" + DIR_SEPARATOR_STR
+                    + aliceDeviceId.toString();
     CPPUNIT_ASSERT(fileutils::isDirectory(clonedPath));
 
     auto adminCrt = clonedPath + DIR_SEPARATOR_STR + "admins" + DIR_SEPARATOR_STR + uri + ".crt";
@@ -280,8 +282,8 @@ ConversationRepositoryTest::testCloneViaChannelSocket()
 
     CPPUNIT_ASSERT(adminCrtStr == parentCert);
 
-    auto deviceCrt = clonedPath + DIR_SEPARATOR_STR + "devices" + DIR_SEPARATOR_STR + aliceDeviceId
-                     + ".crt";
+    auto deviceCrt = clonedPath + DIR_SEPARATOR_STR + "devices" + DIR_SEPARATOR_STR
+                     + aliceDeviceId.toString() + ".crt";
     CPPUNIT_ASSERT(fileutils::isFile(deviceCrt));
 
     crt = std::ifstream(deviceCrt);
@@ -365,8 +367,8 @@ ConversationRepositoryTest::testFetch()
 {
     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
-    auto aliceDeviceId = std::string(aliceAccount->currentDeviceId());
-    auto bobDeviceId = std::string(bobAccount->currentDeviceId());
+    auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
+    auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
 
     bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
     aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
@@ -401,7 +403,7 @@ ConversationRepositoryTest::testFetch()
             rcv.notify_one();
         });
 
-    aliceAccount->connectionManager().connectDevice(DeviceId(bobDeviceId),
+    aliceAccount->connectionManager().connectDevice(bobDeviceId,
                                                     "git://*",
                                                     [&](std::shared_ptr<ChannelSocket> socket,
                                                         const DeviceId&) {
@@ -425,7 +427,7 @@ ConversationRepositoryTest::testFetch()
     // Clone repository
     auto id1 = repository->commitMessage("Commit 1");
     auto cloned = ConversationRepository::cloneConversation(bobAccount->weak(),
-                                                            aliceDeviceId,
+                                                            aliceDeviceId.toString(),
                                                             repository->id());
     gs.stop();
     bobAccount->removeGitSocket(aliceDeviceId, repository->id());
@@ -435,7 +437,7 @@ ConversationRepositoryTest::testFetch()
     auto id3 = repository->commitMessage("Commit 3");
 
     // Open a new channel to simulate the fact that we are later
-    aliceAccount->connectionManager().connectDevice(DeviceId(bobDeviceId),
+    aliceAccount->connectionManager().connectDevice(bobDeviceId,
                                                     "git://*",
                                                     [&](std::shared_ptr<ChannelSocket> socket,
                                                         const DeviceId&) {
@@ -452,8 +454,8 @@ ConversationRepositoryTest::testFetch()
     bobAccount->addGitSocket(aliceDeviceId, repository->id(), channelSocket);
     GitServer gs2(aliceId, repository->id(), sendSocket);
 
-    CPPUNIT_ASSERT(cloned->fetch(aliceDeviceId));
-    CPPUNIT_ASSERT(id3 == cloned->remoteHead(aliceDeviceId));
+    CPPUNIT_ASSERT(cloned->fetch(aliceDeviceId.toString()));
+    CPPUNIT_ASSERT(id3 == cloned->remoteHead(aliceDeviceId.toString()));
 
     gs2.stop();
     bobAccount->removeGitSocket(aliceDeviceId, repository->id());
@@ -493,14 +495,14 @@ ConversationRepositoryTest::addCommit(git_repository* repo,
                                       const std::string& branch,
                                       const std::string& commit_msg)
 {
-    auto deviceId = std::string(account->currentDeviceId());
+    auto deviceId = DeviceId(std::string(account->currentDeviceId()));
     auto name = account->getDisplayName();
     if (name.empty())
-        name = deviceId;
+        name = deviceId.toString();
 
     git_signature* sig_ptr = nullptr;
     // Sign commit's buffer
-    if (git_signature_new(&sig_ptr, name.c_str(), deviceId.c_str(), std::time(nullptr), 0) < 0) {
+    if (git_signature_new(&sig_ptr, name.c_str(), deviceId.to_c_str(), std::time(nullptr), 0) < 0) {
         JAMI_ERR("Unable to create a commit signature.");
         return {};
     }
@@ -674,7 +676,7 @@ void
 ConversationRepositoryTest::testDiff()
 {
     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
-    auto aliceDeviceId = aliceAccount->currentDeviceId();
+    auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     auto uri = aliceAccount->getUsername();
     auto repository = ConversationRepository::createConversation(aliceAccount->weak());
 
@@ -688,7 +690,7 @@ ConversationRepositoryTest::testDiff()
     auto changedFiles = ConversationRepository::changedFiles(diff);
     CPPUNIT_ASSERT(!changedFiles.empty());
     CPPUNIT_ASSERT(changedFiles[0] == "admins/" + uri + ".crt");
-    CPPUNIT_ASSERT(changedFiles[1] == "devices/" + aliceDeviceId + ".crt");
+    CPPUNIT_ASSERT(changedFiles[1] == "devices/" + aliceDeviceId.toString() + ".crt");
 }
 
 void
@@ -756,9 +758,9 @@ ConversationRepositoryTest::testCloneHugeRepo()
 {
     auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
     auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
-    auto aliceDeviceId = std::string(aliceAccount->currentDeviceId());
+    auto aliceDeviceId = DeviceId(std::string(aliceAccount->currentDeviceId()));
     auto uri = aliceAccount->getUsername();
-    auto bobDeviceId = std::string(bobAccount->currentDeviceId());
+    auto bobDeviceId = DeviceId(std::string(bobAccount->currentDeviceId()));
 
     bobAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
     aliceAccount->connectionManager().onICERequest([](const DeviceId&) { return true; });
@@ -801,7 +803,7 @@ DIR_SEPARATOR_STR + bobAccount->getAccountID()
             rcv.notify_one();
         });
 
-    aliceAccount->connectionManager().connectDevice(DeviceId(bobDeviceId),
+    aliceAccount->connectionManager().connectDevice(bobDeviceId,
                                                     "git://*",
                                                     [&](std::shared_ptr<ChannelSocket> socket,
                                                         const DeviceId&) {