Skip to content

Commit 9734372

Browse files
authored
Merge pull request libbitcoin#1587 from evoskuil/master
Fix native_finalize for non-default digest lengths, impl native qtr opt.
2 parents 7926328 + 40848db commit 9734372

File tree

7 files changed

+88
-38
lines changed

7 files changed

+88
-38
lines changed

include/bitcoin/system/hash/sha/algorithm.hpp

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -236,13 +236,17 @@ class algorithm
236236
/// -----------------------------------------------------------------------
237237

238238
INLINE static constexpr void input(buffer_t& buffer, const block_t& block) NOEXCEPT;
239-
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
240-
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;
239+
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
240+
241241
INLINE static constexpr void input_left(auto& buffer, const half_t& half) NOEXCEPT;
242242
INLINE static constexpr void input_right(auto& buffer, const half_t& half) NOEXCEPT;
243-
INLINE static constexpr void inject_left(auto& buffer, const auto& left) NOEXCEPT;
244-
INLINE static constexpr void inject_right(auto& buffer, const auto& right) NOEXCEPT;
245-
INLINE static constexpr digest_t output(const state_t& state) NOEXCEPT;
243+
INLINE static constexpr void input_left(auto& buffer, const quart_t& quarter) NOEXCEPT;
244+
INLINE static constexpr void input_right(auto& buffer, const quart_t& quarter) NOEXCEPT;
245+
246+
INLINE static constexpr void inject_left_half(auto& buffer, const auto& left) NOEXCEPT;
247+
INLINE static constexpr void inject_right_half(auto& buffer, const auto& right) NOEXCEPT;
248+
INLINE static constexpr void inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT;
249+
INLINE static constexpr void inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT;
246250

247251
/// Padding.
248252
/// -----------------------------------------------------------------------
@@ -409,6 +413,7 @@ class algorithm
409413
static digest_t native_hash(const block_t& block) NOEXCEPT;
410414
static digest_t native_hash(const half_t& half) NOEXCEPT;
411415
static digest_t native_hash(const half_t& left, const half_t& right) NOEXCEPT;
416+
static digest_t native_hash(const quart_t& left, const quart_t& right) NOEXCEPT;
412417
static digest_t native_hash(uint8_t byte) NOEXCEPT;
413418

414419
static digest_t native_double_hash(const block_t& block) NOEXCEPT;

include/bitcoin/system/impl/hash/sha/algorithm_double.ipp

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ double_hash(const block_t& block) NOEXCEPT
9595
compress(state, buffer);
9696

9797
// Second hash
98-
inject_left(buffer, state);
98+
inject_left_half(buffer, state);
9999
pad_half(buffer);
100100
schedule(buffer);
101101
state = H::get;
@@ -134,7 +134,7 @@ double_hash(const half_t& half) NOEXCEPT
134134
compress(state, buffer);
135135

136136
// Second hash
137-
inject_left(buffer, state);
137+
inject_left_half(buffer, state);
138138
pad_half(buffer);
139139
schedule(buffer);
140140
state = H::get;
@@ -175,7 +175,7 @@ double_hash(const half_t& left, const half_t& right) NOEXCEPT
175175
compress(state, buffer);
176176

177177
// Second hash
178-
inject_left(buffer, state);
178+
inject_left_half(buffer, state);
179179
pad_half(buffer);
180180
schedule(buffer);
181181
state = H::get;

include/bitcoin/system/impl/hash/sha/algorithm_merkle.ipp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -372,7 +372,7 @@ merkle_hash_vector(idigests_t& digests, iblocks_t& blocks) NOEXCEPT
372372
compress_(xstate, xbuffer);
373373

374374
// Second hash
375-
inject_left(xbuffer, xstate);
375+
inject_left_half(xbuffer, xstate);
376376
pad_half(xbuffer);
377377
schedule_(xbuffer);
378378
xstate = initial;

include/bitcoin/system/impl/hash/sha/algorithm_native.ipp

Lines changed: 30 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -268,11 +268,10 @@ native_finalize(state_t& state, const words_t& pad) NOEXCEPT
268268
unshuffle(lo, hi);
269269

270270
// digest is copied so that state remains valid (LE).
271-
digest_t digest{};
272-
auto& wdigest = array_cast<xint128_t>(digest);
271+
std::array<xint128_t, 2> wdigest{};
273272
store(wdigest[0], byteswap<uint32_t>(lo));
274273
store(wdigest[1], byteswap<uint32_t>(hi));
275-
return digest;
274+
return array_cast<byte_t, sizeof(digest_t)>(wdigest);
276275
}
277276

278277
TEMPLATE
@@ -285,7 +284,7 @@ native_finalize_second(const state_t& state) NOEXCEPT
285284
// Hash a state value and finalize it.
286285
auto state2 = H::get;
287286
words_t block{};
288-
inject_left(block, state);
287+
inject_left_half(block, state);
289288
pad_half(block);
290289
return native_finalize(state2, block);
291290
}
@@ -300,7 +299,7 @@ native_finalize_double(state_t& state, size_t blocks) NOEXCEPT
300299

301300
// This is native_finalize_second() but reuses the initial block.
302301
auto state2 = H::get;
303-
inject_left(block, state);
302+
inject_left_half(block, state);
304303
pad_half(block);
305304
return native_finalize(state2, block);
306305
}
@@ -338,23 +337,38 @@ native_hash(const half_t& left, const half_t& right) NOEXCEPT
338337
{
339338
auto state = H::get;
340339
words_t block{};
341-
inject_left(block, array_cast<word_t>(left));
342-
inject_right(block, array_cast<word_t>(right));
340+
inject_left_half(block, array_cast<word_t>(left));
341+
inject_right_half(block, array_cast<word_t>(right));
343342
native_transform<true>(state, block);
344343
return native_finalize<one>(state);
345344
}
346345

346+
TEMPLATE
347+
typename CLASS::digest_t CLASS::
348+
native_hash(const quart_t& left, const quart_t& right) NOEXCEPT
349+
{
350+
auto state = H::get;
351+
words_t block{};
352+
inject_left_quarter(block, array_cast<word_t>(left));
353+
inject_right_quarter(block, array_cast<word_t>(right));
354+
pad_half(block);
355+
return native_finalize(state, block);
356+
}
357+
347358
TEMPLATE
348359
typename CLASS::digest_t CLASS::
349360
native_hash(uint8_t byte) NOEXCEPT
350361
{
351362
constexpr auto pad = bit_hi<uint8_t>;
352363

364+
auto state = H::get;
353365
block_t block{};
354-
block.at(0) = byte;
355-
block.at(1) = pad;
356-
block.at(63) = byte_bits;
357-
return native_hash(block);
366+
367+
// Order is based on array of little-endian uint32_t.
368+
block.at(3) = byte;
369+
block.at(2) = pad;
370+
block.at(60) = byte_bits;
371+
return native_finalize(state, array_cast<word_t>(block));
358372
}
359373

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

371385
// Second hash
372386
words_t block2{};
373-
inject_left(block2, state);
387+
inject_left_half(block2, state);
374388
pad_half(block2);
375389
state = H::get;
376390
return native_finalize(state, block2);
@@ -388,7 +402,7 @@ native_double_hash(const half_t& half) NOEXCEPT
388402
native_transform<false>(state, block);
389403

390404
// Second hash
391-
inject_left(block, state);
405+
inject_left_half(block, state);
392406
pad_half(block);
393407
state = H::get;
394408
return native_finalize(state, block);
@@ -400,13 +414,13 @@ native_double_hash(const half_t& left, const half_t& right) NOEXCEPT
400414
{
401415
auto state = H::get;
402416
words_t block{};
403-
inject_left(block, array_cast<word_t>(left));
404-
inject_right(block, array_cast<word_t>(right));
417+
inject_left_half(block, array_cast<word_t>(left));
418+
inject_right_half(block, array_cast<word_t>(right));
405419
native_transform<true>(state, block);
406420
native_transform<false>(state, pad_block());
407421

408422
// Second hash
409-
inject_left(block, state);
423+
inject_left_half(block, state);
410424
pad_half(block);
411425
state = H::get;
412426
return native_finalize(state, block);

include/bitcoin/system/impl/hash/sha/algorithm_parsing.ipp

Lines changed: 41 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -410,11 +410,8 @@ output(const state_t& state) NOEXCEPT
410410

411411
TEMPLATE
412412
INLINE constexpr void CLASS::
413-
inject_left(auto& buffer, const auto& left) NOEXCEPT
413+
inject_left_half(auto& buffer, const auto& left) NOEXCEPT
414414
{
415-
using words = decltype(buffer);
416-
static_assert(array_count<words> >= SHA::state_words);
417-
418415
if (std::is_constant_evaluated())
419416
{
420417
buffer.at(0) = left.at(0);
@@ -428,18 +425,15 @@ inject_left(auto& buffer, const auto& left) NOEXCEPT
428425
}
429426
else
430427
{
431-
using word = array_element<words>;
428+
using word = array_element<decltype(buffer)>;
432429
array_cast<word, SHA::state_words>(buffer) = left;
433430
}
434431
}
435432

436433
TEMPLATE
437434
INLINE constexpr void CLASS::
438-
inject_right(auto& buffer, const auto& right) NOEXCEPT
435+
inject_right_half(auto& buffer, const auto& right) NOEXCEPT
439436
{
440-
using words = decltype(buffer);
441-
static_assert(array_count<words> >= SHA::state_words);
442-
443437
if (std::is_constant_evaluated())
444438
{
445439
buffer.at(8) = right.at(0);
@@ -453,11 +447,48 @@ inject_right(auto& buffer, const auto& right) NOEXCEPT
453447
}
454448
else
455449
{
456-
using word = array_element<words>;
450+
using word = array_element<decltype(buffer)>;
457451
array_cast<word, SHA::state_words, SHA::state_words>(buffer) = right;
458452
}
459453
}
460454

455+
TEMPLATE
456+
INLINE constexpr void CLASS::
457+
inject_left_quarter(auto& buffer, const auto& left) NOEXCEPT
458+
{
459+
if (std::is_constant_evaluated())
460+
{
461+
buffer.at(0) = left.at(0);
462+
buffer.at(1) = left.at(1);
463+
buffer.at(2) = left.at(2);
464+
buffer.at(3) = left.at(3);
465+
}
466+
else
467+
{
468+
using word = array_element<decltype(buffer)>;
469+
array_cast<word, to_half(SHA::state_words)>(buffer) = left;
470+
}
471+
}
472+
473+
TEMPLATE
474+
INLINE constexpr void CLASS::
475+
inject_right_quarter(auto& buffer, const auto& right) NOEXCEPT
476+
{
477+
if (std::is_constant_evaluated())
478+
{
479+
buffer.at(4) = right.at(0);
480+
buffer.at(5) = right.at(1);
481+
buffer.at(6) = right.at(2);
482+
buffer.at(7) = right.at(3);
483+
}
484+
else
485+
{
486+
using word = array_element<decltype(buffer)>;
487+
constexpr auto words = to_half(SHA::state_words);
488+
array_cast<word, words, words>(buffer) = right;
489+
}
490+
}
491+
461492
} // namespace sha
462493
} // namespace system
463494
} // namespace libbitcoin

include/bitcoin/system/impl/hash/sha/algorithm_stream.ipp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,7 @@ finalize_second(const state_t& state) NOEXCEPT
116116
{
117117
auto state2 = H::get;
118118
buffer_t buffer{};
119-
inject_left(buffer, state);
119+
inject_left_half(buffer, state);
120120
pad_half(buffer);
121121
schedule(buffer);
122122
compress(state2, buffer);
@@ -150,7 +150,7 @@ finalize_double(state_t& state, size_t blocks) NOEXCEPT
150150

151151
// This is finalize_second() but reuses the initial buffer.
152152
auto state2 = H::get;
153-
inject_left(buffer, state);
153+
inject_left_half(buffer, state);
154154
pad_half(buffer);
155155
schedule(buffer);
156156
compress(state2, buffer);

test/hash/sha/sha256.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ BOOST_AUTO_TEST_CASE(sha256_224__ttt_accumulator_hash__test_vectors__expected)
155155
using sha_256_224 = sha::algorithm<sha::h256<224>, true, true, true>;
156156

157157
// Native only for sha256 (and sha160 when implemented).
158-
static_assert(!sha_256_224::native);
158+
static_assert(sha_256_224::native == native);
159159
static_assert(sha_256_224::vector == vector);
160160
static_assert(sha_256_224::caching);
161161

0 commit comments

Comments
 (0)