diff --git a/include/ircd/hash.h b/include/ircd/hash.h index 80268c88e..60d8bab00 100644 --- a/include/ircd/hash.h +++ b/include/ircd/hash.h @@ -36,6 +36,7 @@ namespace ircd::crh struct hash; struct sha256; + struct ripemd160; } // Export aliases down to ircd:: @@ -43,6 +44,7 @@ namespace ircd { using crh::hash; using crh::sha256; + using crh::ripemd160; } /// Abstract interface to a hashing context for any algorithm in ircd::crh @@ -105,6 +107,35 @@ final ~sha256() noexcept; }; +/// RIPEMD160 hashing device. +struct ircd::crh::ripemd160 +final +:hash +{ + struct ctx; + + static constexpr const size_t digest_size + { + 160 / 8 + }; + + using buf = fixed_const_buffer; + + protected: + std::unique_ptr ctx; + + public: + size_t length() const override; + void digest(const mutable_buffer &) const override; + void finalize(const mutable_buffer &) override; + void update(const const_buffer &) override; + + ripemd160(const mutable_buffer &, const const_buffer &); + ripemd160(const const_buffer &); + ripemd160(); + ~ripemd160() noexcept; +}; + /// Automatic gratification from hash::digest() template ircd::crh::hash::operator diff --git a/ircd/openssl.cc b/ircd/openssl.cc index 02c7137aa..41dc5996d 100644 --- a/ircd/openssl.cc +++ b/ircd/openssl.cc @@ -15,6 +15,7 @@ #include #include #include +#include namespace ircd::openssl { @@ -1368,6 +1369,10 @@ ircd::openssl::init::~init() // hash.h // +// +// sha256 +// + namespace ircd::crh { static void finalize(struct sha256::ctx *const &, const mutable_buffer &); @@ -1454,6 +1459,97 @@ ircd::crh::finalize(struct sha256::ctx *const &ctx, openssl::call(::SHA256_Final, md, ctx); } +// +// ripemd160 +// + +namespace ircd::crh +{ + static void finalize(struct ripemd160::ctx *const &, const mutable_buffer &); +} + +struct ircd::crh::ripemd160::ctx +:RIPEMD160_CTX +{ + ctx(); + ~ctx() noexcept; +}; + +ircd::crh::ripemd160::ctx::ctx() +{ + openssl::call(::RIPEMD160_Init, this); +} + +ircd::crh::ripemd160::ctx::~ctx() +noexcept +{ +} + +ircd::crh::ripemd160::ripemd160() +:ctx{std::make_unique()} +{ +} + +/// One-shot functor. Immediately calls update(); no output +ircd::crh::ripemd160::ripemd160(const const_buffer &in) +:ripemd160{} +{ + update(in); +} + +/// One-shot functor. Immediately calls operator(). +ircd::crh::ripemd160::ripemd160(const mutable_buffer &out, + const const_buffer &in) +:ripemd160{} +{ + operator()(out, in); +} + +ircd::crh::ripemd160::~ripemd160() +noexcept +{ +} + +void +ircd::crh::ripemd160::update(const const_buffer &buf) +{ + openssl::call(::RIPEMD160_Update, ctx.get(), data(buf), size(buf)); +} + +void +ircd::crh::ripemd160::digest(const mutable_buffer &buf) +const +{ + assert(bool(ctx)); + auto copy(*ctx); + crh::finalize(©, buf); +} + +void +ircd::crh::ripemd160::finalize(const mutable_buffer &buf) +{ + crh::finalize(ctx.get(), buf); +} + +size_t +ircd::crh::ripemd160::length() +const +{ + return digest_size; +} + +void +ircd::crh::finalize(struct ripemd160::ctx *const &ctx, + const mutable_buffer &buf) +{ + uint8_t *const md + { + reinterpret_cast(data(buf)) + }; + + openssl::call(::RIPEMD160_Final, md, ctx); +} + /////////////////////////////////////////////////////////////////////////////// // // Internal section for OpenSSL locking.