From 5c69d3df5a9216fdacb0cc79a3c9c729f64747ed Mon Sep 17 00:00:00 2001 From: Jason Volk <jason@zemos.net> Date: Thu, 5 Oct 2017 18:33:46 -0700 Subject: [PATCH] ircd::crh: Improve hash related interface; comments etc. --- include/ircd/hash.h | 66 +++++++++++++++++++++++++++++++++++++-------- ircd/crypto.cc | 7 ----- ircd/openssl.cc | 11 ++++++-- 3 files changed, 64 insertions(+), 20 deletions(-) diff --git a/include/ircd/hash.h b/include/ircd/hash.h index 02a7d649b..c72296d41 100644 --- a/include/ircd/hash.h +++ b/include/ircd/hash.h @@ -38,8 +38,7 @@ namespace ircd size_t hash(const std::u16string &str, const size_t i = 0); size_t hash(const std::string_view &str, const size_t i = 0); - /// ircd reserves the $ character (in our namespace of course) as an alias - /// for hashing string literals at compile time. + /// ircd:: reserves the $ character over a string as an alias for hash() template<class string> constexpr size_t $(string&& s) { @@ -71,25 +70,39 @@ namespace ircd /// Use this type when dealing with algorithm-agnostic hashing. struct ircd::crh::hash { + /// Returns the byte length of the mutable_raw_buffer for digests virtual size_t length() const = 0; - virtual void finalize(const mutable_raw_buffer &) = 0; - virtual void extract(const mutable_raw_buffer &) const = 0; + + /// Samples the digest at the current state (without modifying) + virtual void digest(const mutable_raw_buffer &) const = 0; + + /// Samples the digest and modifies the state (depending on impl) + virtual void finalize(const mutable_raw_buffer &b) + { + digest(b); + } + + /// Appends to the message virtual void update(const const_raw_buffer &) = 0; - // conveniences - void finalize(const mutable_raw_buffer &) const; + // conveniences for output + template<size_t SIZE> fixed_const_raw_buffer<SIZE> digest() const; + template<size_t SIZE> operator fixed_const_raw_buffer<SIZE>() const; + + // conveniences for input void operator()(const mutable_raw_buffer &out, const const_raw_buffer &in); hash &operator+=(const const_raw_buffer &); virtual ~hash() noexcept; }; +/// SHA-256 hashing device. struct ircd::crh::sha256 :hash { struct ctx; - static constexpr const size_t bytes + static constexpr const size_t digest_size { 256 / 8 }; @@ -98,16 +111,43 @@ struct ircd::crh::sha256 std::unique_ptr<ctx> ctx; public: - size_t length() const override; - void finalize(const mutable_raw_buffer &) override; - void extract(const mutable_raw_buffer &) const override; - void update(const const_raw_buffer &) override; + size_t length() const override final; + void digest(const mutable_raw_buffer &) const override final; + void finalize(const mutable_raw_buffer &) override final; + void update(const const_raw_buffer &) override final; sha256(const mutable_raw_buffer &, const const_raw_buffer &); + sha256(const const_raw_buffer &); sha256(); ~sha256() noexcept; }; +/// Automatic gratification from hash::digest() +template<size_t SIZE> +ircd::crh::hash::operator +fixed_const_raw_buffer<SIZE>() +const +{ + return digest<SIZE>(); +} + +/// Digests the hash into the buffer of the specified SIZE and returns it +template<size_t SIZE> +ircd::fixed_const_raw_buffer<SIZE> +ircd::crh::hash::digest() +const +{ + assert(SIZE >= length()); + return fixed_const_raw_buffer<SIZE> + { + [this](const auto &buffer) + { + this->digest(buffer); + } + }; +} + +/// Runtime hashing of a string_view. Non-cryptographic. inline size_t ircd::hash(const std::string_view &str, const size_t i) @@ -115,6 +155,7 @@ ircd::hash(const std::string_view &str, return i >= str.size()? 7681ULL : (hash(str, i+1) * 33ULL) ^ str.at(i); } +/// Runtime hashing of a std::u16string (for js). Non-cryptographic. inline size_t ircd::hash(const std::u16string &str, const size_t i) @@ -122,6 +163,7 @@ ircd::hash(const std::u16string &str, return i >= str.size()? 7681ULL : (hash(str, i+1) * 33ULL) ^ str.at(i); } +/// Runtime hashing of a std::string. Non-cryptographic. inline size_t ircd::hash(const std::string &str, const size_t i) @@ -129,6 +171,7 @@ ircd::hash(const std::string &str, return i >= str.size()? 7681ULL : (hash(str, i+1) * 33ULL) ^ str.at(i); } +/// Compile-time hashing of a wider string literal (for js). Non-cryptographic. constexpr size_t ircd::hash(const char16_t *const &str, const size_t i) @@ -136,6 +179,7 @@ ircd::hash(const char16_t *const &str, return !str[i]? 7681ULL : (hash(str, i+1) * 33ULL) ^ str[i]; } +/// Compile-time hashing of a string literal. Non-cryptographic. constexpr size_t ircd::hash(const char *const &str, const size_t i) diff --git a/ircd/crypto.cc b/ircd/crypto.cc index 830f60449..323cf3bb6 100644 --- a/ircd/crypto.cc +++ b/ircd/crypto.cc @@ -44,13 +44,6 @@ ircd::crh::hash::operator()(const mutable_raw_buffer &out, finalize(out); } -void -ircd::crh::hash::finalize(const mutable_raw_buffer &buf) -const -{ - extract(buf); -} - /////////////////////////////////////////////////////////////////////////////// // // rand.h diff --git a/ircd/openssl.cc b/ircd/openssl.cc index 5e69b5eb7..6be831582 100644 --- a/ircd/openssl.cc +++ b/ircd/openssl.cc @@ -76,6 +76,13 @@ ircd::crh::sha256::sha256() { } +/// One-shot functor. Immediately calls update(); no output +ircd::crh::sha256::sha256(const const_raw_buffer &in) +:sha256{} +{ + update(in); +} + /// One-shot functor. Immediately calls operator(). ircd::crh::sha256::sha256(const mutable_raw_buffer &out, const const_raw_buffer &in) @@ -96,7 +103,7 @@ ircd::crh::sha256::update(const const_raw_buffer &buf) } void -ircd::crh::sha256::extract(const mutable_raw_buffer &buf) +ircd::crh::sha256::digest(const mutable_raw_buffer &buf) const { auto copy(*ctx); @@ -113,7 +120,7 @@ size_t ircd::crh::sha256::length() const { - return bytes; + return digest_size; } void