#ifndef XRPL_BASICS_HARDENED_HASH_H_INCLUDED #define XRPL_BASICS_HARDENED_HASH_H_INCLUDED #include #include #include #include #include #include namespace ripple { namespace detail { using seed_pair = std::pair; template seed_pair make_seed_pair() noexcept { struct state_t { std::mutex mutex; std::random_device rng; std::mt19937_64 gen; std::uniform_int_distribution dist; state_t() : gen(rng()) { } // state_t(state_t const&) = delete; // state_t& operator=(state_t const&) = delete; }; static state_t state; std::lock_guard lock(state.mutex); return {state.dist(state.gen), state.dist(state.gen)}; } } // namespace detail /** * Seed functor once per construction A std compatible hash adapter that resists adversarial inputs. For this to work, T must implement in its own namespace: @code template void hash_append (Hasher& h, T const& t) noexcept { // hash_append each base and member that should // participate in forming the hash using beast::hash_append; hash_append (h, static_cast(t)); hash_append (h, static_cast(t)); // ... hash_append (h, t.member1); hash_append (h, t.member2); // ... } @endcode Do not use any version of Murmur or CityHash for the Hasher template parameter (the hashing algorithm). For details see https://131002.net/siphash/#at */ template class hardened_hash { private: detail::seed_pair m_seeds; public: using result_type = typename HashAlgorithm::result_type; hardened_hash() : m_seeds(detail::make_seed_pair<>()) { } template result_type operator()(T const& t) const noexcept { HashAlgorithm h(m_seeds.first, m_seeds.second); hash_append(h, t); return static_cast(h); } }; } // namespace ripple #endif