Compare commits

...
Author SHA1 Message Date
Adrien Béraud e4622f5e49 dhtrunner: add putEncrypted with PkId 'to' argument 2025-05-31 19:28:30 -04:00
Adrien Béraud 1d86ab8b16 securedht: add putEncrypted with PkId 'to' argument 2025-05-31 19:28:30 -04:00
Adrien Béraud c5edca7508 dhtrunner: allow to find certificates by PkId 2025-05-31 19:28:30 -04:00
Adrien Béraud 767a3721bd securedht: allow to find certificates by PkId 2025-05-31 19:28:30 -04:00
Adrien Béraud e368292546 securedht: put certificate at PkId 2025-05-31 19:28:30 -04:00
4 changed files with 216 additions and 15 deletions

No files matched your search

+8
View File
@@ -268,11 +268,17 @@ public:
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
}
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallback cb={}, bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(InfoHash hash, const std::shared_ptr<crypto::PublicKey>& to, Value&& value, DoneCallbackSimple cb, bool permanent = false) {
putEncrypted(hash, to, std::forward<Value>(value), bindDoneCb(cb), permanent);
}
void putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallback cb={}, bool permanent = false);
void putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallbackSimple cb, bool permanent = false) {
putEncrypted(hash, to, value, bindDoneCb(cb), permanent);
}
/**
* Insert known nodes to the routing table, without necessarly ping them.
@@ -384,6 +390,8 @@ public:
// securedht methods
void findCertificate(InfoHash hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
void findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)>);
void registerCertificate(const std::shared_ptr<crypto::Certificate>& cert);
void setLocalCertificateStore(CertificateStoreQuery&& query_method);
+17 -1
View File
@@ -115,14 +115,20 @@ public:
* The operation will be immediate if the recipient' public key is known (otherwise it will be retrived first).
*/
void putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false) {
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
}
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
[[deprecated("Use the shared_ptr version instead")]]
void putEncrypted(const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false) {
putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
}
void putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
/**
* Take ownership of the value and sign it using our private key.
*/
@@ -135,12 +141,17 @@ public:
void findCertificate(const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
void findPublicKey(const InfoHash& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
void findCertificate(const PkId& id, const std::function<void(const Sp<crypto::Certificate>)>& cb);
void findPublicKey(const PkId& id, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
void registerCertificate(const Sp<crypto::Certificate>& cert);
Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
Sp<crypto::Certificate> getCertificate(const PkId& node) const;
Sp<crypto::PublicKey> getPublicKey(const PkId& node) const;
/**
* Allows to set a custom callback called by the library to find a locally-stored certificate.
* The search key used is the public key ID, so there may be multiple certificates retured, signed with
@@ -360,6 +371,9 @@ private:
ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
Sp<crypto::Certificate> registerCertificate(const PkId& node, const Blob& cert);
Sp<crypto::PrivateKey> key_ {};
Sp<crypto::Certificate> certificate_ {};
@@ -369,6 +383,8 @@ private:
// our certificate cache
std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
std::map<PkId, Sp<crypto::Certificate>> nodesCertificatesLong_ {};
std::map<PkId, Sp<crypto::PublicKey>> nodesPubKeysLong_ {};
std::atomic_bool forward_all_ {false};
bool enableCache_ {false};
+36
View File
@@ -890,6 +890,25 @@ DhtRunner::putSigned(const std::string& key, Value&& value, DoneCallbackSimple c
putSigned(InfoHash::get(key), std::forward<Value>(value), std::move(cb), permanent);
}
void
DhtRunner::putEncrypted(InfoHash hash, const PkId& to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
{
std::unique_lock<std::mutex> lck(storage_mtx);
if (running != State::Running) {
lck.unlock();
if (cb) cb(false, {});
return;
}
ongoing_ops++;
pending_ops.emplace([=,
cb = std::move(cb),
value = std::move(value)
] (SecureDht& dht) mutable {
dht.putEncrypted(hash, to, value, bindOpDoneCallback(std::move(cb)), permanent);
});
cv.notify_all();
}
void
DhtRunner::putEncrypted(InfoHash hash, InfoHash to, std::shared_ptr<Value> value, DoneCallback cb, bool permanent)
{
@@ -1079,6 +1098,23 @@ DhtRunner::findCertificate(InfoHash hash, std::function<void(const Sp<crypto::Ce
cv.notify_all();
}
void DhtRunner::findCertificate(PkId hash, std::function<void(const std::shared_ptr<crypto::Certificate>&)> cb)
{
std::unique_lock<std::mutex> lck(storage_mtx);
if (running != State::Running) {
lck.unlock();
return;
}
ongoing_ops++;
pending_ops.emplace([this, hash, cb = std::move(cb)] (SecureDht& dht) {
dht.findCertificate(hash, [this, cb = std::move(cb)](const Sp<crypto::Certificate>& crt){
cb(crt);
opEnded();
});
});
cv.notify_all();
}
void
DhtRunner::resetDht()
{
+155 -14
View File
@@ -50,9 +50,10 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf,
if (certificate_) {
auto certId = certificate_->getId();
if (key_ and certId != key_->getPublicKey().getId())
auto certLongId = certificate_->getLongId();
if (key_ and (certId != key_->getPublicKey().getId() or certLongId != key_->getPublicKey().getLongId()))
throw DhtException("SecureDht: provided certificate doesn't match private key.");
dht_->addOnConnectedCallback([this, certId, cb=std::move(iacb)]{
dht_->addOnConnectedCallback([this, certId, certLongId, cb=std::move(iacb)]{
dht_->put(certId, Value {
CERTIFICATE_TYPE,
*certificate_,
@@ -62,6 +63,15 @@ SecureDht::SecureDht(std::unique_ptr<DhtInterface> dht, SecureDht::Config conf,
if (logger_)
logger_->d(certId, "SecureDht: certificate announcement %s", ok ? "succeeded" : "failed");
}, {}, true);
dht_->put(InfoHash::get(certLongId), Value {
CERTIFICATE_TYPE,
*certificate_,
1
}, [this, cb=std::move(cb)](bool ok) {
if (cb) cb(ok);
if (logger_)
logger_->debug("SecureDht: certificate announcement {}", ok ? "succeeded" : "failed");
}, {}, true);
});
}
}
@@ -131,6 +141,30 @@ SecureDht::getPublicKey(const InfoHash& node) const
return it->second;
}
Sp<crypto::Certificate>
SecureDht::getCertificate(const PkId& node) const
{
if (node == getLongId())
return certificate_;
auto it = nodesCertificatesLong_.find(node);
if (it == nodesCertificatesLong_.end())
return nullptr;
else
return it->second;
}
Sp<crypto::PublicKey>
SecureDht::getPublicKey(const PkId& node) const
{
if (node == getLongId())
return certificate_->getSharedPublicKey();
auto it = nodesPubKeysLong_.find(node);
if (it == nodesPubKeysLong_.end())
return nullptr;
else
return it->second;
}
Sp<crypto::Certificate>
SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
{
@@ -143,16 +177,33 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
InfoHash h = crt->getPublicKey().getId();
if (node == h) {
if (logger_)
logger_->d("Registering certificate for %s", h.toString().c_str());
auto it = nodesCertificates_.find(h);
if (it == nodesCertificates_.end())
std::tie(it, std::ignore) = nodesCertificates_.emplace(h, std::move(crt));
else
it->second = std::move(crt);
return it->second;
logger_->debug("Registering certificate for {}", h.toString());
registerCertificate(crt);
return crt;
} else {
if (logger_)
logger_->w("Certificate %s for node %s does not match node id !", h.toString().c_str(), node.toString().c_str());
logger_->w("Certificate {} for node {} does not match node id !", h.toString(), node.toString());
return nullptr;
}
}
Sp<crypto::Certificate>
SecureDht::registerCertificate(const PkId& node, const Blob& data)
{
Sp<crypto::Certificate> crt;
try {
crt = std::make_shared<crypto::Certificate>(data);
} catch (const std::exception& e) {
return nullptr;
}
auto h = crt->getPublicKey().getLongId();
if (node == h) {
if (logger_)
logger_->debug("Registering certificate for {}", h.toString());
registerCertificate(crt);
return crt;
} else {
if (logger_)
logger_->w("Certificate {} for node {} does not match node id !", h.toString(), node.toString());
return nullptr;
}
}
@@ -160,8 +211,10 @@ SecureDht::registerCertificate(const InfoHash& node, const Blob& data)
void
SecureDht::registerCertificate(const Sp<crypto::Certificate>& cert)
{
if (cert)
if (cert) {
nodesCertificates_[cert->getId()] = cert;
nodesCertificatesLong_[cert->getLongId()] = cert;
}
}
void
@@ -222,6 +275,63 @@ SecureDht::findPublicKey(const InfoHash& node, const std::function<void(const Sp
auto pk = crt->getSharedPublicKey();
if (*pk) {
nodesPubKeys_[pk->getId()] = pk;
nodesPubKeysLong_[pk->getLongId()] = pk;
if (cb) cb(pk);
return;
}
}
if (cb) cb(nullptr);
});
}
void
SecureDht::findCertificate(const PkId& node, const std::function<void(const Sp<crypto::Certificate>)>& cb)
{
Sp<crypto::Certificate> b = getCertificate(node);
if (b && *b) {
if (logger_)
logger_->debug("Using certificate from cache for {}", node.to_c_str());
if (cb)
cb(b);
return;
}
auto found = std::make_shared<bool>(false);
dht_->get(InfoHash::get(node), [cb,node,found,this](const std::vector<Sp<Value>>& vals) {
for (const auto& v : vals) {
if (auto cert = registerCertificate(node, v->data)) {
*found = true;
if (logger_)
logger_->debug("Found certificate for {}", node.to_c_str());
if (cb)
cb(cert);
return false;
}
}
return !*found;
}, [cb,found](bool) {
if (!*found and cb)
cb(nullptr);
}, Value::TypeFilter(CERTIFICATE_TYPE));
}
void
SecureDht::findPublicKey(const PkId& node, const std::function<void(const Sp<crypto::PublicKey>)>& cb)
{
auto pk = getPublicKey(node);
if (pk && *pk) {
if (logger_)
logger_->debug("Found public key from cache for {}", node.to_c_str());
if (cb)
cb(pk);
return;
}
findCertificate(node, [=](const Sp<crypto::Certificate>& crt) {
if (crt && *crt) {
auto pk = crt->getSharedPublicKey();
if (*pk) {
nodesPubKeys_[pk->getId()] = pk;
nodesPubKeysLong_[pk->getLongId()] = pk;
if (cb) cb(pk);
return;
}
@@ -246,8 +356,10 @@ SecureDht::checkValue(const Sp<Value>& v)
auto isDecrypted = v->isDecrypted();
if (auto decrypted_val = v->decrypt(*key_)) {
auto cacheValue = not isDecrypted and decrypted_val->owner;
if (cacheValue)
if (cacheValue) {
nodesPubKeys_[decrypted_val->owner->getId()] = decrypted_val->owner;
nodesPubKeysLong_[decrypted_val->owner->getLongId()] = decrypted_val->owner;
}
return decrypted_val;
}
} catch (const std::exception& e) {
@@ -259,8 +371,10 @@ SecureDht::checkValue(const Sp<Value>& v)
else if (v->isSigned()) {
auto cacheValue = not v->isSignatureChecked() and enableCache_ and v->owner;
if (v->checkSignature()) {
if (cacheValue)
if (cacheValue) {
nodesPubKeys_[v->owner->getId()] = v->owner;
nodesPubKeysLong_[v->owner->getLongId()] = v->owner;
}
return v;
} else if (logger_)
logger_->w("Signature verification failed for %s", v->toString().c_str());
@@ -401,6 +515,33 @@ SecureDht::putEncrypted(const InfoHash& hash, const InfoHash& to, Sp<Value> val,
});
}
void
SecureDht::putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent)
{
if (not key_) {
if (callback)
callback(false, {});
return;
}
findPublicKey(to, [this, hash, val = std::move(val), callback = std::move(callback), permanent](const Sp<crypto::PublicKey>& pk) {
if(!pk || !*pk) {
if (callback)
callback(false, {});
return;
}
if (logger_)
logger_->warn("Encrypting data for PK: {}", pk->getLongId());
try {
dht_->put(hash, encrypt(*val, *pk), callback, time_point::max(), permanent);
} catch (const std::exception& e) {
if (logger_)
logger_->e("Error putting encrypted data: %s", e.what());
if (callback)
callback(false, {});
}
});
}
void
SecureDht::putEncrypted(const InfoHash& hash, const crypto::PublicKey& pk, Sp<Value> val, DoneCallback callback, bool permanent)
{
@@ -410,7 +551,7 @@ SecureDht::putEncrypted(const InfoHash& hash, const crypto::PublicKey& pk, Sp<Va
return;
}
if (logger_)
logger_->w("Encrypting data for PK: %s", pk.getLongId().to_c_str());
logger_->warn("Encrypting data for PK: {}", pk.getLongId());
try {
dht_->put(hash, encrypt(*val, pk), callback, time_point::max(), permanent);
} catch (const std::exception& e) {