diff --git a/src/jamidht/conversationrepository.cpp b/src/jamidht/conversationrepository.cpp
index 5e0e702e24f1230daf5837b73ab38bf29baf3542..7e76bf92911cd2f1f5f10dcd0113516cbf76f73a 100644
--- a/src/jamidht/conversationrepository.cpp
+++ b/src/jamidht/conversationrepository.cpp
@@ -77,9 +77,9 @@ public:
     std::string createMergeCommit(git_index* index, const std::string& wanted_ref);
 
     bool validCommits(const std::vector<ConversationCommit>& commits) const;
-    bool checkOnlyDeviceCertificate(const std::string& userDevice,
-                                    const std::string& commitId,
-                                    const std::string& parentId) const;
+    bool checkValidUserDiff(const std::string& userDevice,
+                            const std::string& commitId,
+                            const std::string& parentId) const;
     bool checkVote(const std::string& userDevice,
                    const std::string& commitId,
                    const std::string& parentId) const;
@@ -105,6 +105,8 @@ public:
 
     bool add(const std::string& path);
     void addUserDevice();
+    // Verify that the device in the repository is still valid
+    bool validateDevice();
     std::string commit(const std::string& msg);
     ConversationMode mode() const;
 
@@ -167,6 +169,40 @@ public:
 
     // Permissions
     MemberRole updateProfilePermLvl_ {MemberRole::ADMIN};
+
+    /**
+     * Retrieve the user related to a device
+     * @note deviceToUri_ is used to cache result and avoid to
+     * always load the certificate
+     */
+    std::string uriFromDevice(const std::string& deviceId) const
+    {
+        std::lock_guard<std::mutex> lk(deviceToUriMtx_);
+        auto it = deviceToUri_.find(deviceId);
+        if (it != deviceToUri_.end())
+            return it->second;
+
+        auto repo = repository();
+        if (!repo)
+            return {};
+
+        auto cert = tls::CertificateStore::instance().getCertificate(deviceId);
+        if (!cert || !cert->issuer) {
+            // Not pinned, so load certificate from repo
+            std::string deviceFile = git_repository_workdir(repo.get())
+                                     + fmt::format("devices/{}.crt", deviceId);
+            cert = std::make_shared<dht::crypto::Certificate>(fileutils::loadFile(deviceFile));
+            if (!cert)
+                return {};
+        }
+        auto issuerUid = cert->issuer ? cert->issuer->getId().toString() : cert->getIssuerUID();
+        if (issuerUid.empty())
+            return {};
+        deviceToUri_.insert({deviceId, issuerUid});
+        return issuerUid;
+    }
+    mutable std::mutex deviceToUriMtx_;
+    mutable std::map<std::string, std::string> deviceToUri_;
 };
 
 /////////////////////////////////////////////////////////////////////////////////
@@ -663,37 +699,59 @@ ConversationRepository::Impl::add(const std::string& path)
 }
 
 bool
-ConversationRepository::Impl::checkOnlyDeviceCertificate(const std::string& userDevice,
-                                                         const std::string& commitId,
-                                                         const std::string& parentId) const
+ConversationRepository::Impl::checkValidUserDiff(const std::string& userDevice,
+                                                 const std::string& commitId,
+                                                 const std::string& parentId) const
 {
-    // Here, we check that a file device is modified or not.
-    auto changedFiles = ConversationRepository::changedFiles(diffStats(commitId, parentId));
-    if (changedFiles.size() == 0)
-        return true;
-    else if (changedFiles.size() > 1)
-        return false;
-    // If modified, it's the first commit of a device, we check
-    // that the file wasn't there previously
-    // NOTE: libgit2 return a diff with /, not DIR_SEPARATOR_DIR
-    std::string deviceFile = std::string("devices") + "/" + userDevice + ".crt";
-    if (changedFiles[0] != deviceFile) {
-        return false;
-    }
-
     // Retrieve tree for recent commit
     auto repo = repository();
     if (!repo)
         return false;
     auto treeNew = treeAtCommit(repo.get(), commitId);
-    auto treeOld = treeAtCommit(repo.get(), parentId);
-    if (not treeNew or not treeOld)
+    if (not treeNew)
         return false;
+    std::string deviceFile = fmt::format("devices/{}.crt", userDevice);
     if (!fileAtTree(deviceFile, treeNew)) {
         JAMI_ERR("%s announced but not found", deviceFile.c_str());
         return false;
     }
-    return !fileAtTree(deviceFile, treeOld);
+
+    // Here, we check that a file device is modified or not.
+    auto changedFiles = ConversationRepository::changedFiles(diffStats(commitId, parentId));
+    if (changedFiles.size() == 0)
+        return true;
+
+    // If a certificate is modified (in the changedFiles), it MUST be a certificate from the user
+    // Retrieve userUri
+    auto userUri = uriFromDevice(userDevice);
+    if (userUri.empty())
+        return false;
+
+    std::string adminsFile = fmt::format("admins/{}.crt", userUri);
+    std::string membersFile = fmt::format("members/{}.crt", userUri);
+    for (const auto& changedFile : changedFiles) {
+        if (changedFile == adminsFile || changedFile == membersFile) {
+            // In this case, we should verify it's not added (normal commit, not a member change)
+            // but only updated
+            auto treeOld = treeAtCommit(repo.get(), parentId);
+            if (not treeNew or not treeOld)
+                return false;
+
+            if (!fileAtTree(changedFile, treeOld)) {
+                JAMI_ERR("Invalid file modified: %s", changedFile.c_str());
+                return false;
+            }
+        } else if (changedFile == deviceFile) {
+            // In this case, device is added or modified (certificate expiration)
+            continue;
+        } else {
+            // Invalid file detected
+            JAMI_ERR("Invalid add file detected: %s %u", changedFile.c_str(), (int) *mode_);
+            return false;
+        }
+    }
+
+    return true;
 }
 
 bool
@@ -745,12 +803,9 @@ ConversationRepository::Impl::checkVote(const std::string& userDevice,
         }
     }
 
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
-    if (!cert || !cert->issuer)
-        return false;
-    auto userUri = cert->issuer->getId().toString();
+    auto userUri = uriFromDevice(userDevice);
     // Check that voter is admin
-    auto adminFile = std::string("admins") + "/" + userUri + ".crt";
+    auto adminFile = fmt::format("admins/{}.crt", userUri);
 
     if (!fileAtTree(adminFile, treeOld)) {
         JAMI_ERR("Vote from non admin: %s", userUri.c_str());
@@ -829,11 +884,10 @@ ConversationRepository::Impl::checkValidAdd(const std::string& userDevice,
                                             const std::string& commitId,
                                             const std::string& parentId) const
 {
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
+    auto userUri = uriFromDevice(userDevice);
     auto repo = repository();
-    if (not cert or not cert->issuer or not repo)
+    if (userUri.empty() or not repo)
         return false;
-    auto userUri = cert->issuer->getId().toString();
 
     std::string repoPath = git_repository_workdir(repo.get());
     if (mode() == ConversationMode::ONE_TO_ONE) {
@@ -915,24 +969,22 @@ ConversationRepository::Impl::checkValidJoins(const std::string& userDevice,
                                               const std::string& commitId,
                                               const std::string& parentId) const
 {
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
-    if (!cert || !cert->issuer)
+    auto userUri = uriFromDevice(userDevice);
+    if (userUri.empty())
         return false;
-    auto userUri = cert->issuer->getId().toString();
     // Check no other files changed
     auto changedFiles = ConversationRepository::changedFiles(diffStats(commitId, parentId));
     std::size_t wantedChanged = 3;
     if (changedFiles.size() != wantedChanged)
         return false;
 
-    auto invitedFile = std::string("invited") + "/" + uriMember;
-    auto membersFile = std::string("members") + "/" + uriMember + ".crt";
-    auto deviceFile = std::string("devices") + "/" + userDevice + ".crt";
+    auto invitedFile = fmt::format("invited/{}", uriMember);
+    auto membersFile = fmt::format("members/{}.crt", uriMember);
+    auto deviceFile = fmt::format("devices/{}.crt", userDevice);
 
     // Retrieve tree for commits
     auto repo = repository();
-    if (!repo)
-        return false;
+    assert(repo);
     auto treeNew = treeAtCommit(repo.get(), commitId);
     auto treeOld = treeAtCommit(repo.get(), parentId);
     if (not treeNew or not treeOld)
@@ -977,10 +1029,7 @@ ConversationRepository::Impl::checkValidRemove(const std::string& userDevice,
                                                const std::string& commitId,
                                                const std::string& parentId) const
 {
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
-    if (!cert || !cert->issuer)
-        return false;
-    auto userUri = cert->issuer->getId().toString();
+    auto userUri = uriFromDevice(userDevice);
     auto removeSelf = userUri == uriMember;
 
     // Retrieve tree for recent commit
@@ -1043,10 +1092,7 @@ ConversationRepository::Impl::checkValidRemove(const std::string& userDevice,
             JAMI_ERR("device not found added (%s)", deviceFile.c_str());
             return false;
         }
-        cert = tls::CertificateStore::instance().getCertificate(deviceUri);
-        if (!cert || !cert->issuer)
-            return false;
-        if (uriMember != cert->issuer->getId().toString()
+        if (uriMember != uriFromDevice(deviceUri)
             and uriMember != deviceUri /* If device is removed */) {
             JAMI_ERR("device removed but not for removed user (%s)", deviceFile.c_str());
             return false;
@@ -1058,7 +1104,7 @@ ConversationRepository::Impl::checkValidRemove(const std::string& userDevice,
     }
 
     // If not for self check that user device is admin
-    adminFile = std::string("admins") + "/" + userUri + ".crt";
+    adminFile = fmt::format("admins/{}.crt", userUri);
     if (!fileAtTree(adminFile, treeOld)) {
         JAMI_ERR("admin file (%s) not found", adminFile.c_str());
         return false;
@@ -1094,10 +1140,7 @@ ConversationRepository::Impl::checkValidProfileUpdate(const std::string& userDev
                                                       const std::string& commitId,
                                                       const std::string& parentId) const
 {
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
-    if (!cert || !cert->issuer)
-        return false;
-    auto userUri = cert->issuer->getId().toString();
+    auto userUri = uriFromDevice(userDevice);
     auto valid = false;
     {
         std::lock_guard<std::mutex> lk(membersMtx_);
@@ -1224,12 +1267,7 @@ ConversationRepository::Impl::checkInitialCommit(const std::string& userDevice,
     auto account = account_.lock();
     if (!account)
         return false;
-    auto cert = tls::CertificateStore::instance().getCertificate(userDevice);
-    if (!cert || !cert->issuer) {
-        JAMI_ERR("Cannot find certificate for %s", userDevice.c_str());
-        return false;
-    }
-    auto userUri = cert->issuer->getId().toString();
+    auto userUri = uriFromDevice(userDevice);
     auto changedFiles = ConversationRepository::changedFiles(diffStats(commitId, ""));
     // NOTE: libgit2 return a diff with /, not DIR_SEPARATOR_DIR
 
@@ -1280,9 +1318,77 @@ ConversationRepository::Impl::checkInitialCommit(const std::string& userDevice,
     return hasDevice && hasAdmin;
 }
 
+bool
+ConversationRepository::Impl::validateDevice()
+{
+    auto repo = repository();
+    auto account = account_.lock();
+    if (!account || !repo) {
+        JAMI_WARN("Invalid repository detected");
+        return false;
+    }
+    auto path = fmt::format("devices/{}.crt", account->currentDeviceId());
+    std::string devicePath = git_repository_workdir(repo.get()) + path;
+    if (!fileutils::isFile(devicePath)) {
+        JAMI_WARN("Couldn't find file %s", devicePath.c_str());
+        return false;
+    }
+
+    auto deviceCert = dht::crypto::Certificate(fileutils::loadFile(devicePath));
+
+    if (!account->isValidAccountDevice(deviceCert)) {
+        JAMI_WARN("Device's certificate is not valid anymore. Trying to replace certificate with "
+                  "current one.");
+        // Replace certificate with current cert
+        auto cert = account->identity().second;
+        if (!account->isValidAccountDevice(*cert)) {
+            JAMI_ERR("Current device's certificate is invalid. A migration is needed");
+            return false;
+        }
+        auto 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());
+            return false;
+        }
+        file << cert->toString(false);
+        file.close();
+        if (!add(path)) {
+            JAMI_WARN("Couldn't add file %s", devicePath.c_str());
+            return false;
+        }
+
+        auto parentCert = cert->issuer;
+        auto adminPath = fmt::format("admins/{}.crt", account->getUsername());
+        auto memberPath = fmt::format("members/{}.crt", account->getUsername());
+        std::string fullpath = git_repository_workdir(repo.get());
+        if (fileutils::isFile(git_repository_workdir(repo.get()) + adminPath))
+            path = adminPath;
+        else if (fileutils::isFile(git_repository_workdir(repo.get()) + memberPath))
+            path = memberPath;
+        fullpath += path;
+        if (fileutils::isFile(fullpath)) {
+            auto file = fileutils::ofstream(fullpath, std::ios::trunc | std::ios::binary);
+            if (!file.is_open()) {
+                JAMI_ERR("Could not write data to %s", path.c_str());
+                return false;
+            }
+            file << parentCert->toString(true);
+            file.close();
+            if (!add(path)) {
+                JAMI_WARN("Couldn't add file %s", path.c_str());
+                return false;
+            }
+        }
+    }
+
+    return true;
+}
+
 std::string
 ConversationRepository::Impl::commit(const std::string& msg)
 {
+    if (!validateDevice())
+        return {};
     auto account = account_.lock();
     if (!account)
         return {};
@@ -2168,7 +2274,7 @@ ConversationRepository::Impl::validCommits(
                 // Note: accept all mimetype here, as we can have new mimetypes
                 // Just avoid to add weird files
                 // Check that no weird file is added outside device cert nor removed
-                if (!checkOnlyDeviceCertificate(userDevice, commit.id, commit.parents[0])) {
+                if (!checkValidUserDiff(userDevice, commit.id, commit.parents[0])) {
                     JAMI_WARN("Malformed %s commit %s. Please check you use the latest "
                               "version of Jami, or that your contact is not doing unwanted stuff.",
                               type.c_str(),
diff --git a/src/jamidht/jamiaccount.cpp b/src/jamidht/jamiaccount.cpp
index 93887219b4aacd0b2f5d63bfff8ddeddf2f1111d..79bf286fdf7fd25f260536556c4898ed9efb89cd 100644
--- a/src/jamidht/jamiaccount.cpp
+++ b/src/jamidht/jamiaccount.cpp
@@ -1062,6 +1062,18 @@ JamiAccount::unlinkConversations(const std::set<std::string>& removed)
     }
 }
 
+bool
+JamiAccount::isValidAccountDevice(const dht::crypto::Certificate& cert) const
+{
+    if (accountManager_) {
+        if (auto info = accountManager_->getInfo()) {
+            if (info->contacts)
+                return info->contacts->isValidAccountDevice(cert).isValid();
+        }
+    }
+    return false;
+}
+
 bool
 JamiAccount::revokeDevice(const std::string& password, const std::string& device)
 {
diff --git a/src/jamidht/jamiaccount.h b/src/jamidht/jamiaccount.h
index a24f77e9c512e7a9305416a762d6c0504fa4240e..3b6e620d29c0b55e03efe1c05aa8bae5bc59e515 100644
--- a/src/jamidht/jamiaccount.h
+++ b/src/jamidht/jamiaccount.h
@@ -604,6 +604,8 @@ public:
      */
     void unlinkConversations(const std::set<std::string>& removedConv);
 
+    bool isValidAccountDevice(const dht::crypto::Certificate& cert) const;
+
 private:
     NON_COPYABLE(JamiAccount);
 
diff --git a/test/unitTest/account_archive/migration.cpp b/test/unitTest/account_archive/migration.cpp
index 7cb5098db18a18e08e7caf6bfa8c734b09d53d8d..d1a285d79aea17a05570a510f73caea7c232bbcc 100644
--- a/test/unitTest/account_archive/migration.cpp
+++ b/test/unitTest/account_archive/migration.cpp
@@ -64,10 +64,12 @@ public:
 private:
     void testLoadExpiredAccount();
     void testMigrationAfterRevokation();
+    void testExpiredDeviceInSwarm();
 
     CPPUNIT_TEST_SUITE(MigrationTest);
     CPPUNIT_TEST(testLoadExpiredAccount);
     CPPUNIT_TEST(testMigrationAfterRevokation);
+    CPPUNIT_TEST(testExpiredDeviceInSwarm);
     CPPUNIT_TEST_SUITE_END();
 };
 
@@ -223,6 +225,142 @@ MigrationTest::testMigrationAfterRevokation()
     CPPUNIT_ASSERT(bob2Device != bob2Account->currentDeviceId());
 }
 
+void
+MigrationTest::testExpiredDeviceInSwarm()
+{
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+    auto aliceDevice = std::string(aliceAccount->currentDeviceId());
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+    auto bobUri = bobAccount->getUsername();
+
+    std::mutex mtx;
+    std::unique_lock<std::mutex> lk {mtx};
+    std::condition_variable cv;
+    std::map<std::string, std::shared_ptr<DRing::CallbackWrapperBase>> confHandlers;
+    auto messageBobReceived = 0, messageAliceReceived = 0;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::MessageReceived>(
+        [&](const std::string& accountId,
+            const std::string& /* conversationId */,
+            std::map<std::string, std::string> /*message*/) {
+            if (accountId == bobId) {
+                messageBobReceived += 1;
+            } else {
+                messageAliceReceived += 1;
+            }
+            cv.notify_one();
+        }));
+    bool requestReceived = false;
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConversationSignal::ConversationRequestReceived>(
+            [&](const std::string& /*accountId*/,
+                const std::string& /* conversationId */,
+                std::map<std::string, std::string> /*metadatas*/) {
+                requestReceived = true;
+                cv.notify_one();
+            }));
+    bool conversationReady = false;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConversationSignal::ConversationReady>(
+        [&](const std::string& accountId, const std::string& /* conversationId */) {
+            if (accountId == bobId) {
+                conversationReady = true;
+                cv.notify_one();
+            }
+        }));
+    auto aliceMigrated = false;
+    confHandlers.insert(DRing::exportable_callback<DRing::ConfigurationSignal::MigrationEnded>(
+        [&](const std::string& accountId, const std::string& state) {
+            if (accountId == aliceId && state == "SUCCESS") {
+                aliceMigrated = true;
+            }
+            cv.notify_one();
+        }));
+    bool aliceStopped = false, aliceAnnounced = false, aliceRegistered = false;
+    confHandlers.insert(
+        DRing::exportable_callback<DRing::ConfigurationSignal::VolatileDetailsChanged>(
+            [&](const std::string&, const std::map<std::string, std::string>&) {
+                auto details = aliceAccount->getVolatileAccountDetails();
+                auto daemonStatus = details[DRing::Account::ConfProperties::Registration::STATUS];
+                if (daemonStatus == "UNREGISTERED")
+                    aliceStopped = true;
+                else if (daemonStatus == "REGISTERED")
+                    aliceRegistered = true;
+                auto announced = details[DRing::Account::VolatileProperties::DEVICE_ANNOUNCED];
+                if (announced == "true")
+                    aliceAnnounced = true;
+                cv.notify_one();
+            }));
+    DRing::registerSignalHandlers(confHandlers);
+
+    CPPUNIT_ASSERT(aliceAccount->setValidity("", {}, 90));
+    auto now = std::chrono::system_clock::now();
+    aliceRegistered = false;
+    aliceAccount->forceReloadAccount();
+    CPPUNIT_ASSERT(cv.wait_for(lk, 10s, [&]() { return aliceRegistered; }));
+    CPPUNIT_ASSERT(aliceAccount->currentDeviceId() == aliceDevice);
+
+    aliceStopped = false;
+    Manager::instance().sendRegister(aliceId, false);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 15s, [&]() { return aliceStopped; }));
+    aliceAnnounced = false;
+    Manager::instance().sendRegister(aliceId, true);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return aliceAnnounced; }));
+
+    CPPUNIT_ASSERT(aliceAccount->currentDeviceId() == aliceDevice);
+
+    // Create conversation
+    auto convId = DRing::startConversation(aliceId);
+
+    DRing::addConversationMember(aliceId, convId, bobUri);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return requestReceived; }));
+
+    messageAliceReceived = 0;
+    DRing::acceptConversationRequest(bobId, convId);
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return conversationReady; }));
+
+    // Assert that repository exists
+    auto repoPath = fileutils::get_data_dir() + DIR_SEPARATOR_STR + bobAccount->getAccountID()
+                    + DIR_SEPARATOR_STR + "conversations" + DIR_SEPARATOR_STR + convId;
+    CPPUNIT_ASSERT(fileutils::isDirectory(repoPath));
+    // Wait that alice sees Bob
+    cv.wait_for(lk, 20s, [&]() { return messageAliceReceived == 1; });
+
+    messageBobReceived = 0;
+    DRing::sendMessage(aliceId, convId, "hi"s, "");
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return messageBobReceived == 1; }));
+
+    // Wait for certificate to expire
+    std::this_thread::sleep_until(now + 100s);
+    // Check migration is triggered and expiration updated
+    aliceAnnounced = false;
+    aliceAccount->forceReloadAccount();
+    CPPUNIT_ASSERT(cv.wait_for(lk, 30s, [&]() { return aliceAnnounced; }));
+    CPPUNIT_ASSERT(aliceAccount->currentDeviceId() == aliceDevice);
+
+    // check that certificate in conversation is expired
+    auto devicePath = fmt::format("{}/devices/{}.crt", repoPath, aliceAccount->currentDeviceId());
+    CPPUNIT_ASSERT(fileutils::isFile(devicePath));
+    auto cert = dht::crypto::Certificate(fileutils::loadFile(devicePath));
+    now = std::chrono::system_clock::now();
+    CPPUNIT_ASSERT(cert.getExpiration() < now);
+
+    // Resend a new message
+    messageBobReceived = 0;
+    DRing::sendMessage(aliceId, convId, "hi again"s, "");
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return messageBobReceived == 1; }));
+    messageAliceReceived = 0;
+    DRing::sendMessage(bobId, convId, "hi!"s, "");
+    CPPUNIT_ASSERT(cv.wait_for(lk, 20s, [&]() { return messageAliceReceived == 1; }));
+
+    // check that certificate in conversation is updated
+    CPPUNIT_ASSERT(fileutils::isFile(devicePath));
+    cert = dht::crypto::Certificate(fileutils::loadFile(devicePath));
+    now = std::chrono::system_clock::now();
+    CPPUNIT_ASSERT(cert.getExpiration() > now);
+
+    // Check same device as begining
+    CPPUNIT_ASSERT(aliceAccount->currentDeviceId() == aliceDevice);
+}
+
 } // namespace test
 } // namespace jami
 
diff --git a/test/unitTest/conversation/conversation.cpp b/test/unitTest/conversation/conversation.cpp
index 570afa16612920dac5a15f36ebc730b85bf071bf..dccdd208e81d0bbb0a4517da9f97afef2e165fdc 100644
--- a/test/unitTest/conversation/conversation.cpp
+++ b/test/unitTest/conversation/conversation.cpp
@@ -1084,7 +1084,8 @@ ConversationTest::createFakeConversation(std::shared_ptr<JamiAccount> account)
     }
 
     // /devices
-    std::string devicePath = devicesPath + DIR_SEPARATOR_STR + cert->getId().toString() + ".crt";
+    std::string devicePath = devicesPath + DIR_SEPARATOR_STR + cert->getLongId().toString()
+                             + ".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());