Files
scylladb/hashers.cc
Rafael Ávila de Espíndola fd5ea2df5a Avoid including cryptopp headers
cryptopp's config.h has the following pragma:

 #pragma GCC diagnostic ignored "-Wunused-function"

It is not wrapped in a push/pop. Because of that, including cryptopp
headers disables that warning on scylla code too.

The issue has been reported as
https://github.com/weidai11/cryptopp/issues/793

To work around it, this patch uses a pimpl to have a single .cc file
that has to include cryptopp headers.

While at it, it also reduces the differences and code duplication
between the md5 and sha1 hashers.

Signed-off-by: Rafael Ávila de Espíndola <espindola@scylladb.com>
2019-02-20 08:03:46 -08:00

88 lines
3.3 KiB
C++

/*
* 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 <http://www.gnu.org/licenses/>.
*/
#include "hashers.hh"
#define CRYPTOPP_ENABLE_NAMESPACE_WEAK 1
#include <cryptopp/md5.h>
#include <cryptopp/sha.h>
template <typename T> struct hasher_traits;
template <> struct hasher_traits<md5_hasher> { using impl_type = CryptoPP::Weak::MD5; };
template <> struct hasher_traits<sha256_hasher> { using impl_type = CryptoPP::SHA256; };
template <typename T, size_t size> struct hasher<T, size>::impl {
using impl_type = typename hasher_traits<T>::impl_type;
impl_type hash{};
void update(const char* ptr, size_t length) {
using namespace CryptoPP;
static_assert(sizeof(char) == sizeof(byte), "Assuming lengths will be the same");
hash.Update(reinterpret_cast<const byte*>(ptr), length * sizeof(byte));
}
bytes finalize() {
bytes digest{bytes::initialized_later(), size};
hash.Final(reinterpret_cast<unsigned char*>(digest.begin()));
return digest;
}
std::array<uint8_t, size> finalize_array() {
std::array<uint8_t, size> array;
hash.Final(reinterpret_cast<unsigned char*>(array.data()));
return array;
}
};
template <typename T, size_t size> hasher<T, size>::hasher() : _impl(std::make_unique<impl>()) {}
template <typename T, size_t size> hasher<T, size>::~hasher() = default;
template <typename T, size_t size> hasher<T, size>::hasher(hasher&& o) noexcept = default;
template <typename T, size_t size> hasher<T, size>::hasher(const hasher& o) : _impl(std::make_unique<hasher<T, size>::impl>(*o._impl)) {}
template <typename T, size_t size> hasher<T, size>& hasher<T, size>::operator=(hasher&& o) noexcept = default;
template <typename T, size_t size> hasher<T, size>& hasher<T, size>::operator=(const hasher& o) {
_impl = std::make_unique<hasher<T, size>::impl>(*o._impl);
return *this;
}
template <typename T, size_t size> bytes hasher<T, size>::finalize() { return _impl->finalize(); }
template <typename T, size_t size> std::array<uint8_t, size> hasher<T, size>::finalize_array() {
return _impl->finalize_array();
}
template <typename T, size_t size> void hasher<T, size>::update(const char* ptr, size_t length) { _impl->update(ptr, length); }
template <typename T, size_t size> bytes hasher<T, size>::calculate(const std::string_view& s) {
typename hasher<T, size>::impl::impl_type hash;
unsigned char digest[size];
hash.CalculateDigest(digest, reinterpret_cast<const unsigned char*>(s.data()), s.size());
return std::move(bytes{reinterpret_cast<const int8_t*>(digest), size});
}
template class hasher<md5_hasher, 16>;
template class hasher<sha256_hasher, 32>;