27 #include <gnutls/gnutls.h> 28 #include <gnutls/abstract.h> 29 #include <gnutls/x509.h> 30 #include <gnutls/ocsp.h> 49 explicit CryptoException(
const std::string& str) : std::runtime_error(str) {};
70 using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
85 PublicKey(
const uint8_t* dat,
size_t dat_size);
87 PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk =
nullptr; };
90 explicit operator bool()
const {
return pk; }
91 bool operator ==(
const PublicKey& o)
const {
92 return pk == o.pk || getId() == o.getId();
94 bool operator !=(
const PublicKey& o)
const {
98 PublicKey& operator=(PublicKey&& o) noexcept;
103 InfoHash getId()
const;
108 PkId getLongId()
const;
110 bool checkSignature(
const uint8_t* data,
size_t data_len,
const uint8_t* signature,
size_t signature_len)
const;
111 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 {
117 return encrypt(data.data(), data.size());
120 void pack(
Blob& b)
const;
121 int pack(uint8_t* out,
size_t* out_len)
const;
122 void unpack(
const uint8_t* dat,
size_t dat_size);
124 std::string toString()
const;
126 template <
typename Packer>
127 void msgpack_pack(Packer& p)
const 131 p.pack_bin(b.size());
132 p.pack_bin_body((
const char*)b.data(), b.size());
135 void msgpack_unpack(
const msgpack::object& o);
137 gnutls_digest_algorithm_t getPreferredDigest()
const;
139 gnutls_pubkey_t pk {
nullptr};
141 PublicKey(
const PublicKey&) =
delete;
142 PublicKey& operator=(
const PublicKey&) =
delete;
143 void encryptBloc(
const uint8_t* src,
size_t src_size, uint8_t* dst,
size_t dst_size)
const;
162 PrivateKey(
const uint8_t* src,
size_t src_size,
const char* password =
nullptr);
163 PrivateKey(
const Blob& src,
const std::string& password = {}) :
PrivateKey(src.data(), src.size(), password.data()) {}
165 explicit operator bool()
const {
return key; }
168 const std::shared_ptr<PublicKey>& getSharedPublicKey()
const;
170 int serialize(uint8_t* out,
size_t* out_len,
const std::string& password = {})
const;
171 Blob serialize(
const std::string& password = {})
const;
177 Blob sign(
const uint8_t* data,
size_t data_len)
const;
178 inline Blob sign(
const Blob& dat)
const {
return sign(dat.data(), dat.size()); }
185 Blob decrypt(
const uint8_t* cypher,
size_t cypher_len)
const;
186 Blob decrypt(
const Blob& cypher)
const {
return decrypt(cypher.data(), cypher.size()); }
194 static PrivateKey generate(
unsigned key_length = 4096);
197 gnutls_privkey_t key {};
198 gnutls_x509_privkey_t x509_key {};
202 Blob decryptBloc(
const uint8_t* src,
size_t src_size)
const;
204 mutable std::shared_ptr<PublicKey> publicKey_ {};
209 using clock = std::chrono::system_clock;
210 using time_point = clock::time_point;
211 using duration = clock::duration;
220 void pack(
Blob& b)
const;
221 void unpack(
const uint8_t* dat,
size_t dat_size);
222 Blob getPacked()
const {
228 template <
typename Packer>
229 void msgpack_pack(Packer& p)
const 231 Blob b = getPacked();
232 p.pack_bin(b.size());
233 p.pack_bin_body((
const char*)b.data(), b.size());
236 void msgpack_unpack(
const msgpack::object& o);
238 void revoke(
const Certificate& crt, time_point t = time_point::min());
247 void sign(
const Identity&
id) { sign(*
id.first, *
id.second); }
251 std::string toString()
const;
256 Blob getNumber()
const;
259 std::string getIssuerName()
const;
262 std::string getIssuerUID()
const;
264 time_point getUpdateTime()
const;
265 time_point getNextUpdateTime()
const;
267 gnutls_x509_crl_t
get() {
return crl; }
268 gnutls_x509_crl_t getCopy()
const {
272 gnutls_x509_crl_t ret = copy.crl;
278 gnutls_x509_crl_t crl {};
283 enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
298 void setName(
const std::string& name);
299 void setUID(
const std::string& name);
300 void setAltName(NameType type,
const std::string& name);
302 std::string getName()
const;
303 std::string getUID()
const;
305 void sign(
const PrivateKey& key,
const std::string& password = {});
310 std::string toString()
const;
312 gnutls_x509_crq_t
get()
const {
return request; }
316 gnutls_x509_crq_t request {
nullptr};
323 OcspRequest(
const uint8_t* dat_ptr,
size_t dat_size);
329 std::string toString(
const bool compact =
true)
const;
332 Blob getNonce()
const;
334 gnutls_ocsp_req_t request;
348 std::string toString(
const bool compact =
true)
const;
355 gnutls_ocsp_cert_status_t getCertificateStatus()
const;
362 gnutls_ocsp_cert_status_t verifyDirect(
const Certificate& crt,
const Blob& nonce);
365 gnutls_ocsp_resp_t response;
382 Certificate(
const Blob& crt);
383 Certificate(
const std::string& pem) : cert(nullptr) {
384 unpack((
const uint8_t*)pem.data(), pem.size());
386 Certificate(
const uint8_t* dat,
size_t dat_size) : cert(nullptr) {
387 unpack(dat, dat_size);
394 template<
typename Iterator>
403 template<
typename Iterator>
404 Certificate(
const std::vector<std::pair<Iterator, Iterator>>& certs) {
411 void pack(
Blob& b)
const;
412 void unpack(
const uint8_t* dat,
size_t dat_size);
413 Blob getPacked()
const {
427 template<
typename Iterator>
428 void unpack(
const Iterator& begin,
const Iterator& end)
430 std::shared_ptr<Certificate> tmp_subject {};
431 std::shared_ptr<Certificate> first {};
432 for (Iterator icrt = begin; icrt < end; ++icrt) {
433 auto tmp_crt = std::make_shared<Certificate>(*icrt);
435 tmp_subject->issuer = tmp_crt;
436 tmp_subject = std::move(tmp_crt);
454 template<
typename Iterator>
455 void unpack(
const std::vector<std::pair<Iterator, Iterator>>& certs)
457 std::shared_ptr<Certificate> tmp_issuer;
459 for (
auto li = certs.rbegin(); li != certs.rend(); ++li) {
461 gnutls_x509_crt_init(&tmp_crt.cert);
462 const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)};
463 int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
464 if (err != GNUTLS_E_SUCCESS)
465 err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
466 if (err != GNUTLS_E_SUCCESS)
467 throw CryptoException(std::string(
"Could not read certificate - ") + gnutls_strerror(err));
468 tmp_crt.issuer = tmp_issuer;
469 tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt));
471 *
this = tmp_issuer ? std::move(*tmp_issuer) :
Certificate();
474 template <
typename Packer>
475 void msgpack_pack(Packer& p)
const 479 p.pack_bin(b.size());
480 p.pack_bin_body((
const char*)b.data(), b.size());
483 void msgpack_unpack(
const msgpack::object& o);
485 explicit operator bool()
const {
return cert; }
486 PublicKey getPublicKey()
const;
489 InfoHash getId()
const;
491 PkId getLongId()
const;
493 Blob getSerialNumber()
const;
496 std::string getName()
const;
499 std::string getUID()
const;
502 std::string getIssuerName()
const;
505 std::string getIssuerUID()
const;
508 std::vector<std::pair<NameType, std::string>> getAltNames()
const;
510 std::chrono::system_clock::time_point getActivation()
const;
511 std::chrono::system_clock::time_point getExpiration()
const;
523 std::string toString(
bool chain =
true)
const;
525 std::string print()
const;
531 void revoke(
const PrivateKey&,
const Certificate&);
536 std::vector<std::shared_ptr<RevocationList>> getRevocationLists()
const;
541 void addRevocationList(RevocationList&&);
542 void addRevocationList(std::shared_ptr<RevocationList>);
544 static Certificate generate(
const PrivateKey& key,
const std::string& name =
"dhtnode",
const Identity& ca = {},
bool is_ca =
false, int64_t validity = 0);
545 static Certificate generate(
const CertificateRequest& request,
const Identity& ca, int64_t validity = 0);
547 gnutls_x509_crt_t getCopy()
const {
550 auto copy = Certificate(getPacked());
551 gnutls_x509_crt_t ret = copy.cert;
556 std::vector<gnutls_x509_crt_t>
557 getChain(
bool copy =
false)
const 561 std::vector<gnutls_x509_crt_t> crts;
562 for (
auto c =
this; c; c = c->issuer.get())
563 crts.emplace_back(copy ? c->getCopy() : c->cert);
568 std::vector<gnutls_x509_crt_t>,
569 std::vector<gnutls_x509_crl_t>
571 getChainWithRevocations(
bool copy =
false)
const 575 std::vector<gnutls_x509_crt_t> crts;
576 std::vector<gnutls_x509_crl_t> crls;
577 for (
auto c =
this; c; c = c->issuer.get()) {
578 crts.emplace_back(copy ? c->getCopy() : c->cert);
579 crls.reserve(crls.size() + c->revocation_lists.size());
580 for (
const auto& crl : c->revocation_lists)
581 crls.emplace_back(copy ? crl->getCopy() : crl->get());
586 gnutls_digest_algorithm_t getPreferredDigest()
const;
593 std::pair<std::string, Blob> generateOcspRequest(gnutls_x509_crt_t& issuer);
598 void setValidity(
const Identity& ca, int64_t validity);
599 void setValidity(
const PrivateKey& key, int64_t validity);
601 gnutls_x509_crt_t cert {
nullptr};
602 std::shared_ptr<Certificate> issuer {};
603 std::shared_ptr<OcspResponse> ocspResponse;
605 Certificate(
const Certificate&) =
delete;
606 Certificate& operator=(
const Certificate&) =
delete;
607 mutable InfoHash cachedId_ {};
608 mutable PkId cachedLongId_ {};
610 struct crlNumberCmp {
611 bool operator() (
const std::shared_ptr<RevocationList>& lhs,
const std::shared_ptr<RevocationList>& rhs)
const {
612 return lhs->getNumber() < rhs->getNumber();
616 std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
624 bool hasError()
const {
return ret < 0; }
625 bool isValid()
const {
return !hasError() and !(result & GNUTLS_CERT_INVALID); }
626 explicit operator bool()
const {
return isValid(); }
627 std::string toString()
const;
628 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const VerifyResult& h);
639 void remove(
const Certificate& crt,
bool parents =
true);
645 gnutls_x509_trust_list_t trust {
nullptr};
656 explicit secure_vector(
unsigned size, T _item): data_(size, _item) {}
663 crypto::random_device rdev;
665 std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint8_t>::max() };
667 std::uniform_int_distribution<uint8_t> rand_byte;
669 std::generate_n((uint8_t*)ret.data_.data(), ret.size()*
sizeof(T), std::bind(rand_byte, std::ref(rdev)));
683 data_ = std::move(c.data_);
688 data_ = std::move(c);
691 std::vector<T>& writable() { clean();
return data_; }
692 const std::vector<T>& makeInsecure()
const {
return data_; }
693 const uint8_t* data()
const {
return data_.data(); }
696 clean(data_.begin(), data_.end());
699 void clear() { clean(); data_.clear(); }
701 size_t size()
const {
return data_.size(); }
702 bool empty()
const {
return data_.empty(); }
705 void resize(
size_t s) {
706 if (s == data_.size())
return;
707 if (s < data_.size()) {
709 clean(data_.begin()+s, data_.end());
713 auto data = std::move(data_);
716 std::copy(data.begin(), data.end(), data_.begin());
717 clean(data.begin(), data.end());
725 static void clean(
const typename std::vector<T>::iterator& i,
const typename std::vector<T>::iterator& j) {
726 volatile uint8_t* b =
reinterpret_cast<uint8_t*
>(&*i);
727 volatile uint8_t* e =
reinterpret_cast<uint8_t*
>(&*j);
731 std::vector<T> data_;
743 OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name,
const Identity& ca,
unsigned key_length,
bool is_ca);
744 OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name =
"dhtnode",
const Identity& ca = {},
unsigned key_length = 4096);
746 OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name,
const Identity& ca,
bool is_ca);
747 OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name =
"dhtnode",
const Identity& ca = {});
749 OPENDHT_PUBLIC
void saveIdentity(
const Identity&
id,
const std::string& path,
const std::string& privkey_password = {});
759 OPENDHT_PUBLIC
Blob hash(
const Blob& data,
size_t hash_length = 512/8);
761 OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
770 OPENDHT_PUBLIC
Blob stretchKey(
const std::string& password,
Blob& salt,
size_t key_length = 512/8);
775 OPENDHT_PUBLIC
Blob aesEncrypt(
const uint8_t* data,
size_t data_length,
const Blob& key);
777 return aesEncrypt(data.data(), data.size(), key);
784 OPENDHT_PUBLIC
Blob aesDecrypt(
const uint8_t* data,
size_t data_length,
const Blob& key);
786 OPENDHT_PUBLIC
Blob aesDecrypt(
const uint8_t* data,
size_t data_length,
const std::string& password);
787 OPENDHT_PUBLIC
inline Blob aesDecrypt(
const Blob& data,
const std::string& password) {
return aesDecrypt(data.data(), data.size(), password); }
OPENDHT_PUBLIC Identity generateIdentity(const std::string &name, const Identity &ca, unsigned key_length, bool is_ca)
Certificate(const Iterator &begin, const Iterator &end)
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)
Certificate(gnutls_x509_crt_t crt) noexcept
OPENDHT_PUBLIC Blob aesEncrypt(const uint8_t *data, size_t data_length, const Blob &key)
OPENDHT_PUBLIC Blob stretchKey(const std::string &password, Blob &salt, size_t key_length=512/8)
void unpack(const std::vector< std::pair< Iterator, Iterator >> &certs)
PublicKey(gnutls_pubkey_t k)
OPENDHT_PUBLIC Blob aesDecrypt(const uint8_t *data, size_t data_length, const Blob &key)
std::vector< uint8_t > Blob
Certificate(const std::vector< std::pair< Iterator, Iterator >> &certs)
void unpack(const Iterator &begin, const Iterator &end)