26#include <gnutls/gnutls.h>
27#include <gnutls/abstract.h>
28#include <gnutls/x509.h>
62using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>;
79 explicit operator bool()
const {
return pk; }
80 bool operator ==(
const PublicKey& o)
const {
81 return pk == o.pk || getId() == o.getId();
83 bool operator !=(
const PublicKey& o)
const {
87 PublicKey& operator=(PublicKey&& o)
noexcept;
89 InfoHash getId()
const;
90 PkId getLongId()
const;
91 bool checkSignature(
const Blob& data,
const Blob& signature)
const;
94 void pack(
Blob& b)
const;
95 void unpack(
const uint8_t* dat,
size_t dat_size);
97 std::string toString()
const;
99 template <
typename Packer>
100 void msgpack_pack(Packer& p)
const
104 p.pack_bin(b.size());
105 p.pack_bin_body((
const char*)b.data(), b.size());
108 void msgpack_unpack(msgpack::object o);
110 gnutls_pubkey_t pk {};
112 PublicKey(
const PublicKey&) =
delete;
113 PublicKey& operator=(
const PublicKey&) =
delete;
114 void encryptBloc(
const uint8_t* src,
size_t src_size, uint8_t* dst,
size_t dst_size)
const;
135 explicit operator bool()
const {
return key; }
136 PublicKey getPublicKey()
const;
137 Blob serialize(
const std::string& password = {})
const;
161 gnutls_privkey_t key {};
162 gnutls_x509_privkey_t x509_key {};
164 PrivateKey(
const PrivateKey&) =
delete;
165 PrivateKey& operator=(
const PrivateKey&) =
delete;
166 Blob decryptBloc(
const uint8_t* src,
size_t src_size)
const;
174 using clock = std::chrono::system_clock;
175 using time_point = clock::time_point;
176 using duration = clock::duration;
185 void pack(
Blob& b)
const;
186 void unpack(
const uint8_t* dat,
size_t dat_size);
187 Blob getPacked()
const {
193 template <
typename Packer>
194 void msgpack_pack(Packer& p)
const
196 Blob b = getPacked();
197 p.pack_bin(b.size());
198 p.pack_bin_body((
const char*)b.data(), b.size());
201 void msgpack_unpack(msgpack::object o);
203 void revoke(
const Certificate& crt, time_point t = time_point::min());
212 void sign(
const Identity&
id) { sign(*
id.first, *
id.second); }
214 bool isSignedBy(
const Certificate& issuer)
const;
216 std::string toString()
const;
229 time_point getUpdateTime()
const;
230 time_point getNextUpdateTime()
const;
232 gnutls_x509_crl_t get() {
return crl; }
233 gnutls_x509_crl_t getCopy()
const {
237 gnutls_x509_crl_t ret = copy.crl;
243 gnutls_x509_crl_t crl {};
244 RevocationList(
const RevocationList&) =
delete;
245 RevocationList& operator=(
const RevocationList&) =
delete;
264 Certificate(
const std::string& pem) : cert(nullptr) {
265 unpack((
const uint8_t*)pem.data(), pem.size());
267 Certificate(
const uint8_t* dat,
size_t dat_size) : cert(nullptr) {
268 unpack(dat, dat_size);
275 template<
typename Iterator>
284 template<
typename Iterator>
285 Certificate(
const std::vector<std::pair<Iterator, Iterator>>& certs) {
292 void pack(
Blob& b)
const;
293 void unpack(
const uint8_t* dat,
size_t dat_size);
294 Blob getPacked()
const {
308 template<
typename Iterator>
309 void unpack(
const Iterator& begin,
const Iterator& end)
311 std::shared_ptr<Certificate> tmp_subject {};
312 std::shared_ptr<Certificate> first {};
313 for (Iterator icrt = begin; icrt < end; ++icrt) {
314 auto tmp_crt = std::make_shared<Certificate>(*icrt);
316 tmp_subject->issuer = tmp_crt;
317 tmp_subject = std::move(tmp_crt);
335 template<
typename Iterator>
336 void unpack(
const std::vector<std::pair<Iterator, Iterator>>& certs)
338 std::shared_ptr<Certificate> tmp_issuer;
340 for (
auto li = certs.rbegin(); li != certs.rend(); ++li) {
342 gnutls_x509_crt_init(&tmp_crt.cert);
343 const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)};
344 int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM);
345 if (err != GNUTLS_E_SUCCESS)
346 err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER);
347 if (err != GNUTLS_E_SUCCESS)
348 throw CryptoException(std::string(
"Could not read certificate - ") + gnutls_strerror(err));
349 tmp_crt.issuer = tmp_issuer;
350 tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt));
352 *
this = tmp_issuer ? std::move(*tmp_issuer) :
Certificate();
355 template <
typename Packer>
356 void msgpack_pack(Packer& p)
const
360 p.pack_bin(b.size());
361 p.pack_bin_body((
const char*)b.data(), b.size());
364 void msgpack_unpack(msgpack::object o);
366 explicit operator bool()
const {
return cert; }
367 PublicKey getPublicKey()
const;
371 PkId getLongId()
const;
385 enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP };
388 std::vector<std::pair<NameType, std::string>>
getAltNames()
const;
390 std::chrono::system_clock::time_point getActivation()
const;
391 std::chrono::system_clock::time_point getExpiration()
const;
405 std::string print()
const;
408 std::vector<std::shared_ptr<RevocationList>> getRevocationLists()
const;
410 void addRevocationList(std::shared_ptr<RevocationList>);
412 static Certificate generate(
const PrivateKey& key,
const std::string& name =
"dhtnode", Identity ca = {},
bool is_ca =
false);
414 gnutls_x509_crt_t getCopy()
const {
418 gnutls_x509_crt_t ret = copy.cert;
423 std::vector<gnutls_x509_crt_t>
424 getChain(
bool copy =
false)
const
428 std::vector<gnutls_x509_crt_t> crts;
429 for (
auto c =
this; c; c = c->issuer.get())
430 crts.emplace_back(copy ? c->getCopy() : c->cert);
435 std::vector<gnutls_x509_crt_t>,
436 std::vector<gnutls_x509_crl_t>
438 getChainWithRevocations(
bool copy =
false)
const
442 std::vector<gnutls_x509_crt_t> crts;
443 std::vector<gnutls_x509_crl_t> crls;
444 for (
auto c =
this; c; c = c->issuer.get()) {
445 crts.emplace_back(copy ? c->getCopy() : c->cert);
446 crls.reserve(crls.size() + c->revocation_lists.size());
447 for (
const auto& crl : c->revocation_lists)
448 crls.emplace_back(copy ? crl->getCopy() : crl->get());
453 gnutls_x509_crt_t cert {};
454 std::shared_ptr<Certificate> issuer {};
456 Certificate(
const Certificate&) =
delete;
457 Certificate& operator=(
const Certificate&) =
delete;
459 struct crlNumberCmp {
460 bool operator() (
const std::shared_ptr<RevocationList>& lhs,
const std::shared_ptr<RevocationList>& rhs)
const {
461 return lhs->getNumber() < rhs->getNumber();
465 std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists;
473 bool hasError()
const {
return ret < 0; }
474 bool isValid()
const {
return !hasError() and !(result & GNUTLS_CERT_INVALID); }
475 explicit operator bool()
const {
return isValid(); }
476 std::string toString()
const;
477 OPENDHT_PUBLIC
friend std::ostream& operator<< (std::ostream& s,
const VerifyResult& h);
488 void remove(
const Certificate& crt,
bool parents =
true);
494 gnutls_x509_trust_list_t trust;
505 explicit secure_vector(
unsigned size, T _item): data_(size, _item) {}
512 crypto::random_device rdev;
513 std::uniform_int_distribution<uint8_t> rand_byte;
514 std::generate_n((uint8_t*)ret.data_.data(), ret.size()*
sizeof(T), std::bind(rand_byte, std::ref(rdev)));
528 data_ = std::move(c.data_);
533 data_ = std::move(c);
536 std::vector<T>& writable() { clean();
return data_; }
537 const std::vector<T>& makeInsecure()
const {
return data_; }
538 const uint8_t* data()
const {
return data_.data(); }
541 clean(data_.begin(), data_.end());
544 void clear() { clean(); data_.clear(); }
546 size_t size()
const {
return data_.size(); }
547 bool empty()
const {
return data_.empty(); }
550 void resize(
size_t s) {
551 if (s == data_.size())
return;
552 if (s < data_.size()) {
554 clean(data_.begin()+s, data_.end());
558 auto data = std::move(data_);
561 std::copy(data.begin(), data.end(), data_.begin());
562 clean(data.begin(), data.end());
570 static void clean(
const typename std::vector<T>::iterator& i,
const typename std::vector<T>::iterator& j) {
571 volatile uint8_t* b =
reinterpret_cast<uint8_t*
>(&*i);
572 volatile uint8_t* e =
reinterpret_cast<uint8_t*
>(&*j);
576 std::vector<T> data_;
588OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name, Identity ca,
unsigned key_length,
bool is_ca);
589OPENDHT_PUBLIC Identity
generateIdentity(
const std::string& name =
"dhtnode", Identity ca = {},
unsigned key_length = 4096);
591OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name, Identity ca,
bool is_ca);
592OPENDHT_PUBLIC Identity generateEcIdentity(
const std::string& name =
"dhtnode", Identity ca = {});
605OPENDHT_PUBLIC
void hash(
const uint8_t* data,
size_t data_length, uint8_t*
hash,
size_t hash_length);
std::string getIssuerUID() const
void sign(const PrivateKey &, const Certificate &, duration validity_period={})
std::string getIssuerName() const
OPENDHT_PUBLIC Blob stretchKey(const std::string &password, Blob &salt, size_t key_length=512/8)
OPENDHT_PUBLIC Blob hash(const Blob &data, size_t hash_length=512/8)
OPENDHT_PUBLIC Identity generateIdentity(const std::string &name, Identity ca, unsigned key_length, bool is_ca)
OPENDHT_PUBLIC Blob aesDecrypt(const Blob &data, const Blob &key)
OPENDHT_PUBLIC Blob aesEncrypt(const Blob &data, 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)
Certificate(const Blob &crt)
Certificate(gnutls_x509_crt_t crt)
Certificate(const Iterator &begin, const Iterator &end)
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 getName() const
std::vector< std::pair< NameType, std::string > > getAltNames() const
Blob decrypt(const Blob &cypher) const
Blob sign(const Blob &) const
static PrivateKey generate(unsigned key_length=4096)
PrivateKey(gnutls_x509_privkey_t k)
PublicKey(gnutls_pubkey_t k)