diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h
index 8960f37a26108ed14681d2cd5965515ea8c53131..a3c9aa7b40b32de1e1262ac8dba034cc437abc1f 100644
--- a/include/opendht/crypto.h
+++ b/include/opendht/crypto.h
@@ -598,6 +598,8 @@ struct OPENDHT_PUBLIC Certificate {
 private:
     Certificate(const Certificate&) = delete;
     Certificate& operator=(const Certificate&) = delete;
+    InfoHash cachedId_ {};
+    PkId cachedLongId_ {};
 
     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 80dbbbdce0f921f86524998bc4afdc200da1d824..e5c7f83df893dc1c142f238b796499db99e3819e 100644
--- a/src/crypto.cpp
+++ b/src/crypto.cpp
@@ -853,12 +853,15 @@ Certificate::getId() const
 {
     if (not cert)
         return {};
+    if (cachedId_)
+        return cachedId_;
     InfoHash id;
     size_t sz = id.size();
     if (auto err = gnutls_x509_crt_get_key_id(cert, 0, id.data(), &sz))
         throw CryptoException(std::string("Can't get certificate public key ID: ") + gnutls_strerror(err));
     if (sz != id.size())
         throw CryptoException("Can't get certificate public key ID: wrong output length.");
+    cachedId_ = id;
     return id;
 }
 
@@ -867,6 +870,8 @@ Certificate::getLongId() const
 {
     if (not cert)
         return {};
+    if (cachedLongId_)
+        return cachedLongId_;
 #if GNUTLS_VERSION_NUMBER < 0x030401
     throw CryptoException("Can't get certificate 256 bits public key ID: GnuTLS 3.4.1 or higher required.");
 #else
@@ -876,6 +881,7 @@ Certificate::getLongId() const
         throw CryptoException(std::string("Can't get certificate 256 bits public key ID: ") + gnutls_strerror(err));
     if (sz != id.size())
         throw CryptoException("Can't get certificate 256 bits public key ID: wrong output length.");
+    cachedLongId_ = id;
     return id;
 #endif
 }