Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
61 changes: 61 additions & 0 deletions include/boost/crypt2/hash/detail/hash_file.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
// Copyright 2025 Matt Borland
// Distributed under the Boost Software License, Version 1.0.
// https://www.boost.org/LICENSE_1_0.txt

#ifndef BOOST_CRYPT2_HASH_DETAIL_HASH_FILE_HPP
#define BOOST_CRYPT2_HASH_DETAIL_HASH_FILE_HPP

#include <boost/crypt2/detail/config.hpp>

#ifndef BOOST_CRYPT_HAS_CUDA

#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/detail/concepts.hpp>
#include <boost/crypt2/detail/compat.hpp>

namespace boost::crypt::hash_detail {

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

template <typename HasherType, concepts::file_system_path T>
[[nodiscard]] auto hash_file_impl(const T& filepath) -> compat::expected<typename HasherType::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<HasherType::block_size> reader(filepath);
HasherType hasher;

while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}


#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

} // namespace boost::crypt::detail

#endif // BOOST_CRYPT_HAS_CUDA

#endif //BOOST_CRYPT2_HASH_DETAIL_HASH_FILE_HPP
44 changes: 2 additions & 42 deletions include/boost/crypt2/hash/sha1.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
#define BOOST_CRYPT2_HASH_SHA1_HPP

#include <boost/crypt2/hash/detail/sha_1_2_hasher_base.hpp>
#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/hash/detail/hash_file.hpp>
#include <boost/crypt2/detail/compat.hpp>
#include <boost/crypt2/detail/concepts.hpp>

Expand Down Expand Up @@ -251,52 +251,12 @@ auto sha1(SizedRange&& data) noexcept -> compat::expected<sha1_hasher::return_ty

#ifndef BOOST_CRYPT_HAS_CUDA

namespace detail {

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

template <std::size_t block_size = 64U>
[[nodiscard]] auto sha1_file_impl(detail::file_reader<block_size>& reader) -> compat::expected<sha1_hasher::return_type, state>
{
sha1_hasher hasher;
while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}

#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

} // namespace detail

template <concepts::file_system_path T>
[[nodiscard]] BOOST_CRYPT_EXPORT inline
auto sha1_file(const T& filepath) -> compat::expected<sha1_hasher::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<64U> reader(filepath);
return detail::sha1_file_impl(reader);
return hash_detail::hash_file_impl<sha1_hasher>(filepath);
}

#endif // BOOST_CRYPT_HAS_CUDA
Expand Down
46 changes: 3 additions & 43 deletions include/boost/crypt2/hash/sha224.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define BOOST_CRYPT2_SHA224_HPP

#include <boost/crypt2/hash/detail/sha224_256_hasher.hpp>
#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/hash/detail/hash_file.hpp>
#include <boost/crypt2/detail/compat.hpp>
#include <boost/crypt2/detail/concepts.hpp>

Expand Down Expand Up @@ -39,53 +39,13 @@ auto sha224(SizedRange&& data) noexcept -> compat::expected<sha224_hasher::retur

#ifndef BOOST_CRYPT_HAS_CUDA

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

namespace detail {

[[nodiscard]] inline auto sha224_file_impl(detail::file_reader<64U>& reader) -> compat::expected<sha224_hasher::return_type, state>
{
sha224_hasher hasher;
while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}

} // namespace detail

template <concepts::file_system_path T>
[[nodiscard]] BOOST_CRYPT_EXPORT inline auto sha224_file(const T& filepath) -> compat::expected<sha224_hasher::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<64U> reader(filepath);
return detail::sha224_file_impl(reader);
return hash_detail::hash_file_impl<sha224_hasher>(filepath);
}

#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

#endif
#endif // BOOST_CRYPT_HAS_CUDA

} // namespace boost::crypt

Expand Down
46 changes: 3 additions & 43 deletions include/boost/crypt2/hash/sha256.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define BOOST_CRYPT2_SHA256_HPP

#include <boost/crypt2/hash/detail/sha224_256_hasher.hpp>
#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/hash/detail/hash_file.hpp>
#include <boost/crypt2/detail/compat.hpp>
#include <boost/crypt2/detail/concepts.hpp>

Expand Down Expand Up @@ -39,53 +39,13 @@ auto sha256(SizedRange&& data) noexcept -> compat::expected<sha256_hasher::retur

#ifndef BOOST_CRYPT_HAS_CUDA

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

namespace detail {

[[nodiscard]] inline auto sha256_file_impl(detail::file_reader<64U>& reader) -> compat::expected<sha256_hasher::return_type, state>
{
sha256_hasher hasher;
while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}

} // namespace detail

template <concepts::file_system_path T>
[[nodiscard]] BOOST_CRYPT_EXPORT inline auto sha256_file(const T& filepath) -> compat::expected<sha256_hasher::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<64U> reader(filepath);
return detail::sha256_file_impl(reader);
return hash_detail::hash_file_impl<sha256_hasher>(filepath);
}

#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

#endif
#endif // BOOST_CRYPT_HAS_CUDA

} // namespace boost::crypt

Expand Down
46 changes: 3 additions & 43 deletions include/boost/crypt2/hash/sha384.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define BOOST_CRYPT2_HASH_SHA384_HPP

#include <boost/crypt2/hash/detail/sha512_base.hpp>
#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/hash/detail/hash_file.hpp>
#include <boost/crypt2/detail/compat.hpp>
#include <boost/crypt2/detail/concepts.hpp>

Expand Down Expand Up @@ -39,53 +39,13 @@ auto sha384(SizedRange&& data) noexcept -> compat::expected<sha384_hasher::retur

#ifndef BOOST_CRYPT_HAS_CUDA

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

namespace detail {

[[nodiscard]] inline auto sha384_file_impl(detail::file_reader<64U>& reader) -> compat::expected<sha384_hasher::return_type, state>
{
sha384_hasher hasher;
while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}

} // namespace detail

template <concepts::file_system_path T>
[[nodiscard]] BOOST_CRYPT_EXPORT inline auto sha384_file(const T& filepath) -> compat::expected<sha384_hasher::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<64U> reader(filepath);
return detail::sha384_file_impl(reader);
return hash_detail::hash_file_impl<sha384_hasher>(filepath);
}

#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

#endif
#endif // BOOST_CRYPT_HAS_CUDA

} // namespace boost::crypt

Expand Down
46 changes: 3 additions & 43 deletions include/boost/crypt2/hash/sha512.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
#define BOOST_CRYPT2_SHA512_HPP

#include <boost/crypt2/hash/detail/sha512_base.hpp>
#include <boost/crypt2/detail/file_reader.hpp>
#include <boost/crypt2/hash/detail/hash_file.hpp>
#include <boost/crypt2/detail/compat.hpp>
#include <boost/crypt2/detail/concepts.hpp>

Expand Down Expand Up @@ -39,53 +39,13 @@ auto sha512(SizedRange&& data) noexcept -> compat::expected<sha512_hasher::retur

#ifndef BOOST_CRYPT_HAS_CUDA

// Error: the two-parameter std::span construction is unsafe as it can introduce mismatch between buffer size and the bound information [-Werror,-Wunsafe-buffer-usage-in-container]
// Since this is the way the file streams report sizing information we must use it
// If a bad read occurs an exception is thrown so there's little risk of a bad region
#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunsafe-buffer-usage-in-container"
#endif

namespace detail {

[[nodiscard]] inline auto sha512_file_impl(detail::file_reader<64U>& reader) -> compat::expected<sha512_hasher::return_type, state>
{
sha512_hasher hasher;
while (!reader.eof())
{
const auto buffer_iter {reader.read_next_block()};
const auto len {reader.get_bytes_read()};
const auto buffer_span {std::span(buffer_iter, len)};
hasher.process_bytes(buffer_span);
}

hasher.finalize();
return hasher.get_digest();
}

} // namespace detail

template <concepts::file_system_path T>
[[nodiscard]] BOOST_CRYPT_EXPORT inline auto sha512_file(const T& filepath) -> compat::expected<sha512_hasher::return_type, state>
{
if constexpr (std::is_pointer_v<std::remove_cvref_t<T>>)
{
if (filepath == nullptr)
{
throw std::runtime_error("Invalid file path");
}
}

detail::file_reader<64U> reader(filepath);
return detail::sha512_file_impl(reader);
return hash_detail::hash_file_impl<sha512_hasher>(filepath);
}

#if defined(__clang__) && __clang_major__ >= 19
#pragma clang diagnostic pop
#endif

#endif
#endif // BOOST_CRYPT_HAS_CUDA

} // namespace boost::crypt

Expand Down
Loading
Loading