diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index 83d2cb90d2171328b241de827a59eadb94b33ea1..8960f37a26108ed14681d2cd5965515ea8c53131 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<PublicKey>& 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> publicKey_ {}; }; class OPENDHT_PUBLIC RevocationList diff --git a/include/opendht/securedht.h b/include/opendht/securedht.h index 237dfb50058bf363f5d1188cd354319d7a6d7703..e1d046606404c3b4701867960cdc47d7715f8c71 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<crypto::PublicKey> getPublicKey() const { + return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey>{}; + } ValueType secureType(ValueType&& type); diff --git a/include/opendht/value.h b/include/opendht/value.h index a99363705b91a11192e0904ad2c3ce6b58e25ac9..f949c9b7aed5ca4bda701278ba0be2b52dfb2a17 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<crypto::PublicKey>(key.getPublicKey()); + owner = key.getSharedPublicKey(); signature = key.sign(getToSign()); } diff --git a/python/opendht.pyx b/python/opendht.pyx index 31ac76094b396eade4fb80427051fd04937d7f7c..8ffe6202d62053e7bbbfd40ed9f7b94dcd4faf89 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 = <cpp.uint8_t*>dat cdef cpp.Blob indat indat.assign(d_ptr, <cpp.uint8_t*>(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 = <char *>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 2aeff604ccf93054a6d811c9845fa4cb46370a30..0033caaa0a67f4e1af34853a8ec059589b282311 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 78ccb0825b005b11456e90aacc8e117852f557ac..80dbbbdce0f921f86524998bc4afdc200da1d824 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<PublicKey>& +PrivateKey::getSharedPublicKey() const +{ + if (publicKey_) + return publicKey_; + 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)); - 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 4ca56528375d88f12313ed1db29b39af78b892c2..8c4c4e996213f74bd3d53a46548d7d6132624b5e 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<uint8_t> data1 {5, 10}; std::vector<uint8_t> data2(64 * 1024, 10);