diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index 718a650decff4fab765c7ca8e03818d6663cef2c..64d43092928acad69f7a222ff9fd01d88d70bd62 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -32,6 +32,7 @@ extern "C" {
 
 #include <vector>
 #include <memory>
+#include <atomic>
 
 #ifdef _WIN32
 #include <iso646.h>
@@ -140,6 +141,8 @@ struct OPENDHT_PUBLIC PublicKey
 private:
     mutable InfoHash cachedId_ {};
     mutable PkId cachedLongId_ {};
+    mutable std::atomic_bool idCached_ {false};
+    mutable std::atomic_bool longIdCached_ {false};
 
     PublicKey(const PublicKey&) = delete;
     PublicKey& operator=(const PublicKey&) = delete;
@@ -609,6 +612,8 @@ private:
     Certificate& operator=(const Certificate&) = delete;
     mutable InfoHash cachedId_ {};
     mutable PkId cachedLongId_ {};
+    mutable std::atomic_bool idCached_ {false};
+    mutable std::atomic_bool longIdCached_ {false};
 
     struct crlNumberCmp {
         bool operator() (const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const {
diff --git a/src/crypto.cpp b/src/crypto.cpp
index 9840c04339a923a8d08ecb51b30e1d9883d4f68e..f1b18c1523534429ea3d7d75bb6e55e5821a234e 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -529,7 +529,7 @@ PublicKey::encrypt(const uint8_t* data, size_t data_len) const
 const InfoHash&
 PublicKey::getId() const
 {
-    if (pk and not cachedId_) {
+    if (pk and not idCached_.load()) {
         InfoHash id;
         size_t sz = id.size();
         if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz))
@@ -537,6 +537,7 @@ PublicKey::getId() const
         if (sz != id.size())
             throw CryptoException("Can't get public key ID: wrong output length.");
         cachedId_ = id;
+        idCached_.store(true);
     }
     return cachedId_;
 }
@@ -544,7 +545,7 @@ PublicKey::getId() const
 const PkId&
 PublicKey::getLongId() const
 {
-    if (pk and not cachedLongId_) {
+    if (pk and not longIdCached_.load()) {
         PkId h;
         size_t sz = h.size();
         if (auto err = gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz))
@@ -552,6 +553,7 @@ PublicKey::getLongId() const
         if (sz != h.size())
             throw CryptoException("Can't get 256 bits public key ID: wrong output length.");
         cachedLongId_ = h;
+        longIdCached_.store(true);
     }
     return cachedLongId_;
 }
@@ -833,7 +835,7 @@ Certificate::getPublicKey() const
 const InfoHash&
 Certificate::getId() const
 {
-    if (cert and not cachedId_) {
+    if (cert and not idCached_.load()) {
         InfoHash id;
         size_t sz = id.size();
         if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz))
@@ -841,6 +843,7 @@ Certificate::getId() const
         if (sz != id.size())
             throw CryptoException("Can't get certificate public key ID: wrong output length.");
         cachedId_ = id;
+        idCached_.store(true);
     }
     return cachedId_;
 }
@@ -848,7 +851,7 @@ Certificate::getId() const
 const PkId&
 Certificate::getLongId() const
 {
-    if (cert and not cachedLongId_) {
+    if (cert and not longIdCached_.load()) {
         PkId id;
         size_t sz = id.size();
         if (auto err = gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz))
@@ -856,6 +859,7 @@ Certificate::getLongId() const
         if (sz != id.size())
             throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length.");
         cachedLongId_ = id;
+        longIdCached_.store(true);
     }
     return cachedLongId_;
 }