/* * Copyright (C) 2019-present ScyllaDB */ /* * SPDX-License-Identifier: LicenseRef-ScyllaDB-Source-Available-1.0 */ #include "utils/hashers.hh" #include "utils/xx_hasher.hh" #include "utils/simple_hashers.hh" #define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1 #include #include static_assert(Hasher); static_assert(HasherReturningBytes); static_assert(HasherReturningBytes); static_assert(HasherReturningBytes); static_assert(SimpleHasher); template struct hasher_traits; template <> struct hasher_traits { using impl_type = CryptoPP::Weak::MD5; }; template <> struct hasher_traits { using impl_type = CryptoPP::SHA256; }; template concept HashUpdater = requires(typename hasher_traits::impl_type& h, const CryptoPP::byte* ptr, size_t size) { // We need Update() not to throw, but it isn't marked noexcept // in CryptoPP source. We'll just hope it doesn't throw. { h.Update(ptr, size) } -> std::same_as; }; template struct cryptopp_hasher::impl { static_assert(HashUpdater); using impl_type = typename hasher_traits::impl_type; impl_type hash{}; void update(const char* ptr, size_t length) noexcept { using namespace CryptoPP; static_assert(sizeof(char) == sizeof(byte), "Assuming lengths will be the same"); hash.Update(reinterpret_cast(ptr), length * sizeof(byte)); } bytes finalize() { bytes digest{bytes::initialized_later(), size}; hash.Final(reinterpret_cast(digest.begin())); return digest; } std::array finalize_array() { std::array array; hash.Final(reinterpret_cast(array.data())); return array; } }; template cryptopp_hasher::cryptopp_hasher() : _impl(std::make_unique()) {} template cryptopp_hasher::~cryptopp_hasher() = default; template cryptopp_hasher::cryptopp_hasher(cryptopp_hasher&& o) noexcept = default; template cryptopp_hasher::cryptopp_hasher(const cryptopp_hasher& o) : _impl(std::make_unique::impl>(*o._impl)) {} template cryptopp_hasher& cryptopp_hasher::operator=(cryptopp_hasher&& o) noexcept = default; template cryptopp_hasher& cryptopp_hasher::operator=(const cryptopp_hasher& o) { _impl = std::make_unique::impl>(*o._impl); return *this; } template bytes cryptopp_hasher::finalize() { return _impl->finalize(); } template std::array cryptopp_hasher::finalize_array() { return _impl->finalize_array(); } template void cryptopp_hasher::update(const char* ptr, size_t length) noexcept { _impl->update(ptr, length); } template bytes cryptopp_hasher::calculate(const std::string_view& s) { typename cryptopp_hasher::impl::impl_type hash; unsigned char digest[size]; hash.CalculateDigest(digest, reinterpret_cast(s.data()), s.size()); return bytes{reinterpret_cast(digest), size}; } template class cryptopp_hasher; template class cryptopp_hasher; std::array get_sha256(std::span in) { sha256_hasher hasher; hasher.update(reinterpret_cast(in.data()), in.size()); auto b = hasher.finalize_array(); auto out = std::array(); assert(b.size() == out.size()); std::memcpy(&out, b.data(), b.size()); return out; }