My Project 3.7.7
C++ Distributed Hash Table
Loading...
Searching...
No Matches
securedht.h
1// Copyright (c) 2014-2026 Savoir-faire Linux Inc.
2// SPDX-License-Identifier: MIT
3#pragma once
4
5#include "dht.h"
6#include "crypto.h"
7
8#include <map>
9#include <vector>
10#include <memory>
11#include <random>
12
13namespace dht {
14
15class OPENDHT_PUBLIC SecureDht final : public DhtInterface
16{
17public:
18 typedef std::function<void(bool)> SignatureCheckCallback;
19
20 using Config = SecureDhtConfig;
21
22 static dht::Config getConfig(const SecureDht::Config& conf)
23 {
24 auto c = conf.node_config;
25 if (not c.node_id and conf.id.second)
26 c.node_id = InfoHash::get("node:" + conf.id.second->getId().toString());
27 return c;
28 }
29
36 SecureDht(std::unique_ptr<DhtInterface> dht,
37 Config config,
38 IdentityAnnouncedCb iacb = {},
39 const std::shared_ptr<Logger>& l = {});
40
41 virtual ~SecureDht();
42
43 InfoHash getId() const { return key_ ? key_->getPublicKey().getId() : InfoHash(); }
44 PkId getLongId() const { return key_ ? key_->getPublicKey().getLongId() : PkId(); }
45 Sp<crypto::PublicKey> getPublicKey() const { return key_ ? key_->getSharedPublicKey() : Sp<crypto::PublicKey> {}; }
46
47 ValueType secureType(ValueType&& type);
48
49 ValueType secureType(const ValueType& type)
50 {
51 ValueType tmp_type = type;
52 return secureType(std::move(tmp_type));
53 }
54
55 void registerType(const ValueType& type) override
56 {
57 if (dht_)
58 dht_->registerType(secureType(type));
59 }
60 void registerType(ValueType&& type)
61 {
62 if (dht_)
63 dht_->registerType(secureType(std::forward<ValueType>(type)));
64 }
65 void registerInsecureType(const ValueType& type)
66 {
67 if (dht_)
68 dht_->registerType(type);
69 }
70
76 void get(const InfoHash& id, GetCallback cb, DoneCallback donecb = {}, Value::Filter&& = {}, Where&& w = {}) override;
77 void get(const InfoHash& id,
78 GetCallback cb,
79 DoneCallbackSimple donecb = {},
80 Value::Filter&& f = {},
81 Where&& w = {}) override
82 {
83 get(id, cb, bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
84 }
85 void get(const InfoHash& key,
86 GetCallbackSimple cb,
87 DoneCallback donecb = {},
88 Value::Filter&& f = {},
89 Where&& w = {}) override
90 {
91 get(key, bindGetCb(cb), donecb, std::forward<Value::Filter>(f), std::forward<Where>(w));
92 }
93 void get(const InfoHash& key,
94 GetCallbackSimple cb,
95 DoneCallbackSimple donecb,
96 Value::Filter&& f = {},
97 Where&& w = {}) override
98 {
99 get(key, bindGetCb(cb), bindDoneCb(donecb), std::forward<Value::Filter>(f), std::forward<Where>(w));
100 }
101
105 void putSigned(const InfoHash& hash, Sp<Value> val, DoneCallback callback, bool permanent = false);
106 void putSigned(const InfoHash& hash, Value&& v, DoneCallback callback, bool permanent = false)
107 {
108 putSigned(hash, std::make_shared<Value>(std::move(v)), callback, permanent);
109 }
110
117 const InfoHash& hash, const InfoHash& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
118
119 [[deprecated("Use the shared_ptr version instead")]]
120 void putEncrypted(const InfoHash& hash, const InfoHash& to, Value&& v, DoneCallback callback, bool permanent = false)
121 {
122 putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
123 }
124 void putEncrypted(const InfoHash& hash,
125 const crypto::PublicKey& to,
126 Sp<Value> val,
127 DoneCallback callback,
128 bool permanent = false);
129
130 [[deprecated("Use the shared_ptr version instead")]]
131 void putEncrypted(
132 const InfoHash& hash, const crypto::PublicKey& to, Value&& v, DoneCallback callback, bool permanent = false)
133 {
134 putEncrypted(hash, to, std::make_shared<Value>(std::move(v)), callback, permanent);
135 }
136
137 void putEncrypted(const InfoHash& hash, const PkId& to, Sp<Value> val, DoneCallback callback, bool permanent = false);
138
142 void sign(Value& v) const;
143
144 Value encrypt(Value& v, const crypto::PublicKey& to) const;
145
146 Value decrypt(const Value& v);
147
148 [[deprecated("Use PkId version")]] void findCertificate(
149 const InfoHash& node, const std::function<void(const Sp<crypto::Certificate>)>& cb);
150 [[deprecated("Use PkId version")]] void findPublicKey(const InfoHash& node,
151 const std::function<void(const Sp<crypto::PublicKey>)>& cb);
152
153 void findCertificate(const PkId& id, const std::function<void(const Sp<crypto::Certificate>)>& cb);
154 void findPublicKey(const PkId& id, const std::function<void(const Sp<crypto::PublicKey>)>& cb);
155
156 void registerCertificate(const Sp<crypto::Certificate>& cert);
157
158 [[deprecated("Use PkId version")]] Sp<crypto::Certificate> getCertificate(const InfoHash& node) const;
159 [[deprecated("Use PkId version")]] Sp<crypto::PublicKey> getPublicKey(const InfoHash& node) const;
160
161 Sp<crypto::Certificate> getCertificate(const PkId& node) const;
162 Sp<crypto::PublicKey> getPublicKey(const PkId& node) const;
163
169 void setLocalCertificateStore(CertificateStoreQueryLegacy&& query_method)
170 {
171 localQueryMethodLegacy_ = std::move(query_method);
172 }
173 void setLocalCertificateStore(CertificateStoreQuery&& query_method) { localQueryMethod_ = std::move(query_method); }
174 void setOnPublicAddressChanged(PublicAddressChangedCb cb) override { dht_->setOnPublicAddressChanged(cb); }
175
179 void shutdown(ShutdownCallback cb, bool stop = false) override { dht_->shutdown(cb, stop); }
180 void dumpTables() const override { dht_->dumpTables(); }
181 inline const InfoHash& getNodeId() const override { return dht_->getNodeId(); }
182
183 std::pair<size_t, size_t> getStoreSize() const override { return dht_->getStoreSize(); }
184 std::pair<size_t, size_t> getLocalStoreSize() const override { return dht_->getLocalStoreSize(); }
185 std::string getStorageLog() const override { return dht_->getStorageLog(); }
186 std::string getStorageLog(const InfoHash& h) const override { return dht_->getStorageLog(h); }
187 void setStorageLimit(size_t limit = 0) override { dht_->setStorageLimit(limit); }
188 size_t getStorageLimit() const override { return dht_->getStorageLimit(); }
189 void setLocalStorageLimit(size_t limit = 0) override { dht_->setLocalStorageLimit(limit); }
190 size_t getLocalStorageLimit() const override { return dht_->getLocalStorageLimit(); }
191
192 std::vector<NodeExport> exportNodes() const override { return dht_->exportNodes(); }
193 std::vector<ValuesExport> exportValues() const override { return dht_->exportValues(); }
194 void importValues(const std::vector<ValuesExport>& v) override { dht_->importValues(v); }
195 NodeStats getNodesStats(sa_family_t af) const override { return dht_->getNodesStats(af); }
196
197 NodeInfo getNodeInfo()
198 {
199 NodeInfo info;
200 info.id = getId();
201 info.node_id = getNodeId();
202 info.ipv4 = getNodesStats(AF_INET);
203 info.ipv6 = getNodesStats(AF_INET6);
204 std::tie(info.storage_size, info.storage_values) = getStoreSize();
205 std::tie(info.local_storage_size, info.local_storage_values) = getLocalStoreSize();
206 if (auto sock = getSocket()) {
207 info.bound4 = sock->getBoundRef(AF_INET).getPort();
208 info.bound6 = sock->getBoundRef(AF_INET6).getPort();
209 }
210 return info;
211 }
212
213 std::vector<unsigned> getNodeMessageStats(bool in = false) override { return dht_->getNodeMessageStats(in); }
214 std::string getRoutingTablesLog(sa_family_t af) const override { return dht_->getRoutingTablesLog(af); }
215 std::string getSearchesLog(sa_family_t af) const override { return dht_->getSearchesLog(af); }
216 std::string getSearchLog(const InfoHash& h, sa_family_t af = AF_UNSPEC) const override
217 {
218 return dht_->getSearchLog(h, af);
219 }
220 std::vector<SockAddr> getPublicAddress(sa_family_t family = 0) override { return dht_->getPublicAddress(family); }
221 time_point periodic(const uint8_t* buf, size_t buflen, SockAddr sa, const time_point& now) override
222 {
223 return dht_->periodic(buf, buflen, std::move(sa), now);
224 }
225 time_point periodic(
226 const uint8_t* buf, size_t buflen, const sockaddr* from, socklen_t fromlen, const time_point& now) override
227 {
228 return dht_->periodic(buf, buflen, from, fromlen, now);
229 }
230 NodeStatus updateStatus(sa_family_t af) override { return dht_->updateStatus(af); }
231 NodeStatus getStatus(sa_family_t af) const override { return dht_->getStatus(af); }
232 NodeStatus getStatus() const override { return dht_->getStatus(); }
233 net::DatagramSocket* getSocket() const override { return dht_->getSocket(); };
234 bool isRunning(sa_family_t af = 0) const override { return dht_->isRunning(af); }
235 const ValueType& getType(ValueType::Id type_id) const override { return dht_->getType(type_id); }
236 void addBootstrap(const std::string& host, const std::string& service) override
237 {
238 dht_->addBootstrap(host, service);
239 }
240 void clearBootstrap() override { dht_->clearBootstrap(); }
241 void insertNode(const InfoHash& id, const SockAddr& sa) override { dht_->insertNode(id, sa); }
242 void insertNode(const NodeExport& n) override { dht_->insertNode(n); }
243 void pingNode(SockAddr sa, DoneCallbackSimple&& cb = {}) override { dht_->pingNode(std::move(sa), std::move(cb)); }
244 void query(const InfoHash& key, QueryCallback cb, DoneCallback done_cb = {}, Query&& q = {}) override
245 {
246 dht_->query(key, cb, done_cb, std::move(q));
247 }
248 void query(const InfoHash& key, QueryCallback cb, DoneCallbackSimple done_cb = {}, Query&& q = {}) override
249 {
250 dht_->query(key, cb, done_cb, std::move(q));
251 }
252 std::vector<Sp<Value>> getLocal(const InfoHash& key, const Value::Filter& f = {}) const override
253 {
254 return dht_->getLocal(key, f);
255 }
256 Sp<Value> getLocalById(const InfoHash& key, Value::Id vid) const override { return dht_->getLocalById(key, vid); }
257 void put(const InfoHash& key,
258 Sp<Value> v,
259 DoneCallback cb = nullptr,
260 time_point created = time_point::max(),
261 bool permanent = false) override
262 {
263 dht_->put(key, v, cb, created, permanent);
264 }
265 void put(const InfoHash& key,
266 const Sp<Value>& v,
267 DoneCallbackSimple cb,
268 time_point created = time_point::max(),
269 bool permanent = false) override
270 {
271 dht_->put(key, v, cb, created, permanent);
272 }
273
274 void put(const InfoHash& key,
275 Value&& v,
276 DoneCallback cb = nullptr,
277 time_point created = time_point::max(),
278 bool permanent = false) override
279 {
280 dht_->put(key, std::move(v), cb, created, permanent);
281 }
282 void put(const InfoHash& key,
283 Value&& v,
284 DoneCallbackSimple cb,
285 time_point created = time_point::max(),
286 bool permanent = false) override
287 {
288 dht_->put(key, std::move(v), cb, created, permanent);
289 }
290 std::vector<Sp<Value>> getPut(const InfoHash& h) const override { return dht_->getPut(h); }
291 Sp<Value> getPut(const InfoHash& h, const Value::Id& vid) const override { return dht_->getPut(h, vid); }
292 bool cancelPut(const InfoHash& h, const Value::Id& vid) override { return dht_->cancelPut(h, vid); }
293
294 size_t listen(const InfoHash& key, ValueCallback, Value::Filter = {}, Where = {}) override;
295 size_t listen(const InfoHash& key, GetCallback cb, Value::Filter = {}, Where w = {}) override;
296 size_t listen(const InfoHash& key, GetCallbackSimple cb, Value::Filter f = {}, Where w = {}) override
297 {
298 return listen(key, bindGetCb(cb), f, w);
299 }
300 bool cancelListen(const InfoHash& h, size_t token) override { return dht_->cancelListen(h, token); }
301 void connectivityChanged(sa_family_t af) override { dht_->connectivityChanged(af); }
302 void connectivityChanged() override { dht_->connectivityChanged(); }
303
304 void forwardAllMessages(bool forward) { forward_all_ = forward; }
305
306 void setPushNotificationToken(const std::string& token = "") override { dht_->setPushNotificationToken(token); }
307
312 PushNotificationResult pushNotificationReceived(const std::map<std::string, std::string>& notification) override
313 {
314 return dht_->pushNotificationReceived(notification);
315 }
316
317 void setLogger(const std::shared_ptr<Logger>& logger) override
318 {
319 DhtInterface::setLogger(logger);
320 dht_->setLogger(logger);
321 }
322
326 void setLogFilter(const InfoHash& f) override
327 {
329 dht_->setLogFilter(f);
330 }
331
332private:
333 std::unique_ptr<DhtInterface> dht_;
334 // prevent copy
335 SecureDht(const SecureDht&) = delete;
336 SecureDht& operator=(const SecureDht&) = delete;
337
338 Sp<Value> checkValue(const Sp<Value>& v);
339 ValueCallback getCallbackFilter(const ValueCallback&, Value::Filter&&);
340 GetCallback getCallbackFilter(const GetCallback&, Value::Filter&&);
341
342 Sp<crypto::Certificate> registerCertificate(const InfoHash& node, const Blob& cert);
343 Sp<crypto::Certificate> registerCertificate(const PkId& node, const Blob& cert);
344
345 Sp<crypto::PrivateKey> key_ {};
346 Sp<crypto::Certificate> certificate_ {};
347
348 // method to query the local certificate store
349 CertificateStoreQuery localQueryMethod_ {};
350 CertificateStoreQueryLegacy localQueryMethodLegacy_ {};
351
352 // our certificate cache
353 std::map<InfoHash, Sp<crypto::Certificate>> nodesCertificates_ {};
354 std::map<InfoHash, Sp<crypto::PublicKey>> nodesPubKeys_ {};
355 std::map<PkId, Sp<crypto::Certificate>> nodesCertificatesLong_ {};
356 std::map<PkId, Sp<crypto::PublicKey>> nodesPubKeysLong_ {};
357
358 std::atomic_bool forward_all_ {false};
359 bool enableCache_ {false};
360};
361
362const ValueType CERTIFICATE_TYPE = {8,
363 "Certificate",
364 std::chrono::hours(24 * 7),
365 // A certificate can only be stored at its public key ID.
366 [](InfoHash id, Sp<Value>& v, const InfoHash&, const SockAddr&) {
367 try {
368 crypto::Certificate crt(v->data);
369 // TODO check certificate signature
370 return crt.getPublicKey().getId() == id
371 || InfoHash::get(crt.getPublicKey().getLongId()) == id;
372 } catch (const std::exception& e) {
373 }
374 return false;
375 },
376 [](InfoHash, const Sp<Value>& o, Sp<Value>& n, const InfoHash&, const SockAddr&) {
377 try {
378 return crypto::Certificate(o->data).getPublicKey().getLongId()
379 == crypto::Certificate(n->data).getPublicKey().getLongId();
380 } catch (const std::exception& e) {
381 }
382 return false;
383 }};
384
385} // namespace dht
virtual void setLogFilter(const InfoHash &f)
void putSigned(const InfoHash &hash, Sp< Value > val, DoneCallback callback, bool permanent=false)
size_t listen(const InfoHash &key, GetCallback cb, Value::Filter={}, Where w={}) override
bool isRunning(sa_family_t af=0) const override
Definition securedht.h:234
void insertNode(const InfoHash &id, const SockAddr &sa) override
Definition securedht.h:241
void setLocalStorageLimit(size_t limit=0) override
Definition securedht.h:189
void query(const InfoHash &key, QueryCallback cb, DoneCallback done_cb={}, Query &&q={}) override
Definition securedht.h:244
void get(const InfoHash &id, GetCallback cb, DoneCallback donecb={}, Value::Filter &&={}, Where &&w={}) override
void sign(Value &v) const
SecureDht(std::unique_ptr< DhtInterface > dht, Config config, IdentityAnnouncedCb iacb={}, const std::shared_ptr< Logger > &l={})
void setLogFilter(const InfoHash &f) override
Definition securedht.h:326
void shutdown(ShutdownCallback cb, bool stop=false) override
Definition securedht.h:179
void setStorageLimit(size_t limit=0) override
Definition securedht.h:187
std::vector< NodeExport > exportNodes() const override
Definition securedht.h:192
std::vector< Sp< Value > > getLocal(const InfoHash &key, const Value::Filter &f={}) const override
Definition securedht.h:252
bool cancelPut(const InfoHash &h, const Value::Id &vid) override
Definition securedht.h:292
std::vector< Sp< Value > > getPut(const InfoHash &h) const override
Definition securedht.h:290
void put(const InfoHash &key, Sp< Value > v, DoneCallback cb=nullptr, time_point created=time_point::max(), bool permanent=false) override
Definition securedht.h:257
std::pair< size_t, size_t > getStoreSize() const override
Definition securedht.h:183
Sp< Value > getLocalById(const InfoHash &key, Value::Id vid) const override
Definition securedht.h:256
Sp< Value > getPut(const InfoHash &h, const Value::Id &vid) const override
Definition securedht.h:291
void putEncrypted(const InfoHash &hash, const InfoHash &to, Sp< Value > val, DoneCallback callback, bool permanent=false)
void setLocalCertificateStore(CertificateStoreQueryLegacy &&query_method)
Definition securedht.h:169
const InfoHash & getNodeId() const override
Definition securedht.h:181
PushNotificationResult pushNotificationReceived(const std::map< std::string, std::string > &notification) override
Definition securedht.h:312
NodeStatus updateStatus(sa_family_t af) override
Definition securedht.h:230
void connectivityChanged(sa_family_t af) override
Definition securedht.h:301
std::vector< uint8_t > Blob
Definition utils.h:158
NodeStatus
Definition callbacks.h:24
InfoHash node_id
Definition callbacks.h:101
Describes a query destined to another peer.
Definition value.h:988
Serializable dht::Value filter.
Definition value.h:850
const PkId & getLongId() const