diff --git a/c/opendht.cpp b/c/opendht.cpp index 7ba15ea9c310953e9aa2b8ce41f40730d26a6628..d1fe081176b397011cb28476a9d984c340421550 100644 --- a/c/opendht.cpp +++ b/c/opendht.cpp @@ -261,7 +261,7 @@ dht_pkid dht_certificate_get_long_id(const dht_certificate* c) { dht_publickey* dht_certificate_get_publickey(const dht_certificate* c) { const auto& cert = *reinterpret_cast<const CertSp*>(c); - return reinterpret_cast<dht_publickey*>(new PubkeySp(std::make_shared<dht::crypto::PublicKey>(cert->getPublicKey()))); + return reinterpret_cast<dht_publickey*>(new PubkeySp(cert->getSharedPublicKey())); } // dht::crypto::Identity diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index f26a65f2af8271c356e46041181937db2233e2af..84d5df0e9f62ff5c9f4247470d9c532923041b75 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -390,7 +390,11 @@ struct OPENDHT_PUBLIC Certificate { */ Certificate(gnutls_x509_crt_t crt) noexcept : cert(crt) {} - Certificate(Certificate&& o) noexcept : cert(o.cert), issuer(std::move(o.issuer)) { o.cert = nullptr; }; + Certificate(Certificate&& o) noexcept + : cert(o.cert) + , issuer(std::move(o.issuer)) + , publicKey_(std::move(o.publicKey_)) + { o.cert = nullptr; }; /** * Import certificate (PEM or DER) or certificate chain (PEM), @@ -498,7 +502,8 @@ struct OPENDHT_PUBLIC Certificate { void msgpack_unpack(const msgpack::object& o); explicit operator bool() const { return cert; } - PublicKey getPublicKey() const; + const PublicKey& getPublicKey() const; + const std::shared_ptr<PublicKey>& getSharedPublicKey() const; /** Same as getPublicKey().getId() */ const InfoHash& getId() const; @@ -631,6 +636,9 @@ private: }; std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists; + + mutable std::mutex publicKeyMutex_ {}; + mutable std::shared_ptr<PublicKey> publicKey_ {}; }; struct OPENDHT_PUBLIC TrustList diff --git a/src/crypto.cpp b/src/crypto.cpp index dba347320eb7fe16f0a19a0151913bfadf82693d..ff997d64688fa3b6d2fa8be91801c3bfe4f370b3 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -366,7 +366,7 @@ PrivateKey::getSharedPublicKey() const auto pk = std::make_shared<PublicKey>(); if (auto err = gnutls_pubkey_import_privkey(pk->pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0)) throw CryptoException(std::string("Can't retreive public key: ") + gnutls_strerror(err)); - publicKey_ = pk; + publicKey_ = std::move(pk); } return publicKey_; } @@ -824,13 +824,23 @@ Certificate::~Certificate() } } -PublicKey +const PublicKey& Certificate::getPublicKey() const { - PublicKey pk_ret; - if (auto err = gnutls_pubkey_import_x509(pk_ret.pk, cert, 0)) - throw CryptoException(std::string("Can't get certificate public key: ") + gnutls_strerror(err)); - return pk_ret; + return *getSharedPublicKey(); +} + +const std::shared_ptr<PublicKey>& +Certificate::getSharedPublicKey() const +{ + std::lock_guard<std::mutex> lock(publicKeyMutex_); + if (not publicKey_) { + auto pk = std::make_shared<PublicKey>(); + if (auto err = gnutls_pubkey_import_x509(pk->pk, cert, 0)) + throw CryptoException(std::string("Can't get certificate public key: ") + gnutls_strerror(err)); + publicKey_ = std::move(pk); + } + return publicKey_; } const InfoHash& diff --git a/src/securedht.cpp b/src/securedht.cpp index 55a7bd8a0aeabd3202e4c12164f3b4c97e2794c7..ae1dc0f517e2a1dcc8b4bfeeb3198887395f541a 100644 --- a/src/securedht.cpp +++ b/src/securedht.cpp @@ -121,7 +121,7 @@ Sp<crypto::PublicKey> SecureDht::getPublicKey(const InfoHash& node) const { if (node == getId()) - return std::make_shared<crypto::PublicKey>(certificate_->getPublicKey()); + return certificate_->getSharedPublicKey(); auto it = nodesPubKeys_.find(node); if (it == nodesPubKeys_.end()) return nullptr; @@ -217,7 +217,7 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp } findCertificate(node, [=](const Sp<crypto::Certificate>& crt) { if (crt && *crt) { - auto pk = std::make_shared<crypto::PublicKey>(crt->getPublicKey()); + auto pk = crt->getSharedPublicKey(); if (*pk) { nodesPubKeys_[pk->getId()] = pk; if (cb) cb(pk);