/*
* Copyright (C) 2019 ScyllaDB
*/
/*
* This file is part of Scylla.
*
* Scylla is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Scylla is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Scylla. If not, see .
*/
#include "hashers.hh"
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include
#include
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 std::move(bytes{reinterpret_cast(digest), size});
}
template class cryptopp_hasher;
template class cryptopp_hasher;