From 51525d144bcd06609ffd08aec3244590d5ac7520 Mon Sep 17 00:00:00 2001 From: Adrien Beraud <adrien.beraud@savoirfairelinux.com> Date: Wed, 15 Mar 2023 20:05:06 -0400 Subject: [PATCH] certificate: add public key cache --- c/opendht.cpp | 2 +- include/opendht/crypto.h | 12 ++++++++++-- src/crypto.cpp | 22 ++++++++++++++++------ src/securedht.cpp | 4 ++-- 4 files changed, 29 insertions(+), 11 deletions(-) diff --git a/c/opendht.cpp b/c/opendht.cpp index 7ba15ea9..d1fe0811 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 f26a65f2..84d5df0e 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 dba34732..ff997d64 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 55a7bd8a..ae1dc0f5 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); -- GitLab