diff --git a/include/opendht/crypto.h b/include/opendht/crypto.h index ee88ad0d..4f66b764 100644 --- a/include/opendht/crypto.h +++ b/include/opendht/crypto.h @@ -83,6 +83,7 @@ struct OPENDHT_PUBLIC PublicKey PublicKey& operator=(PublicKey&& o) noexcept; InfoHash getId() const; + PkId getLongId() const; bool checkSignature(const Blob& data, const Blob& signature) const; Blob encrypt(const Blob&) const; @@ -350,6 +351,7 @@ struct OPENDHT_PUBLIC Certificate { /** Same as getPublicKey().getId() */ InfoHash getId() const; + PkId getLongId() const; /** Read certificate Common Name (CN) */ std::string getName() const; diff --git a/include/opendht/infohash.h b/include/opendht/infohash.h index 4e7e40d2..e6d23b78 100644 --- a/include/opendht/infohash.h +++ b/include/opendht/infohash.h @@ -50,6 +50,51 @@ typedef uint16_t in_port_t; namespace dht { +using byte = uint8_t; + +template +class OPENDHT_PUBLIC Hash +{ +public: + Hash() { + data_.fill(0); + } + Hash(const msgpack::object& o) { + msgpack_unpack(o); + } + byte* data() { + return data_.data(); + } + const byte* data() const { + return data_.data(); + } + constexpr size_t size() const { return data_.size(); } + explicit operator bool() const { return std::any_of(data_.begin(), data_.end(), [](byte _b) { return _b != 0; }); } + bool operator==(Hash const& _c) const { return data_ == _c.data_; } + bool operator!=(Hash const& _c) const { return data_ != _c.data_; } + bool operator<(Hash const& _c) const { for (unsigned i = 0; i < N; ++i) if (data_[i] < _c.data_[i]) return true; else if (data_[i] > _c.data_[i]) return false; return false; } + bool operator>=(Hash const& _c) const { return !operator<(_c); } + bool operator<=(Hash const& _c) const { return operator==(_c) || operator<(_c); } + bool operator>(Hash const& _c) const { return !operator<=(_c); } + template + void msgpack_pack(Packer& pk) const + { + pk.pack_bin(N); + pk.pack_bin_body((char*)data_.data(), N); + } + void msgpack_unpack(msgpack::object o) { + if (o.type != msgpack::type::BIN or o.via.bin.size != N) + throw msgpack::type_error(); + std::copy_n(o.via.bin.ptr, N, data_.data()); + } + +private: + std::array data_; +}; + +using h256 = Hash<32>; +using PkId = h256; + /** * Represents an InfoHash. * An InfoHash is a byte array of HASH_LEN bytes. diff --git a/src/crypto.cpp b/src/crypto.cpp index c4844efc..d7a30c63 100644 --- a/src/crypto.cpp +++ b/src/crypto.cpp @@ -517,6 +517,16 @@ PublicKey::getId() const return id; } +PkId +PublicKey::getLongId() const +{ + PkId h; + size_t sz = h.size(); + if (gnutls_pubkey_get_key_id(pk, GNUTLS_KEYID_USE_SHA256, h.data(), &sz) != GNUTLS_E_SUCCESS || sz != h.size()) + return {}; + return h; +} + Certificate::Certificate(const Blob& certData) : cert(nullptr) { unpack(certData.data(), certData.size()); @@ -621,6 +631,18 @@ Certificate::getId() const return id; } +PkId +Certificate::getLongId() const +{ + if (not cert) + return {}; + PkId id; + size_t sz = id.size(); + if (gnutls_x509_crt_get_key_id(cert, GNUTLS_KEYID_USE_SHA256, id.data(), &sz) != GNUTLS_E_SUCCESS || sz != id.size()) + throw CryptoException("Can't get certificate public key ID."); + return id; +} + static std::string getDN(gnutls_x509_crt_t cert, const char* oid, bool issuer = false) {