#ifndef HASH_KECCAK_BASE_2019_04_11_H #define HASH_KECCAK_BASE_2019_04_11_H #include #if(__cplusplus >= 201703L) namespace al::crypto::stream::hash { #else namespace al { namespace crypto { namespace stream { namespace hash { #endif template class hash_keccak_base : public al::crypto::stream::hash::hash_base(25UL * 64UL), std::uint64_t, (1600ULL - (ResultBitCount * 2ULL)) / 8U> { private: using base_class_type = al::crypto::stream::hash::hash_base(25UL * 64UL), std::uint64_t, (1600ULL - (ResultBitCount * 2ULL)) / 8U>; // Number of bits/bytes in SHA3 Keccak message buffer. // Bits | message_buffer_static_size // 512 | 1600 - (512 * 2) = 576 // 384 | 1600 - (384 * 2) = 832 // 256 | 1600 - (256 * 2) = 1088 // 224 | 1600 - (224 * 2) = 1152 public: ~hash_keccak_base() override = default; auto finalize() -> void override { // Fill the unused part of the message buffer with zero. std::fill(base_class_type::message_buffer.begin() + static_cast(base_class_type::message_index), base_class_type::message_buffer.end(), 0U); // Message padding. this->padding(); // Process the final block. this->transform(); } AL_CRYPTO_NODISCARD auto get_result() const -> typename base_class_type::result_type override { using base_class_result_type = typename base_class_type::result_type; base_class_result_type result { }; { // Calculate the number of uint64_t in the result type, // rounded up to the nearest multiple of 8. // Consider, for example, SHA3-224. // It has 224 bits (28 bytes) in the result buffer. // This results in: // qwords_in_result_type = [(28 / 8) + 1] = 3 + 1 = 4 // (for SHA3-224). constexpr auto local_result_byte_count = static_cast ( 8U * ( static_cast ((ResultBitCount / 8U) / 8U) + static_cast((((ResultBitCount / 8U) % 8U) != 0U) ? 1U : 0U)) ); using local_result_type = std::array; local_result_type local_result; // Copy the local result to the result requested by the caller. base_class_type::copy_transform_context_forward(local_result.data()); std::copy(local_result.cbegin(), local_result.cbegin() + result.size(), result.begin()); } return result; } protected: hash_keccak_base() = default; hash_keccak_base(const hash_keccak_base& other) : base_class_type(static_cast(other)) { } hash_keccak_base(hash_keccak_base&& other) noexcept : base_class_type(static_cast(other)) { } auto operator=(const hash_keccak_base& other) -> hash_keccak_base& // NOLINT(cert-oop54-cpp) { if(this != &other) { static_cast(base_class_type::operator=(static_cast(other))); } return *this; } auto operator=(hash_keccak_base&& other) noexcept -> hash_keccak_base& { static_cast(base_class_type::operator=(static_cast(other))); return *this; } private: virtual auto padding() -> void = 0; }; #if(__cplusplus >= 201703L) } // namespace al::crypto::stream::hash #else } // namespace hash } // namespace stream } // namespace crypto } // namespace al #endif #endif // HASH_KECCAK_BASE_2019_04_11_H