10#include <gnutls/gnutls.h>
11#include <gnutls/abstract.h>
12#include <gnutls/x509.h>
13#include <gnutls/ocsp.h>
33class OPENDHT_PUBLIC CryptoException :
public std::runtime_error
36 explicit CryptoException(
const std::string& str)
37 : std::runtime_error(str) {};
38 explicit CryptoException(
const char* str)
39 : std::runtime_error(str) {};
40 CryptoException(
const CryptoException& e)
noexcept =
default;
41 CryptoException& operator=(
const CryptoException&)
noexcept =
default;
47class OPENDHT_PUBLIC DecryptError :
public CryptoException
50 explicit DecryptError(
const std::string& str)
51 : CryptoException(str) {};
52 explicit DecryptError(
const char* str)
53 : CryptoException(str) {};
54 DecryptError(
const DecryptError& e)
noexcept =
default;
55 DecryptError& operator=(
const DecryptError&)
noexcept =
default;
62using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
67struct OPENDHT_PUBLIC PublicKey
80 PublicKey(
const Blob& pk)
81 : PublicKey(pk.data(), pk.size())
84 :
PublicKey((const uint8_t*) pk.data(), pk.size())
86 PublicKey(PublicKey&& o) noexcept
93 explicit operator bool()
const {
return pk; }
94 bool operator==(
const PublicKey& o)
const {
return pk == o.pk || getLongId() == o.getLongId(); }
95 bool operator!=(
const PublicKey& o)
const {
return !(*
this == o); }
97 PublicKey& operator=(PublicKey&& o)
noexcept;
109 bool checkSignature(
const uint8_t* data,
size_t data_len,
const uint8_t* signature,
size_t signature_len)
const;
110 inline bool checkSignature(
const Blob& data,
const Blob& signature)
const
112 return checkSignature(data.data(), data.size(), signature.data(), signature.size());
115 Blob encrypt(
const uint8_t* data,
size_t data_len)
const;
116 inline Blob encrypt(
const Blob& data)
const {
return encrypt(data.data(), data.size()); }
117 inline Blob encrypt(std::string_view data)
const {
return encrypt((
const uint8_t*) data.data(), data.size()); }
118 void pack(Blob& b)
const;
119 int pack(uint8_t* out,
size_t* out_len)
const;
120 void unpack(
const uint8_t* dat,
size_t dat_size);
122 std::string toString()
const;
124 template<
typename Packer>
125 void msgpack_pack(Packer& p)
const
129 p.pack_bin(b.size());
130 p.pack_bin_body((
const char*) b.data(), b.size());
133 void msgpack_unpack(
const msgpack::object& o);
135 gnutls_digest_algorithm_t getPreferredDigest()
const;
137 gnutls_pubkey_t pk {
nullptr};
140 mutable InfoHash cachedId_ {};
141 mutable PkId cachedLongId_ {};
142 mutable std::atomic_bool idCached_ {
false};
143 mutable std::atomic_bool longIdCached_ {
false};
145 PublicKey(
const PublicKey&) =
delete;
146 PublicKey& operator=(
const PublicKey&) =
delete;
147 void encryptBloc(
const uint8_t* src,
size_t src_size, uint8_t* dst,
size_t dst_size)
const;
153struct OPENDHT_PUBLIC PrivateKey
163 PrivateKey(PrivateKey&& o)
noexcept;
164 PrivateKey& operator=(PrivateKey&& o)
noexcept;
166 PrivateKey(
const uint8_t* src,
size_t src_size,
const char* password =
nullptr);
167 PrivateKey(
const Blob& src,
const std::string& password = {})
168 :
PrivateKey(src.data(), src.size(), password.c_str())
170 PrivateKey(std::string_view src,
const std::string& password = {})
171 : PrivateKey((const uint8_t*) src.data(), src.size(), password.c_str())
175 explicit operator bool()
const {
return key; }
177 const PublicKey& getPublicKey()
const;
178 const std::shared_ptr<PublicKey>& getSharedPublicKey()
const;
180 int serialize(uint8_t* out,
size_t* out_len,
const std::string& password = {})
const;
181 Blob serialize(
const std::string& password = {})
const;
187 Blob sign(
const uint8_t* data,
size_t data_len)
const;
188 inline Blob sign(std::string_view dat)
const {
return sign((
const uint8_t*) dat.data(), dat.size()); }
189 inline Blob sign(
const Blob& dat)
const {
return sign(dat.data(), dat.size()); }
206 static PrivateKey
generate(
unsigned key_length = 4096, gnutls_pk_algorithm_t algo = GNUTLS_PK_RSA);
213 static PrivateKey
generateEC(gnutls_ecc_curve_t curve = GNUTLS_ECC_CURVE_INVALID);
215 gnutls_privkey_t key {};
216 gnutls_x509_privkey_t x509_key {};
219 PrivateKey(
const PrivateKey&) =
delete;
220 PrivateKey& operator=(
const PrivateKey&) =
delete;
221 Blob decryptBloc(
const uint8_t* src,
size_t src_size)
const;
223 mutable std::mutex publicKeyMutex_;
224 mutable std::shared_ptr<PublicKey> publicKey_ {};
227class OPENDHT_PUBLIC RevocationList
229 using clock = std::chrono::system_clock;
230 using time_point = clock::time_point;
231 using duration = clock::duration;
235 RevocationList(
const Blob& b);
236 RevocationList(RevocationList&& o) noexcept
243 RevocationList& operator=(RevocationList&& o)
250 void pack(
Blob& b)
const;
251 void unpack(
const uint8_t* dat,
size_t dat_size);
252 Blob getPacked()
const
259 template<
typename Packer>
260 void msgpack_pack(Packer& p)
const
262 Blob b = getPacked();
263 p.pack_bin(b.size());
264 p.pack_bin_body((
const char*) b.data(), b.size());
267 void msgpack_unpack(
const msgpack::object& o);
269 void revoke(
const Certificate& crt, time_point t = time_point::min());
281 void sign(
const Identity&
id, duration validity_period = {}, uint64_t number = 0)
283 sign(*
id.first, *
id.second, validity_period, number);
286 bool isSignedBy(
const Certificate& issuer)
const;
288 std::string toString()
const;
301 time_point getUpdateTime()
const;
302 time_point getNextUpdateTime()
const;
304 gnutls_x509_crl_t get() {
return crl; }
305 gnutls_x509_crl_t getCopy()
const
310 gnutls_x509_crl_t ret = copy.crl;
316 gnutls_x509_crl_t crl {};
317 RevocationList(
const RevocationList&) =
delete;
318 RevocationList& operator=(
const RevocationList&) =
delete;
321enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
323class OPENDHT_PUBLIC CertificateRequest
326 CertificateRequest();
327 CertificateRequest(
const uint8_t* data,
size_t size);
328 CertificateRequest(std::string_view src)
329 : CertificateRequest((
const uint8_t*) src.data(), src.size())
331 CertificateRequest(
const Blob& data)
332 : CertificateRequest(data.data(), data.size())
335 CertificateRequest(CertificateRequest&& o) noexcept
336 : request(std::move(o.request))
340 CertificateRequest& operator=(CertificateRequest&& o)
noexcept;
342 ~CertificateRequest();
344 void setName(
const std::string& name);
345 void setUID(
const std::string& name);
346 void setAltName(NameType type,
const std::string& name);
348 std::string getName()
const;
349 std::string getUID()
const;
351 void sign(
const PrivateKey& key,
const std::string& password = {});
356 std::string toString()
const;
358 gnutls_x509_crq_t get()
const {
return request; }
361 CertificateRequest(
const CertificateRequest& o) =
delete;
362 CertificateRequest& operator=(
const CertificateRequest& o) =
delete;
363 gnutls_x509_crq_t request {
nullptr};
366class OPENDHT_PUBLIC OcspRequest
369 OcspRequest(gnutls_ocsp_req_t r)
372 OcspRequest(
const uint8_t* dat_ptr,
size_t dat_size);
373 OcspRequest(std::string_view dat)
374 : OcspRequest((
const uint8_t*) dat.data(), dat.size())
381 std::string toString(
const bool compact =
true)
const;
384 Blob getNonce()
const;
387 gnutls_ocsp_req_t request;
390class OPENDHT_PUBLIC OcspResponse
393 OcspResponse(
const uint8_t* dat_ptr,
size_t dat_size);
394 OcspResponse(std::string_view response)
395 : OcspResponse((
const uint8_t*) response.data(), response.size())
403 std::string toString(
const bool compact =
true)
const;
410 gnutls_ocsp_cert_status_t getCertificateStatus()
const;
417 gnutls_ocsp_cert_status_t verifyDirect(
const Certificate& crt,
const Blob& nonce);
420 gnutls_ocsp_resp_t response;
423struct OPENDHT_PUBLIC Certificate
425 Certificate()
noexcept {}
436 , issuer(std::move(o.issuer))
437 , publicKey_(std::move(o.publicKey_))
447 Certificate(
const uint8_t* dat,
size_t dat_size)
450 unpack(dat, dat_size);
453 :
Certificate((const uint8_t*) pem.data(), pem.size())
460 template<
typename Iterator>
470 template<
typename Iterator>
471 Certificate(
const std::vector<std::pair<Iterator, Iterator>>& certs)
479 void pack(
Blob& b)
const;
480 void unpack(
const uint8_t* dat,
size_t dat_size);
481 Blob getPacked()
const
496 template<
typename Iterator>
497 void unpack(
const Iterator& begin,
const Iterator& end)
499 std::shared_ptr<Certificate> tmp_subject {};
500 std::shared_ptr<Certificate> first {};
501 for (Iterator icrt = begin; icrt < end; ++icrt) {
502 auto tmp_crt = std::make_shared<Certificate>(*icrt);
504 tmp_subject->issuer = tmp_crt;
505 tmp_subject = std::move(tmp_crt);
509 *
this = first ? std::move(*first) : Certificate();
523 template<
typename Iterator>
524 void unpack(
const std::vector<std::pair<Iterator, Iterator>>& certs)
526 std::shared_ptr<Certificate> tmp_issuer;
528 for (
auto li = certs.rbegin(); li != certs.rend(); ++li) {
530 gnutls_x509_crt_init(&tmp_crt.cert);
531 const gnutls_datum_t crt_dt {(uint8_t*) &(*li->first), (unsigned) (li->second - li->first)};
532 int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
533 if (err != GNUTLS_E_SUCCESS)
534 err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
535 if (err != GNUTLS_E_SUCCESS)
536 throw CryptoException(std::string(
"Could not read certificate - ") + gnutls_strerror(err));
537 tmp_crt.issuer = tmp_issuer;
538 tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt));
540 *
this = tmp_issuer ? std::move(*tmp_issuer) : Certificate();
543 template<
typename Packer>
544 void msgpack_pack(Packer& p)
const
548 p.pack_bin(b.size());
549 p.pack_bin_body((
const char*) b.data(), b.size());
552 void msgpack_unpack(
const msgpack::object& o);
554 explicit operator bool()
const {
return cert; }
555 const PublicKey& getPublicKey()
const;
556 const std::shared_ptr<PublicKey>& getSharedPublicKey()
const;
563 Blob getSerialNumber()
const;
584 std::vector<std::pair<NameType, std::string>>
getAltNames()
const;
586 std::chrono::system_clock::time_point getActivation()
const;
587 std::chrono::system_clock::time_point getExpiration()
const;
601 std::string print()
const;
620 static Certificate generate(
const PrivateKey& key,
621 const std::string& name =
"dhtnode",
622 const Identity& ca = {},
624 int64_t validity = 0);
627 gnutls_x509_crt_t getCopy()
const
632 gnutls_x509_crt_t ret = copy.cert;
637 std::vector<gnutls_x509_crt_t> getChain(
bool copy =
false)
const
641 std::vector<gnutls_x509_crt_t> crts;
642 for (
auto c =
this; c; c = c->issuer.get())
643 crts.emplace_back(copy ? c->getCopy() : c->cert);
647 std::pair<std::vector<gnutls_x509_crt_t>, std::vector<gnutls_x509_crl_t>> getChainWithRevocations(
648 bool copy =
false)
const
652 std::vector<gnutls_x509_crt_t> crts;
653 std::vector<gnutls_x509_crl_t> crls;
654 for (
auto c =
this; c; c = c->issuer.get()) {
655 crts.emplace_back(copy ? c->getCopy() : c->cert);
656 crls.reserve(crls.size() + c->revocation_lists.size());
657 for (
const auto& crl : c->revocation_lists)
658 crls.emplace_back(copy ? crl->getCopy() : crl->get());
663 gnutls_digest_algorithm_t getPreferredDigest()
const;
670 std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
678 gnutls_x509_crt_t cert {
nullptr};
679 std::shared_ptr<Certificate> issuer {};
680 std::shared_ptr<OcspResponse> ocspResponse;
683 Certificate(
const Certificate&) =
delete;
684 Certificate& operator=(
const Certificate&) =
delete;
685 mutable InfoHash cachedId_ {};
686 mutable PkId cachedLongId_ {};
687 mutable std::atomic_bool idCached_ {
false};
688 mutable std::atomic_bool longIdCached_ {
false};
692 bool operator()(
const std::shared_ptr<RevocationList>& lhs,
const std::shared_ptr<RevocationList>& rhs)
const
694 return lhs->getNumber() < rhs->getNumber();
698 std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
700 mutable std::mutex publicKeyMutex_;
701 mutable std::shared_ptr<PublicKey> publicKey_ {};
704struct OPENDHT_PUBLIC TrustList
710 bool hasError()
const {
return ret < 0; }
711 bool isValid()
const {
return !hasError() and !(result & GNUTLS_CERT_INVALID); }
712 explicit operator bool()
const {
return isValid(); }
713 OPENDHT_PUBLIC std::string toString()
const;
714 OPENDHT_PUBLIC
friend std::ostream& operator<<(std::ostream& s,
const VerifyResult& h);
718 TrustList(TrustList&& o) noexcept
719 : trust(std::move(o.trust))
727 void remove(
const Certificate& crt,
bool parents =
true);
733 gnutls_x509_trust_list_t trust {
nullptr};
743OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name,
const Identity& ca,
unsigned key_length,
bool is_ca);
744OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name =
"dhtnode",
745 const Identity& ca = {},
746 unsigned key_length = 4096);
748OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name,
const Identity& ca,
bool is_ca);
749OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name =
"dhtnode",
const Identity& ca = {});
751OPENDHT_PUBLIC
void saveIdentity(
const Identity&
id,
const std::string& path,
const std::string& privkey_password = {});
752OPENDHT_PUBLIC Identity loadIdentity(
const std::string& path,
const std::string& privkey_password = {});
762OPENDHT_PUBLIC
Blob hash(
const Blob& data,
size_t hash_length = 512 / 8);
764OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
779OPENDHT_PUBLIC
inline Blob
782 return aesEncrypt(data.data(), data.size(), key);
800OPENDHT_PUBLIC
inline Blob
803 return aesDecrypt(data.data(), data.size(), key);
805OPENDHT_PUBLIC
inline Blob
808 return aesDecrypt((uint8_t*) data.data(), data.size(), key);
811OPENDHT_PUBLIC
Blob aesDecrypt(
const uint8_t* data,
size_t data_length, std::string_view password);
812OPENDHT_PUBLIC
inline Blob
815 return aesDecrypt(data.data(), data.size(), password);
817OPENDHT_PUBLIC
inline Blob
818aesDecrypt(std::string_view data, std::string_view password)
820 return aesDecrypt((uint8_t*) data.data(), data.size(), password);
826OPENDHT_PUBLIC
Blob aesGetKey(
const uint8_t* data,
size_t data_length, std::string_view password);
829 return aesGetKey(data.data(), data.size(), password);
838OPENDHT_PUBLIC std::string_view
aesGetEncrypted(
const uint8_t* data,
size_t data_length);
856 return aesBuildEncrypted((
const uint8_t*) encryptedData.data(), encryptedData.size(), salt);
870 const uint8_t* payload,
871 size_t payload_length,
873 const Blob& salt = {});
void sign(const PrivateKey &, const Certificate &, duration validity_period={}, uint64_t number=0)
std::string getIssuerUID() const
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 webPushEncrypt(const Blob &p256dh, const Blob &auth, const uint8_t *payload, size_t payload_length, const PrivateKey &privKey={}, const Blob &salt={})
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::string getIssuerDN() const
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
std::string getDN() 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 generateEC(gnutls_ecc_curve_t curve=GNUTLS_ECC_CURVE_INVALID)
PrivateKey(gnutls_x509_privkey_t k)
static PrivateKey generate(unsigned key_length=4096, gnutls_pk_algorithm_t algo=GNUTLS_PK_RSA)
const InfoHash & getId() const
PublicKey(const uint8_t *dat, size_t dat_size)
PublicKey(gnutls_pubkey_t k)
const PkId & getLongId() const