From 8aef63ce4a9ad751f2c8fcb920012670ac6f65e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Adrien=20B=C3=A9raud?= Date: Fri, 28 May 2021 11:42:39 -0400 Subject: [PATCH] crypto: cache public key --- include/opendht/crypto.h | 6 ++++-- include/opendht/securedht.h | 3 +++ include/opendht/value.h | 2 +- python/opendht.pyx | 12 ++++++------ python/opendht_cpp.pxd | 2 +- src/crypto.cpp | 26 +++++++++++++++----------- tests/cryptotester.cpp | 2 +- 7 files changed, 31 insertions(+), 22 deletions(-) diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index 83d2cb90..8960f37a 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -164,7 +164,9 @@ struct OPENDHT_PUBLIC PrivateKey ~PrivateKey(); explicit operator bool() const { return key; } - PublicKey getPublicKey() const; + const PublicKey& getPublicKey() const; + const std::shared_ptr& getSharedPublicKey() const; + int serialize(uint8_t* out, size_t* out_len, const std::string& password = {}) const; Blob serialize(const std::string& password = {}) const; @@ -199,7 +201,7 @@ private: PrivateKey& operator=(const PrivateKey&) = delete; Blob decryptBloc(const uint8_t* src, size_t src_size) const; - //friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length); + mutable std::shared_ptr publicKey_ {}; }; class OPENDHT_PUBLIC RevocationList diff --git a/include/opendht/securedht.h b/include/opendht/securedht.h index 237dfb50..e1d04660 100644 --- a/include/opendht/securedht.h +++ b/include/opendht/securedht.h @@ -61,6 +61,9 @@ public: PkId getLongId() const { return key_ ? key_->getPublicKey().getLongId() : PkId(); } + Sp getPublicKey() const { + return key_ ? key_->getSharedPublicKey() : Sp{}; + } ValueType secureType(ValueType&& type); diff --git a/include/opendht/value.h b/include/opendht/value.h index a9936370..f949c9b7 100644 --- a/include/opendht/value.h +++ b/include/opendht/value.h @@ -356,7 +356,7 @@ struct OPENDHT_PUBLIC Value void sign(const crypto::PrivateKey& key) { if (isEncrypted()) throw DhtException("Can't sign encrypted data."); - owner = std::make_shared(key.getPublicKey()); + owner = key.getSharedPublicKey(); signature = key.sign(getToSign()); } diff --git a/python/opendht.pyx b/python/opendht.pyx index 31ac7609..8ffe6202 100644 --- a/python/opendht.pyx +++ b/python/opendht.pyx @@ -329,11 +329,11 @@ cdef class PrivateKey(_WithID): cdef shared_ptr[cpp.PrivateKey] _key def getId(self): h = InfoHash() - h._infohash = self._key.get().getPublicKey().getId() + h._infohash = self._key.get().getSharedPublicKey().get().getId() return h def getPublicKey(self): pk = PublicKey() - pk._key = self._key.get().getPublicKey() + pk._key = self._key.get().getSharedPublicKey() return pk def decrypt(self, bytes dat): cdef size_t d_len = len(dat) @@ -358,17 +358,17 @@ cdef class PrivateKey(_WithID): return k cdef class PublicKey(_WithID): - cdef cpp.PublicKey _key + cdef cpp.shared_ptr[cpp.PublicKey] _key def getId(self): h = InfoHash() - h._infohash = self._key.getId() + h._infohash = self._key.get().getId() return h def encrypt(self, bytes dat): cdef size_t d_len = len(dat) cdef cpp.uint8_t* d_ptr = dat cdef cpp.Blob indat indat.assign(d_ptr, (d_ptr + d_len)) - cdef cpp.Blob encrypted = self._key.encrypt(indat) + cdef cpp.Blob encrypted = self._key.get().encrypt(indat) cdef char* encrypted_c_str = encrypted.data() cdef Py_ssize_t length = encrypted.size() return encrypted_c_str[:length] @@ -440,7 +440,7 @@ cdef class Identity(object): property publickey: def __get__(self): k = PublicKey() - k._key = self._id.first.get().getPublicKey() + k._key = self._id.first.get().getSharedPublicKey() return k property certificate: def __get__(self): diff --git a/python/opendht_cpp.pxd b/python/opendht_cpp.pxd index 2aeff604..0033caaa 100644 --- a/python/opendht_cpp.pxd +++ b/python/opendht_cpp.pxd @@ -97,7 +97,7 @@ cdef extern from "opendht/crypto.h" namespace "dht::crypto": cdef cppclass PrivateKey: PrivateKey() - PublicKey getPublicKey() const + shared_ptr[PublicKey] getSharedPublicKey() const Blob decrypt(Blob data) const @staticmethod PrivateKey generate() diff --git a/src/crypto.cpp b/src/crypto.cpp index 78ccb082..80dbbbdc 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -368,13 +368,22 @@ PrivateKey::serialize(uint8_t* out, size_t* out_len, const std::string& password : gnutls_x509_privkey_export_pkcs8(x509_key, GNUTLS_X509_FMT_PEM, password.c_str(), GNUTLS_PKCS_PBES2_AES_256, out, out_len); } -PublicKey +const PublicKey& PrivateKey::getPublicKey() const { - PublicKey pk; - if (auto err = gnutls_pubkey_import_privkey(pk.pk, key, GNUTLS_KEY_KEY_CERT_SIGN | GNUTLS_KEY_CRL_SIGN, 0)) + return *getSharedPublicKey(); +} + +const std::shared_ptr& +PrivateKey::getSharedPublicKey() const +{ + if (publicKey_) + return publicKey_; + auto pk = std::make_shared(); + 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)); - return pk; + publicKey_ = pk; + return publicKey_; } PublicKey::PublicKey() @@ -540,12 +549,7 @@ PublicKey::getId() const return {}; InfoHash id; size_t sz = id.size(); -#if GNUTLS_VERSION_NUMBER < 0x030401 - const int flags = 0; -#else - const int flags = (id.size() == 32) ? GNUTLS_KEYID_USE_SHA256 : 0; -#endif - if (auto err = gnutls_pubkey_get_key_id(pk, flags, id.data(), &sz)) + if (auto err = gnutls_pubkey_get_key_id(pk, 0, id.data(), &sz)) throw CryptoException(std::string("Can't get public key ID: ") + gnutls_strerror(err)); if (sz != id.size()) throw CryptoException("Can't get public key ID: wrong output length."); @@ -1169,7 +1173,7 @@ Certificate::generate(const PrivateKey& key, const std::string& name, const Iden } // TODO: compute the subject key using the recommended RFC method - auto pk = key.getPublicKey(); + const auto& pk = key.getPublicKey(); auto pk_id = pk.getId(); const std::string uid_str = pk_id.toString(); diff --git a/tests/cryptotester.cpp b/tests/cryptotester.cpp index 4ca56528..8c4c4e99 100644 --- a/tests/cryptotester.cpp +++ b/tests/cryptotester.cpp @@ -33,7 +33,7 @@ CryptoTester::setUp() { void CryptoTester::testSignatureEncryption() { auto key = dht::crypto::PrivateKey::generate(); - auto public_key = key.getPublicKey(); + const auto& public_key = key.getPublicKey(); std::vector data1 {5, 10}; std::vector data2(64 * 1024, 10);