Skip to content

Commit

Permalink
Merge pull request #1587 from evoskuil/master
Browse files Browse the repository at this point in the history
Fix native_finalize for non-default digest lengths, impl native qtr opt.
  • Loading branch information
evoskuil authored Jan 21, 2025
2 parents 7926328 + 40848db commit 9734372
Show file tree
Hide file tree
Showing 7 changed files with 88 additions and 38 deletions.
15 changes: 10 additions & 5 deletions include/bitcoin/system/hash/sha/algorithm.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -236,13 +236,17 @@ class algorithm
/// -----------------------------------------------------------------------

INLINE static constexpr void input(buffer_t& buffer, const block_t& block) NOEXCEPT;
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;

INLINE static constexpr void input_left(auto& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr void input_right(auto& buffer, const half_t& half) NOEXCEPT;
INLINE static constexpr void inject_left(auto& buffer, const auto& left) NOEXCEPT;
INLINE static constexpr void inject_right(auto& buffer, const auto& right) NOEXCEPT;
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;

INLINE static constexpr void inject_left_half(auto& buffer, const auto& left) NOEXCEPT;
INLINE static constexpr void inject_right_half(auto& buffer, const auto& right) NOEXCEPT;
INLINE static constexpr void inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT;
INLINE static constexpr void inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT;

/// Padding.
/// -----------------------------------------------------------------------
Expand Down Expand Up @@ -409,6 +413,7 @@ class algorithm
static digest_t native_hash(const block_t& block) NOEXCEPT;
static digest_t native_hash(const half_t& half) NOEXCEPT;
static digest_t native_hash(const half_t& left, const half_t& right) NOEXCEPT;
static digest_t native_hash(const quart_t& left, const quart_t& right) NOEXCEPT;
static digest_t native_hash(uint8_t byte) NOEXCEPT;

static digest_t native_double_hash(const block_t& block) NOEXCEPT;
Expand Down
6 changes: 3 additions & 3 deletions include/bitcoin/system/impl/hash/sha/algorithm_double.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ double_hash(const block_t& block) NOEXCEPT
compress(state, buffer);

// Second hash
inject_left(buffer, state);
inject_left_half(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
Expand Down Expand Up @@ -134,7 +134,7 @@ double_hash(const half_t& half) NOEXCEPT
compress(state, buffer);

// Second hash
inject_left(buffer, state);
inject_left_half(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
Expand Down Expand Up @@ -175,7 +175,7 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
compress(state, buffer);

// Second hash
inject_left(buffer, state);
inject_left_half(buffer, state);
pad_half(buffer);
schedule(buffer);
state = H::get;
Expand Down
2 changes: 1 addition & 1 deletion include/bitcoin/system/impl/hash/sha/algorithm_merkle.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ merkle_hash_vector(idigests_t& digests, iblocks_t& blocks) NOEXCEPT
compress_(xstate, xbuffer);

// Second hash
inject_left(xbuffer, xstate);
inject_left_half(xbuffer, xstate);
pad_half(xbuffer);
schedule_(xbuffer);
xstate = initial;
Expand Down
46 changes: 30 additions & 16 deletions include/bitcoin/system/impl/hash/sha/algorithm_native.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -268,11 +268,10 @@ native_finalize(state_t& state, const words_t& pad) NOEXCEPT
unshuffle(lo, hi);

// digest is copied so that state remains valid (LE).
digest_t digest{};
auto& wdigest = array_cast<xint128_t>(digest);
std::array<xint128_t, 2> wdigest{};
store(wdigest[0], byteswap<uint32_t>(lo));
store(wdigest[1], byteswap<uint32_t>(hi));
return digest;
return array_cast<byte_t, sizeof(digest_t)>(wdigest);
}

TEMPLATE
Expand All @@ -285,7 +284,7 @@ native_finalize_second(const state_t& state) NOEXCEPT
// Hash a state value and finalize it.
auto state2 = H::get;
words_t block{};
inject_left(block, state);
inject_left_half(block, state);
pad_half(block);
return native_finalize(state2, block);
}
Expand All @@ -300,7 +299,7 @@ native_finalize_double(state_t& state, size_t blocks) NOEXCEPT

// This is native_finalize_second() but reuses the initial block.
auto state2 = H::get;
inject_left(block, state);
inject_left_half(block, state);
pad_half(block);
return native_finalize(state2, block);
}
Expand Down Expand Up @@ -338,23 +337,38 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
{
auto state = H::get;
words_t block{};
inject_left(block, array_cast<word_t>(left));
inject_right(block, array_cast<word_t>(right));
inject_left_half(block, array_cast<word_t>(left));
inject_right_half(block, array_cast<word_t>(right));
native_transform<true>(state, block);
return native_finalize<one>(state);
}

TEMPLATE
typename CLASS::digest_t CLASS::
native_hash(const quart_t& left, const quart_t& right) NOEXCEPT
{
auto state = H::get;
words_t block{};
inject_left_quarter(block, array_cast<word_t>(left));
inject_right_quarter(block, array_cast<word_t>(right));
pad_half(block);
return native_finalize(state, block);
}

TEMPLATE
typename CLASS::digest_t CLASS::
native_hash(uint8_t byte) NOEXCEPT
{
constexpr auto pad = bit_hi<uint8_t>;

auto state = H::get;
block_t block{};
block.at(0) = byte;
block.at(1) = pad;
block.at(63) = byte_bits;
return native_hash(block);

// Order is based on array of little-endian uint32_t.
block.at(3) = byte;
block.at(2) = pad;
block.at(60) = byte_bits;
return native_finalize(state, array_cast<word_t>(block));
}

// Double hash functions start with BE data and end with BE digest_t.
Expand All @@ -370,7 +384,7 @@ native_double_hash(const block_t& block) NOEXCEPT

// Second hash
words_t block2{};
inject_left(block2, state);
inject_left_half(block2, state);
pad_half(block2);
state = H::get;
return native_finalize(state, block2);
Expand All @@ -388,7 +402,7 @@ native_double_hash(const half_t& half) NOEXCEPT
native_transform<false>(state, block);

// Second hash
inject_left(block, state);
inject_left_half(block, state);
pad_half(block);
state = H::get;
return native_finalize(state, block);
Expand All @@ -400,13 +414,13 @@ native_double_hash(const half_t& left, const half_t& right) NOEXCEPT
{
auto state = H::get;
words_t block{};
inject_left(block, array_cast<word_t>(left));
inject_right(block, array_cast<word_t>(right));
inject_left_half(block, array_cast<word_t>(left));
inject_right_half(block, array_cast<word_t>(right));
native_transform<true>(state, block);
native_transform<false>(state, pad_block());

// Second hash
inject_left(block, state);
inject_left_half(block, state);
pad_half(block);
state = H::get;
return native_finalize(state, block);
Expand Down
51 changes: 41 additions & 10 deletions include/bitcoin/system/impl/hash/sha/algorithm_parsing.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -410,11 +410,8 @@ output(const state_t& state) NOEXCEPT

TEMPLATE
INLINE constexpr void CLASS::
inject_left(auto& buffer, const auto& left) NOEXCEPT
inject_left_half(auto& buffer, const auto& left) NOEXCEPT
{
using words = decltype(buffer);
static_assert(array_count<words> >= SHA::state_words);

if (std::is_constant_evaluated())
{
buffer.at(0) = left.at(0);
Expand All @@ -428,18 +425,15 @@ inject_left(auto& buffer, const auto& left) NOEXCEPT
}
else
{
using word = array_element<words>;
using word = array_element<decltype(buffer)>;
array_cast<word, SHA::state_words>(buffer) = left;
}
}

TEMPLATE
INLINE constexpr void CLASS::
inject_right(auto& buffer, const auto& right) NOEXCEPT
inject_right_half(auto& buffer, const auto& right) NOEXCEPT
{
using words = decltype(buffer);
static_assert(array_count<words> >= SHA::state_words);

if (std::is_constant_evaluated())
{
buffer.at(8) = right.at(0);
Expand All @@ -453,11 +447,48 @@ inject_right(auto& buffer, const auto& right) NOEXCEPT
}
else
{
using word = array_element<words>;
using word = array_element<decltype(buffer)>;
array_cast<word, SHA::state_words, SHA::state_words>(buffer) = right;
}
}

TEMPLATE
INLINE constexpr void CLASS::
inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT
{
if (std::is_constant_evaluated())
{
buffer.at(0) = left.at(0);
buffer.at(1) = left.at(1);
buffer.at(2) = left.at(2);
buffer.at(3) = left.at(3);
}
else
{
using word = array_element<decltype(buffer)>;
array_cast<word, to_half(SHA::state_words)>(buffer) = left;
}
}

TEMPLATE
INLINE constexpr void CLASS::
inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT
{
if (std::is_constant_evaluated())
{
buffer.at(4) = right.at(0);
buffer.at(5) = right.at(1);
buffer.at(6) = right.at(2);
buffer.at(7) = right.at(3);
}
else
{
using word = array_element<decltype(buffer)>;
constexpr auto words = to_half(SHA::state_words);
array_cast<word, words, words>(buffer) = right;
}
}

} // namespace sha
} // namespace system
} // namespace libbitcoin
Expand Down
4 changes: 2 additions & 2 deletions include/bitcoin/system/impl/hash/sha/algorithm_stream.ipp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ finalize_second(const state_t& state) NOEXCEPT
{
auto state2 = H::get;
buffer_t buffer{};
inject_left(buffer, state);
inject_left_half(buffer, state);
pad_half(buffer);
schedule(buffer);
compress(state2, buffer);
Expand Down Expand Up @@ -150,7 +150,7 @@ finalize_double(state_t& state, size_t blocks) NOEXCEPT

// This is finalize_second() but reuses the initial buffer.
auto state2 = H::get;
inject_left(buffer, state);
inject_left_half(buffer, state);
pad_half(buffer);
schedule(buffer);
compress(state2, buffer);
Expand Down
2 changes: 1 addition & 1 deletion test/hash/sha/sha256.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(sha256_224__ttt_accumulator_hash__test_vectors__expected)
using sha_256_224 = sha::algorithm<sha::h256<224>, true, true, true>;

// Native only for sha256 (and sha160 when implemented).
static_assert(!sha_256_224::native);
static_assert(sha_256_224::native == native);
static_assert(sha_256_224::vector == vector);
static_assert(sha_256_224::caching);

Expand Down

0 comments on commit 9734372

Please sign in to comment.