27#include <gnutls/gnutls.h>
28#include <gnutls/abstract.h>
29#include <gnutls/x509.h>
30#include <gnutls/ocsp.h>
52 explicit CryptoException(
const std::string& str) : std::runtime_error(str) {};
73using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
91 PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk =
nullptr; }
94 explicit operator bool()
const {
return pk; }
95 bool operator ==(
const PublicKey& o)
const {
96 return pk == o.pk || getLongId() == o.getLongId();
98 bool operator !=(
const PublicKey& o)
const {
102 PublicKey& operator=(PublicKey&& o)
noexcept;
114 bool checkSignature(
const uint8_t* data,
size_t data_len,
const uint8_t* signature,
size_t signature_len)
const;
115 inline bool checkSignature(
const Blob& data,
const Blob& signature)
const {
116 return checkSignature(data.data(), data.size(), signature.data(), signature.size());
119 Blob encrypt(
const uint8_t* data,
size_t data_len)
const;
120 inline Blob encrypt(
const Blob& data)
const {
121 return encrypt(data.data(), data.size());
123 inline Blob encrypt(std::string_view data)
const {
124 return encrypt((
const uint8_t*)data.data(), data.size());
126 void pack(Blob& b)
const;
127 int pack(uint8_t* out,
size_t* out_len)
const;
128 void unpack(
const uint8_t* dat,
size_t dat_size);
130 std::string toString()
const;
132 template <
typename Packer>
133 void msgpack_pack(Packer& p)
const
137 p.pack_bin(b.size());
138 p.pack_bin_body((
const char*)b.data(), b.size());
141 void msgpack_unpack(
const msgpack::object& o);
143 gnutls_digest_algorithm_t getPreferredDigest()
const;
145 gnutls_pubkey_t pk {
nullptr};
147 mutable InfoHash cachedId_ {};
148 mutable PkId cachedLongId_ {};
149 mutable std::atomic_bool idCached_ {
false};
150 mutable std::atomic_bool longIdCached_ {
false};
152 PublicKey(
const PublicKey&) =
delete;
153 PublicKey& operator=(
const PublicKey&) =
delete;
154 void encryptBloc(
const uint8_t* src,
size_t src_size, uint8_t* dst,
size_t dst_size)
const;
173 PrivateKey(
const uint8_t* src,
size_t src_size,
const char* password =
nullptr);
174 PrivateKey(
const Blob& src,
const std::string& password = {}) :
PrivateKey(src.data(), src.size(), password.c_str()) {}
175 PrivateKey(std::string_view src,
const std::string& password = {}) : PrivateKey((const uint8_t*)src.data(), src.size(), password.c_str()) {}
178 explicit operator bool()
const {
return key; }
180 const PublicKey& getPublicKey()
const;
181 const std::shared_ptr<PublicKey>& getSharedPublicKey()
const;
183 int serialize(uint8_t* out,
size_t* out_len,
const std::string& password = {})
const;
184 Blob serialize(
const std::string& password = {})
const;
190 Blob sign(
const uint8_t* data,
size_t data_len)
const;
191 inline Blob sign(std::string_view dat)
const {
return sign((
const uint8_t*)dat.data(), dat.size()); }
192 inline Blob sign(
const Blob& dat)
const {
return sign(dat.data(), dat.size()); }
200 Blob decrypt(
const Blob& cypher)
const {
return decrypt(cypher.data(), cypher.size()); }
211 gnutls_privkey_t key {};
212 gnutls_x509_privkey_t x509_key {};
214 PrivateKey(
const PrivateKey&) =
delete;
215 PrivateKey& operator=(
const PrivateKey&) =
delete;
216 Blob decryptBloc(
const uint8_t* src,
size_t src_size)
const;
218 mutable std::mutex publicKeyMutex_ {};
219 mutable std::shared_ptr<PublicKey> publicKey_ {};
224 using clock = std::chrono::system_clock;
225 using time_point = clock::time_point;
226 using duration = clock::duration;
235 void pack(
Blob& b)
const;
236 void unpack(
const uint8_t* dat,
size_t dat_size);
237 Blob getPacked()
const {
243 template <
typename Packer>
244 void msgpack_pack(Packer& p)
const
246 Blob b = getPacked();
247 p.pack_bin(b.size());
248 p.pack_bin_body((
const char*)b.data(), b.size());
251 void msgpack_unpack(
const msgpack::object& o);
253 void revoke(
const Certificate& crt, time_point t = time_point::min());
262 void sign(
const Identity&
id) { sign(*
id.first, *
id.second); }
264 bool isSignedBy(
const Certificate& issuer)
const;
266 std::string toString()
const;
279 time_point getUpdateTime()
const;
280 time_point getNextUpdateTime()
const;
282 gnutls_x509_crl_t get() {
return crl; }
283 gnutls_x509_crl_t getCopy()
const {
287 gnutls_x509_crl_t ret = copy.crl;
293 gnutls_x509_crl_t crl {};
294 RevocationList(
const RevocationList&) =
delete;
295 RevocationList& operator=(
const RevocationList&) =
delete;
298enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
314 void setName(
const std::string& name);
315 void setUID(
const std::string& name);
316 void setAltName(NameType type,
const std::string& name);
318 std::string getName()
const;
319 std::string getUID()
const;
321 void sign(
const PrivateKey& key,
const std::string& password = {});
326 std::string toString()
const;
328 gnutls_x509_crq_t get()
const {
return request; }
332 gnutls_x509_crq_t request {
nullptr};
339 OcspRequest(
const uint8_t* dat_ptr,
size_t dat_size);
346 std::string toString(
const bool compact =
true)
const;
349 Blob getNonce()
const;
351 gnutls_ocsp_req_t request;
365 std::string toString(
const bool compact =
true)
const;
372 gnutls_ocsp_cert_status_t getCertificateStatus()
const;
379 gnutls_ocsp_cert_status_t verifyDirect(
const Certificate& crt,
const Blob& nonce);
382 gnutls_ocsp_resp_t response;
395 , issuer(std::move(o.issuer))
396 , publicKey_(std::move(o.publicKey_))
397 { o.cert =
nullptr; };
404 Certificate(
const uint8_t* dat,
size_t dat_size) : cert(nullptr) {
405 unpack(dat, dat_size);
413 template<
typename Iterator>
422 template<
typename Iterator>
423 Certificate(
const std::vector<std::pair<Iterator, Iterator>>& certs) {
430 void pack(
Blob& b)
const;
431 void unpack(
const uint8_t* dat,
size_t dat_size);
432 Blob getPacked()
const {
446 template<
typename Iterator>
447 void unpack(
const Iterator& begin,
const Iterator& end)
449 std::shared_ptr<Certificate> tmp_subject {};
450 std::shared_ptr<Certificate> first {};
451 for (Iterator icrt = begin; icrt < end; ++icrt) {
452 auto tmp_crt = std::make_shared<Certificate>(*icrt);
454 tmp_subject->issuer = tmp_crt;
455 tmp_subject = std::move(tmp_crt);
473 template<
typename Iterator>
474 void unpack(
const std::vector<std::pair<Iterator, Iterator>>& certs)
476 std::shared_ptr<Certificate> tmp_issuer;
478 for (
auto li = certs.rbegin(); li != certs.rend(); ++li) {
480 gnutls_x509_crt_init(&tmp_crt.cert);
481 const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)};
482 int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
483 if (err != GNUTLS_E_SUCCESS)
484 err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
485 if (err != GNUTLS_E_SUCCESS)
486 throw CryptoException(std::string(
"Could not read certificate - ") + gnutls_strerror(err));
487 tmp_crt.issuer = tmp_issuer;
488 tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt));
490 *
this = tmp_issuer ? std::move(*tmp_issuer) :
Certificate();
493 template <
typename Packer>
494 void msgpack_pack(Packer& p)
const
498 p.pack_bin(b.size());
499 p.pack_bin_body((
const char*)b.data(), b.size());
502 void msgpack_unpack(
const msgpack::object& o);
504 explicit operator bool()
const {
return cert; }
505 const PublicKey& getPublicKey()
const;
506 const std::shared_ptr<PublicKey>& getSharedPublicKey()
const;
513 Blob getSerialNumber()
const;
528 std::vector<std::pair<NameType, std::string>>
getAltNames()
const;
530 std::chrono::system_clock::time_point getActivation()
const;
531 std::chrono::system_clock::time_point getExpiration()
const;
545 std::string print()
const;
562 void addRevocationList(std::shared_ptr<RevocationList>);
564 static Certificate generate(
const PrivateKey& key,
const std::string& name =
"dhtnode",
const Identity& ca = {},
bool is_ca =
false, int64_t validity = 0);
567 gnutls_x509_crt_t getCopy()
const {
571 gnutls_x509_crt_t ret = copy.cert;
576 std::vector<gnutls_x509_crt_t>
577 getChain(
bool copy =
false)
const
581 std::vector<gnutls_x509_crt_t> crts;
582 for (
auto c =
this; c; c = c->issuer.get())
583 crts.emplace_back(copy ? c->getCopy() : c->cert);
588 std::vector<gnutls_x509_crt_t>,
589 std::vector<gnutls_x509_crl_t>
591 getChainWithRevocations(
bool copy =
false)
const
595 std::vector<gnutls_x509_crt_t> crts;
596 std::vector<gnutls_x509_crl_t> crls;
597 for (
auto c =
this; c; c = c->issuer.get()) {
598 crts.emplace_back(copy ? c->getCopy() : c->cert);
599 crls.reserve(crls.size() + c->revocation_lists.size());
600 for (
const auto& crl : c->revocation_lists)
601 crls.emplace_back(copy ? crl->getCopy() : crl->get());
606 gnutls_digest_algorithm_t getPreferredDigest()
const;
613 std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
619 void setValidity(
const PrivateKey& key, int64_t validity);
621 gnutls_x509_crt_t cert {
nullptr};
622 std::shared_ptr<Certificate> issuer {};
623 std::shared_ptr<OcspResponse> ocspResponse;
625 Certificate(
const Certificate&) =
delete;
626 Certificate& operator=(
const Certificate&) =
delete;
628 mutable PkId cachedLongId_ {};
629 mutable std::atomic_bool idCached_ {
false};
630 mutable std::atomic_bool longIdCached_ {
false};
632 struct crlNumberCmp {
633 bool operator() (
const std::shared_ptr<RevocationList>& lhs,
const std::shared_ptr<RevocationList>& rhs)
const {
634 return lhs->getNumber() < rhs->getNumber();
638 std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
640 mutable std::mutex publicKeyMutex_ {};
641 mutable std::shared_ptr<PublicKey> publicKey_ {};
649 bool hasError()
const {
return ret < 0; }
650 bool isValid()
const {
return !hasError() and !(result & GNUTLS_CERT_INVALID); }
651 explicit operator bool()
const {
return isValid(); }
652 std::string toString()
const;
653 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const VerifyResult& h);
664 void remove(
const Certificate& crt,
bool parents =
true);
670 gnutls_x509_trust_list_t trust {
nullptr};
680OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name,
const Identity& ca,
unsigned key_length,
bool is_ca);
681OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name =
"dhtnode",
const Identity& ca = {},
unsigned key_length = 4096);
683OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name,
const Identity& ca,
bool is_ca);
684OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name =
"dhtnode",
const Identity& ca = {});
686OPENDHT_PUBLIC
void saveIdentity(
const Identity&
id,
const std::string& path,
const std::string& privkey_password = {});
687OPENDHT_PUBLIC Identity loadIdentity(
const std::string &path,
const std::string &privkey_password = {});
699OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
715 return aesEncrypt(data.data(), data.size(), key);
733OPENDHT_PUBLIC
inline Blob aesDecrypt(std::string_view data,
const Blob& key) {
return aesDecrypt((uint8_t*)data.data(), data.size(), key); }
735OPENDHT_PUBLIC
Blob aesDecrypt(
const uint8_t* data,
size_t data_length, std::string_view password);
736OPENDHT_PUBLIC
inline Blob aesDecrypt(
const Blob& data, std::string_view password) {
return aesDecrypt(data.data(), data.size(), password); }
737OPENDHT_PUBLIC
inline Blob aesDecrypt(std::string_view data, std::string_view password) {
return aesDecrypt((uint8_t*)data.data(), data.size(), password); }
742OPENDHT_PUBLIC
Blob aesGetKey(
const uint8_t* data,
size_t data_length, std::string_view password);
743OPENDHT_PUBLIC
Blob inline aesGetKey(
const Blob& data, std::string_view password) {
744 return aesGetKey(data.data(), data.size(), password);
752OPENDHT_PUBLIC std::string_view
aesGetEncrypted(
const uint8_t* data,
size_t data_length);
767 return aesBuildEncrypted((
const uint8_t*)encryptedData.data(), encryptedData.size(), salt);
std::string getIssuerUID() const
void sign(const PrivateKey &, const Certificate &, duration validity_period={})
std::string getIssuerName() const
OPENDHT_PUBLIC Blob aesEncrypt(const uint8_t *data, size_t data_length, const Blob &key)
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)
OPENDHT_PUBLIC Blob aesBuildEncrypted(const uint8_t *encryptedData, size_t data_length, const Blob &salt)
OPENDHT_PUBLIC Identity generateIdentity(const std::string &name, const Identity &ca, unsigned key_length, bool is_ca)
OPENDHT_PUBLIC Blob stretchKey(std::string_view password, Blob &salt, size_t key_length=512/8)
OPENDHT_PUBLIC std::string_view aesGetEncrypted(const uint8_t *data, size_t data_length)
OPENDHT_PUBLIC Blob aesGetKey(const uint8_t *data, size_t data_length, std::string_view password)
OPENDHT_PUBLIC Blob aesGetSalt(const uint8_t *data, size_t data_length)
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t *data, size_t data_length, const Blob &key)
std::vector< uint8_t > Blob
std::string getIssuerUID() const
Certificate(const std::vector< std::pair< Iterator, Iterator > > &certs)
void unpack(const Iterator &begin, const Iterator &end)
void setValidity(const Identity &ca, int64_t validity)
Certificate(const Blob &crt)
void revoke(const PrivateKey &, const Certificate &)
const PkId & getLongId() const
const InfoHash & getId() const
Certificate(const Iterator &begin, const Iterator &end)
std::vector< std::shared_ptr< RevocationList > > getRevocationLists() const
std::string getIssuerName() const
std::string getUID() const
void unpack(const std::vector< std::pair< Iterator, Iterator > > &certs)
std::string toString(bool chain=true) const
void addRevocationList(RevocationList &&)
std::string getName() const
std::vector< std::pair< NameType, std::string > > getAltNames() const
Certificate(gnutls_x509_crt_t crt) noexcept
Blob sign(const uint8_t *data, size_t data_len) const
Blob decrypt(const uint8_t *cypher, size_t cypher_len) const
static PrivateKey generate(unsigned key_length=4096)
PrivateKey(gnutls_x509_privkey_t k)
const InfoHash & getId() const
PublicKey(const uint8_t *dat, size_t dat_size)
PublicKey(gnutls_pubkey_t k)
const PkId & getLongId() const