1 /* 2 * Copyright (C) 2014-2019 Savoir-faire Linux Inc. 3 * Author : Adrien Béraud <adrien.beraud@savoirfairelinux.com> 4 * 5 * This program is free software; you can redistribute it and/or modify 6 * it under the terms of the GNU General Public License as published by 7 * the Free Software Foundation; either version 3 of the License, or 8 * (at your option) any later version. 9 * 10 * This program is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 * GNU General Public License for more details. 14 * 15 * You should have received a copy of the GNU General Public License 16 * along with this program. If not, see <https://www.gnu.org/licenses/>. 17 */ 18 19 #pragma once 20 21 #include "infohash.h" 22 #include "utils.h" 23 #include "rng.h" 24 25 extern "C" { 26 #include <gnutls/gnutls.h> 27 #include <gnutls/abstract.h> 28 #include <gnutls/x509.h> 29 } 30 31 #include <vector> 32 #include <memory> 33 34 #ifdef _WIN32 35 #include <iso646.h> 36 #endif 37 38 namespace dht { 39 40 /** 41 * Contains all crypto primitives 42 */ 43 namespace crypto { 44 45 class OPENDHT_PUBLIC CryptoException : public std::runtime_error { 46 public: CryptoException(const std::string & str)47 CryptoException(const std::string& str) : std::runtime_error(str) {}; 48 }; 49 50 /** 51 * Exception thrown when a decryption error happened. 52 */ 53 class OPENDHT_PUBLIC DecryptError : public CryptoException { 54 public: CryptoException(str)55 DecryptError(const std::string& str = "") : CryptoException(str) {}; 56 }; 57 58 struct PrivateKey; 59 struct Certificate; 60 class RevocationList; 61 62 using Identity = std::pair<std::shared_ptr<PrivateKey>, std::shared_ptr<Certificate>>; 63 64 /** 65 * A public key. 66 */ 67 struct OPENDHT_PUBLIC PublicKey 68 { 69 PublicKey(); 70 71 /** 72 * Takes ownership of an existing gnutls_pubkey. 73 */ PublicKeyPublicKey74 PublicKey(gnutls_pubkey_t k) : pk(k) {} 75 PublicKey(const Blob& pk); PublicKeyPublicKey76 PublicKey(PublicKey&& o) noexcept : pk(o.pk) { o.pk = nullptr; }; 77 78 ~PublicKey(); 79 explicit operator bool() const { return pk; } 80 bool operator ==(const PublicKey& o) const { 81 return pk == o.pk || getId() == o.getId(); 82 } 83 bool operator !=(const PublicKey& o) const { 84 return !(*this == o); 85 } 86 87 PublicKey& operator=(PublicKey&& o) noexcept; 88 89 /** 90 * Get public key fingerprint 91 */ 92 InfoHash getId() const; 93 94 /** 95 * Get public key long fingerprint 96 */ 97 PkId getLongId() const; 98 99 bool checkSignature(const Blob& data, const Blob& signature) const; 100 Blob encrypt(const Blob&) const; 101 102 void pack(Blob& b) const; 103 void unpack(const uint8_t* dat, size_t dat_size); 104 105 std::string toString() const; 106 107 template <typename Packer> msgpack_packPublicKey108 void msgpack_pack(Packer& p) const 109 { 110 Blob b; 111 pack(b); 112 p.pack_bin(b.size()); 113 p.pack_bin_body((const char*)b.data(), b.size()); 114 } 115 116 void msgpack_unpack(msgpack::object o); 117 118 gnutls_digest_algorithm_t getPreferredDigest() const; 119 120 gnutls_pubkey_t pk {nullptr}; 121 private: 122 PublicKey(const PublicKey&) = delete; 123 PublicKey& operator=(const PublicKey&) = delete; 124 void encryptBloc(const uint8_t* src, size_t src_size, uint8_t* dst, size_t dst_size) const; 125 }; 126 127 /** 128 * A private key, including the corresponding public key. 129 */ 130 struct OPENDHT_PUBLIC PrivateKey 131 { 132 PrivateKey(); 133 //PrivateKey(gnutls_privkey_t k) : key(k) {} 134 135 /** 136 * Takes ownership of an existing gnutls_x509_privkey. 137 */ 138 PrivateKey(gnutls_x509_privkey_t k); 139 140 PrivateKey(PrivateKey&& o) noexcept; 141 PrivateKey& operator=(PrivateKey&& o) noexcept; 142 143 PrivateKey(const Blob& import, const std::string& password = {}); 144 ~PrivateKey(); 145 explicit operator bool() const { return key; } 146 147 PublicKey getPublicKey() const; 148 Blob serialize(const std::string& password = {}) const; 149 150 /** 151 * Sign the provided binary object. 152 * @returns the signature data. 153 */ 154 Blob sign(const Blob&) const; 155 156 /** 157 * Try to decrypt the provided cypher text. 158 * In case of failure a CryptoException is thrown. 159 * @returns the decrypted data. 160 */ 161 Blob decrypt(const Blob& cypher) const; 162 163 /** 164 * Generate a new RSA key pair 165 * @param key_length : size of the modulus in bits 166 * Minimim value: 2048 167 * Recommended values: 4096, 8192 168 */ 169 static PrivateKey generate(unsigned key_length = 4096); 170 static PrivateKey generateEC(); 171 172 gnutls_privkey_t key {}; 173 gnutls_x509_privkey_t x509_key {}; 174 private: 175 PrivateKey(const PrivateKey&) = delete; 176 PrivateKey& operator=(const PrivateKey&) = delete; 177 Blob decryptBloc(const uint8_t* src, size_t src_size) const; 178 179 //friend dht::crypto::Identity dht::crypto::generateIdentity(const std::string&, dht::crypto::Identity, unsigned key_length); 180 }; 181 182 183 class OPENDHT_PUBLIC RevocationList 184 { 185 using clock = std::chrono::system_clock; 186 using time_point = clock::time_point; 187 using duration = clock::duration; 188 public: 189 RevocationList(); 190 RevocationList(const Blob& b); RevocationList(RevocationList && o)191 RevocationList(RevocationList&& o) noexcept : crl(o.crl) { o.crl = nullptr; } 192 ~RevocationList(); 193 194 RevocationList& operator=(RevocationList&& o) { crl = o.crl; o.crl = nullptr; return *this; } 195 196 void pack(Blob& b) const; 197 void unpack(const uint8_t* dat, size_t dat_size); getPacked()198 Blob getPacked() const { 199 Blob b; 200 pack(b); 201 return b; 202 } 203 204 template <typename Packer> msgpack_pack(Packer & p)205 void msgpack_pack(Packer& p) const 206 { 207 Blob b = getPacked(); 208 p.pack_bin(b.size()); 209 p.pack_bin_body((const char*)b.data(), b.size()); 210 } 211 212 void msgpack_unpack(msgpack::object o); 213 214 void revoke(const Certificate& crt, time_point t = time_point::min()); 215 216 bool isRevoked(const Certificate& crt) const; 217 218 /** 219 * Sign this revocation list using provided key and certificate. 220 * Validity_period sets the duration until next update (default to no next update). 221 */ 222 void sign(const PrivateKey&, const Certificate&, duration validity_period = {}); sign(const Identity & id)223 void sign(const Identity& id) { sign(*id.first, *id.second); } 224 225 bool isSignedBy(const Certificate& issuer) const; 226 227 std::string toString() const; 228 229 /** 230 * Read the CRL number extension field. 231 */ 232 Blob getNumber() const; 233 234 /** Read CRL issuer Common Name (CN) */ 235 std::string getIssuerName() const; 236 237 /** Read CRL issuer User ID (UID) */ 238 std::string getIssuerUID() const; 239 240 time_point getUpdateTime() const; 241 time_point getNextUpdateTime() const; 242 get()243 gnutls_x509_crl_t get() { return crl; } getCopy()244 gnutls_x509_crl_t getCopy() const { 245 if (not crl) 246 return nullptr; 247 auto copy = RevocationList(getPacked()); 248 gnutls_x509_crl_t ret = copy.crl; 249 copy.crl = nullptr; 250 return ret; 251 } 252 253 private: 254 gnutls_x509_crl_t crl {}; 255 RevocationList(const RevocationList&) = delete; 256 RevocationList& operator=(const RevocationList&) = delete; 257 }; 258 259 enum class NameType { UNKNOWN = 0, RFC822, DNS, URI, IP }; 260 261 class OPENDHT_PUBLIC CertificateRequest { 262 public: 263 CertificateRequest(); 264 CertificateRequest(const uint8_t* data, size_t size); CertificateRequest(const Blob & data)265 CertificateRequest(const Blob& data) : CertificateRequest(data.data(), data.size()) {} 266 CertificateRequest(CertificateRequest && o)267 CertificateRequest(CertificateRequest&& o) noexcept : request(std::move(o.request)) { 268 o.request = nullptr; 269 } 270 CertificateRequest& operator=(CertificateRequest&& o) noexcept; 271 272 ~CertificateRequest(); 273 274 void setName(const std::string& name); 275 void setUID(const std::string& name); 276 void setAltName(NameType type, const std::string& name); 277 278 std::string getName() const; 279 std::string getUID() const; 280 281 void sign(const PrivateKey& key, const std::string& password = {}); 282 283 bool verify() const; 284 285 Blob pack() const; 286 get()287 gnutls_x509_crq_t get() const { return request; } 288 private: 289 CertificateRequest(const CertificateRequest& o) = delete; 290 CertificateRequest& operator=(const CertificateRequest& o) = delete; 291 gnutls_x509_crq_t request {nullptr}; 292 }; 293 294 struct OPENDHT_PUBLIC Certificate { CertificateCertificate295 Certificate() noexcept {} 296 297 /** 298 * Take ownership of existing gnutls structure 299 */ CertificateCertificate300 Certificate(gnutls_x509_crt_t crt) noexcept : cert(crt) {} 301 CertificateCertificate302 Certificate(Certificate&& o) noexcept : cert(o.cert), issuer(std::move(o.issuer)) { o.cert = nullptr; }; 303 304 /** 305 * Import certificate (PEM or DER) or certificate chain (PEM), 306 * ordered from subject to issuer 307 */ 308 Certificate(const Blob& crt); CertificateCertificate309 Certificate(const std::string& pem) : cert(nullptr) { 310 unpack((const uint8_t*)pem.data(), pem.size()); 311 } CertificateCertificate312 Certificate(const uint8_t* dat, size_t dat_size) : cert(nullptr) { 313 unpack(dat, dat_size); 314 } 315 316 /** 317 * Import certificate chain (PEM or DER), 318 * ordered from subject to issuer 319 */ 320 template<typename Iterator> CertificateCertificate321 Certificate(const Iterator& begin, const Iterator& end) { 322 unpack(begin, end); 323 } 324 325 /** 326 * Import certificate chain (PEM or DER), 327 * ordered from subject to issuer 328 */ 329 template<typename Iterator> CertificateCertificate330 Certificate(const std::vector<std::pair<Iterator, Iterator>>& certs) { 331 unpack(certs); 332 } 333 334 Certificate& operator=(Certificate&& o) noexcept; 335 ~Certificate(); 336 337 void pack(Blob& b) const; 338 void unpack(const uint8_t* dat, size_t dat_size); getPackedCertificate339 Blob getPacked() const { 340 Blob b; 341 pack(b); 342 return b; 343 } 344 345 /** 346 * Import certificate chain (PEM or DER). 347 * Certificates are not checked during import. 348 * 349 * Iterator is the type of an iterator or pointer to 350 * gnutls_x509_crt_t or Blob instances to import, that should be 351 * ordered from subject to issuer. 352 */ 353 template<typename Iterator> unpackCertificate354 void unpack(const Iterator& begin, const Iterator& end) 355 { 356 std::shared_ptr<Certificate> tmp_subject {}; 357 std::shared_ptr<Certificate> first {}; 358 for (Iterator icrt = begin; icrt < end; ++icrt) { 359 auto tmp_crt = std::make_shared<Certificate>(*icrt); 360 if (tmp_subject) 361 tmp_subject->issuer = tmp_crt; 362 tmp_subject = std::move(tmp_crt); 363 if (!first) 364 first = tmp_subject; 365 } 366 *this = first ? std::move(*first) : Certificate(); 367 } 368 369 /** 370 * Import certificate chain (PEM or DER). 371 * Certificates are not checked during import. 372 * 373 * Iterator is the type of an iterator or pointer to the bytes of 374 * the certificates to import. 375 * 376 * @param certs list of (begin, end) iterator pairs, pointing to the 377 * PEM or DER certificate data to import, that should be 378 * ordered from subject to issuer. 379 */ 380 template<typename Iterator> unpackCertificate381 void unpack(const std::vector<std::pair<Iterator, Iterator>>& certs) 382 { 383 std::shared_ptr<Certificate> tmp_issuer; 384 // reverse iteration 385 for (auto li = certs.rbegin(); li != certs.rend(); ++li) { 386 Certificate tmp_crt; 387 gnutls_x509_crt_init(&tmp_crt.cert); 388 const gnutls_datum_t crt_dt {(uint8_t*)&(*li->first), (unsigned)(li->second-li->first)}; 389 int err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_PEM); 390 if (err != GNUTLS_E_SUCCESS) 391 err = gnutls_x509_crt_import(tmp_crt.cert, &crt_dt, GNUTLS_X509_FMT_DER); 392 if (err != GNUTLS_E_SUCCESS) 393 throw CryptoException(std::string("Could not read certificate - ") + gnutls_strerror(err)); 394 tmp_crt.issuer = tmp_issuer; 395 tmp_issuer = std::make_shared<Certificate>(std::move(tmp_crt)); 396 } 397 *this = tmp_issuer ? std::move(*tmp_issuer) : Certificate(); 398 } 399 400 template <typename Packer> msgpack_packCertificate401 void msgpack_pack(Packer& p) const 402 { 403 Blob b; 404 pack(b); 405 p.pack_bin(b.size()); 406 p.pack_bin_body((const char*)b.data(), b.size()); 407 } 408 409 void msgpack_unpack(msgpack::object o); 410 411 explicit operator bool() const { return cert; } 412 PublicKey getPublicKey() const; 413 414 /** Same as getPublicKey().getId() */ 415 InfoHash getId() const; 416 /** Same as getPublicKey().getLongId() */ 417 PkId getLongId() const; 418 419 /** Read certificate Common Name (CN) */ 420 std::string getName() const; 421 422 /** Read certificate User ID (UID) */ 423 std::string getUID() const; 424 425 /** Read certificate issuer Common Name (CN) */ 426 std::string getIssuerName() const; 427 428 /** Read certificate issuer User ID (UID) */ 429 std::string getIssuerUID() const; 430 431 /** Read certificate alternative names */ 432 std::vector<std::pair<NameType, std::string>> getAltNames() const; 433 434 std::chrono::system_clock::time_point getActivation() const; 435 std::chrono::system_clock::time_point getExpiration() const; 436 437 /** 438 * Returns true if the certificate is marked as a Certificate Authority 439 * and has necessary key usage flags to sign certificates. 440 */ 441 bool isCA() const; 442 443 /** 444 * PEM encoded certificate. 445 * If chain is true, the issuer chain will be included (default). 446 */ 447 std::string toString(bool chain = true) const; 448 449 std::string print() const; 450 451 /** 452 * As a CA, revoke a certificate, adding it to 453 * the attached Certificate Revocation List (CRL) 454 */ 455 void revoke(const PrivateKey&, const Certificate&); 456 457 /** 458 * Get the list of certificates revoked as as CA. 459 */ 460 std::vector<std::shared_ptr<RevocationList>> getRevocationLists() const; 461 462 /** 463 * Attach existing revocation list. 464 */ 465 void addRevocationList(RevocationList&&); 466 void addRevocationList(std::shared_ptr<RevocationList>); 467 468 static Certificate generate(const PrivateKey& key, const std::string& name = "dhtnode", const Identity& ca = {}, bool is_ca = false); 469 static Certificate generate(const CertificateRequest& request, const Identity& ca); 470 getCopyCertificate471 gnutls_x509_crt_t getCopy() const { 472 if (not cert) 473 return nullptr; 474 auto copy = Certificate(getPacked()); 475 gnutls_x509_crt_t ret = copy.cert; 476 copy.cert = nullptr; 477 return ret; 478 } 479 480 std::vector<gnutls_x509_crt_t> 481 getChain(bool copy = false) const 482 { 483 if (not cert) 484 return {}; 485 std::vector<gnutls_x509_crt_t> crts; 486 for (auto c = this; c; c = c->issuer.get()) 487 crts.emplace_back(copy ? c->getCopy() : c->cert); 488 return crts; 489 } 490 491 std::pair< 492 std::vector<gnutls_x509_crt_t>, 493 std::vector<gnutls_x509_crl_t> 494 > 495 getChainWithRevocations(bool copy = false) const 496 { 497 if (not cert) 498 return {}; 499 std::vector<gnutls_x509_crt_t> crts; 500 std::vector<gnutls_x509_crl_t> crls; 501 for (auto c = this; c; c = c->issuer.get()) { 502 crts.emplace_back(copy ? c->getCopy() : c->cert); 503 crls.reserve(crls.size() + c->revocation_lists.size()); 504 for (const auto& crl : c->revocation_lists) 505 crls.emplace_back(copy ? crl->getCopy() : crl->get()); 506 } 507 return {crts, crls}; 508 } 509 510 gnutls_digest_algorithm_t getPreferredDigest() const; 511 512 gnutls_x509_crt_t cert {nullptr}; 513 std::shared_ptr<Certificate> issuer {}; 514 private: 515 Certificate(const Certificate&) = delete; 516 Certificate& operator=(const Certificate&) = delete; 517 518 struct crlNumberCmp { operatorCertificate::crlNumberCmp519 bool operator() (const std::shared_ptr<RevocationList>& lhs, const std::shared_ptr<RevocationList>& rhs) const { 520 return lhs->getNumber() < rhs->getNumber(); 521 } 522 }; 523 524 std::set<std::shared_ptr<RevocationList>, crlNumberCmp> revocation_lists; 525 }; 526 527 struct OPENDHT_PUBLIC TrustList 528 { 529 struct VerifyResult { 530 int ret; 531 unsigned result; hasErrorTrustList::VerifyResult532 bool hasError() const { return ret < 0; } isValidTrustList::VerifyResult533 bool isValid() const { return !hasError() and !(result & GNUTLS_CERT_INVALID); } 534 explicit operator bool() const { return isValid(); } 535 std::string toString() const; 536 OPENDHT_PUBLIC friend std::ostream& operator<< (std::ostream& s, const VerifyResult& h); 537 }; 538 539 TrustList(); TrustListTrustList540 TrustList(TrustList&& o) noexcept : trust(std::move(o.trust)) { 541 o.trust = nullptr; 542 } 543 TrustList& operator=(TrustList&& o) noexcept; 544 ~TrustList(); 545 void add(const Certificate& crt); 546 void add(const RevocationList& crl); 547 void remove(const Certificate& crt, bool parents = true); 548 VerifyResult verify(const Certificate& crt) const; 549 550 private: 551 TrustList(const TrustList& o) = delete; 552 TrustList& operator=(const TrustList& o) = delete; 553 gnutls_x509_trust_list_t trust {nullptr}; 554 }; 555 556 template <class T> 557 class OPENDHT_PUBLIC secure_vector 558 { 559 public: secure_vector()560 secure_vector() {} 561 secure_vector(secure_vector<T> const&) = default; 562 secure_vector(secure_vector<T> &&) = default; secure_vector(unsigned size)563 explicit secure_vector(unsigned size): data_(size) {} secure_vector(unsigned size,T _item)564 explicit secure_vector(unsigned size, T _item): data_(size, _item) {} secure_vector(const std::vector<T> & c)565 explicit secure_vector(const std::vector<T>& c): data_(c) {} secure_vector(std::vector<T> && c)566 secure_vector(std::vector<T>&& c): data_(std::move(c)) {} ~secure_vector()567 ~secure_vector() { clean(); } 568 getRandom(size_t size)569 static secure_vector<T> getRandom(size_t size) { 570 secure_vector<T> ret(size); 571 crypto::random_device rdev; 572 #ifdef _WIN32 573 std::uniform_int_distribution<int> rand_byte{ 0, std::numeric_limits<uint8_t>::max() }; 574 #else 575 std::uniform_int_distribution<uint8_t> rand_byte; 576 #endif 577 std::generate_n((uint8_t*)ret.data_.data(), ret.size()*sizeof(T), std::bind(rand_byte, std::ref(rdev))); 578 return ret; 579 } 580 secure_vector<T>& operator=(const secure_vector<T>& c) { 581 if (&c == this) 582 return *this; 583 clean(); 584 data_ = c.data_; 585 return *this; 586 } 587 secure_vector<T>& operator=(secure_vector<T>&& c) { 588 if (&c == this) 589 return *this; 590 clean(); 591 data_ = std::move(c.data_); 592 return *this; 593 } 594 secure_vector<T>& operator=(std::vector<T>&& c) { 595 clean(); 596 data_ = std::move(c); 597 return *this; 598 } writable()599 std::vector<T>& writable() { clean(); return data_; } makeInsecure()600 const std::vector<T>& makeInsecure() const { return data_; } data()601 const uint8_t* data() const { return data_.data(); } 602 clean()603 void clean() { 604 clean(data_.begin(), data_.end()); 605 } 606 clear()607 void clear() { clean(); data_.clear(); } 608 size()609 size_t size() const { return data_.size(); } empty()610 bool empty() const { return data_.empty(); } 611 swap(secure_vector<T> & other)612 void swap(secure_vector<T>& other) { data_.swap(other.data_); } resize(size_t s)613 void resize(size_t s) { 614 if (s == data_.size()) return; 615 if (s < data_.size()) { 616 //shrink 617 clean(data_.begin()+s, data_.end()); 618 data_.resize(s); 619 } else { 620 //grow 621 auto data = std::move(data_); // move protected data 622 clear(); 623 data_.resize(s); 624 std::copy(data.begin(), data.end(), data_.begin()); 625 clean(data.begin(), data.end()); 626 } 627 } 628 629 private: 630 /** 631 * Securely wipe memory 632 */ clean(const typename std::vector<T>::iterator & i,const typename std::vector<T>::iterator & j)633 static void clean(const typename std::vector<T>::iterator& i, const typename std::vector<T>::iterator& j) { 634 volatile uint8_t* b = reinterpret_cast<uint8_t*>(&*i); 635 volatile uint8_t* e = reinterpret_cast<uint8_t*>(&*j); 636 std::fill(b, e, 0); 637 } 638 639 std::vector<T> data_; 640 }; 641 642 using SecureBlob = secure_vector<uint8_t>; 643 644 /** 645 * Generate an RSA key pair (4096 bits) and a certificate. 646 * @param name the name used in the generated certificate 647 * @param ca if set, the certificate authority that will sign the generated certificate. 648 * If not set, the generated certificate will be a self-signed CA. 649 * @param key_length stength of the generated private key (bits). 650 */ 651 OPENDHT_PUBLIC Identity generateIdentity(const std::string& name, const Identity& ca, unsigned key_length, bool is_ca); 652 OPENDHT_PUBLIC Identity generateIdentity(const std::string& name = "dhtnode", const Identity& ca = {}, unsigned key_length = 4096); 653 654 OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name, const Identity& ca, bool is_ca); 655 OPENDHT_PUBLIC Identity generateEcIdentity(const std::string& name = "dhtnode", const Identity& ca = {}); 656 657 OPENDHT_PUBLIC void saveIdentity(const Identity& id, const std::string& path, const std::string& privkey_password = {}); 658 659 /** 660 * Performs SHA512, SHA256 or SHA1, depending on hash_length. 661 * Attempts to choose an hash function with 662 * output size of at least hash_length bytes, Current implementation 663 * will use SHA1 for hash_length up to 20 bytes, 664 * will use SHA256 for hash_length up to 32 bytes, 665 * will use SHA512 for hash_length of 33 bytes and more. 666 */ 667 OPENDHT_PUBLIC Blob hash(const Blob& data, size_t hash_length = 512/8); 668 669 OPENDHT_PUBLIC void hash(const uint8_t* data, size_t data_length, uint8_t* hash, size_t hash_length); 670 671 /** 672 * Generates an encryption key from a text password, 673 * making the key longer to bruteforce. 674 * The generated key also depends on a unique salt value of any size, 675 * that can be transmitted in clear, and will be generated if 676 * not provided (32 bytes). 677 */ 678 OPENDHT_PUBLIC Blob stretchKey(const std::string& password, Blob& salt, size_t key_length = 512/8); 679 680 /** 681 * AES-GCM encryption. Key must be 128, 192 or 256 bits long (16, 24 or 32 bytes). 682 */ 683 OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, const Blob& key); 684 OPENDHT_PUBLIC Blob aesEncrypt(const Blob& data, const std::string& password); 685 686 /** 687 * AES-GCM decryption. 688 */ 689 OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const Blob& key); 690 OPENDHT_PUBLIC Blob aesDecrypt(const Blob& data, const std::string& password); 691 692 } 693 } 694