#ifndef HASH_SHA1_2019_01_11_H #define HASH_SHA1_2019_01_11_H #include #include #include #include #include #include #include #include #include #if(__cplusplus >= 201703L) namespace al::crypto::stream::hash { #else namespace al { namespace crypto { namespace stream { namespace hash { #endif class hash_sha1 : public al::crypto::stream::hash::hash_sha_base<160U, 160U, std::uint32_t, 64U, 64U> { private: using base_class_type = al::crypto::stream::hash::hash_sha_base<160U, 160U, std::uint32_t, 64U, 64U>; public: hash_sha1() = default; ~hash_sha1() override = default; hash_sha1(const hash_sha1& other) : base_class_type(static_cast(other)) { } hash_sha1(hash_sha1&& other) noexcept : base_class_type(static_cast(other)) { } auto operator=(const hash_sha1& other) -> hash_sha1& { if(this != &other) { static_cast(base_class_type::operator=(static_cast(other))); } return *this; } auto operator=(hash_sha1&& other) noexcept -> hash_sha1& { static_cast(base_class_type::operator=(static_cast(other))); return *this; } auto initialize() -> void override { base_class_type::initialize(); std::copy(al::crypto::math::constants::hash::hash_init.begin(), al::crypto::math::constants::hash::hash_init.end(), base_class_type::transform_context.begin()); base_class_type::transform_context[4U] = UINT32_C(0xC3D2E1F0); } private: auto transform() -> void override { // Apply the hash1 transformation algorithm to a full data block. using local_transform_block_type = std::array; constexpr local_transform_block_type local_constants = {{ UINT32_C(0x5A827999), UINT32_C(0x6ED9EBA1), UINT32_C(0x8F1BBCDC), UINT32_C(0xCA62C1D6) }}; local_transform_block_type local_transform_block; this->copy_message_buffer_reverse(local_transform_block.data()); base_class_type::transform_context_type hash_tmp = base_class_type::transform_context; for(auto i = static_cast(0U); i < static_cast(80U); ++i) { auto block_index = static_cast(i); if(i > static_cast(0x0FU)) { block_index &= static_cast(0x0FU); const auto the_dword = static_cast ( local_transform_block[static_cast((i + 13U) & 0x0FU)] ^ local_transform_block[static_cast((i + 8U) & 0x0FU)] ^ local_transform_block[static_cast((i + 2U) & 0x0FU)] ^ local_transform_block[block_index] ); local_transform_block[block_index] = al::crypto::math::utils::rotl(the_dword, 1U); } std::uint32_t fn { }; std::uint32_t cn { }; if (i >= static_cast(60U)) { fn = transform_function4(hash_tmp.data()); cn = local_constants[3U]; } else if(i >= static_cast(40U)) { fn = transform_function3(hash_tmp.data()); cn = local_constants[2U]; } else if(i >= static_cast(20U)) { fn = transform_function2(hash_tmp.data()); cn = local_constants[1U]; } else { fn = transform_function1(hash_tmp.data()); cn = local_constants[0U]; } const auto tmp32 = static_cast ( al::crypto::math::utils::rotl(hash_tmp[0U], 5U) + fn + hash_tmp[4U] + local_transform_block[block_index] + cn ); hash_tmp[4U] = hash_tmp[3U]; hash_tmp[3U] = hash_tmp[2U]; hash_tmp[2U] = al::crypto::math::utils::rotl(hash_tmp[1U], 30U); hash_tmp[1U] = hash_tmp[0U]; hash_tmp[0U] = tmp32; } // Update the hash state with the transformation results. std::transform(base_class_type::transform_context.cbegin(), base_class_type::transform_context.cend (), hash_tmp.cbegin (), base_class_type::transform_context.begin (), std::plus ()); // NOLINT(modernize-use-transparent-functors) base_class_type::message_buffer.fill(0U); base_class_type::message_index = 0U; } // BSIG0 static constexpr auto transform_function1(const std::uint32_t* hash_ptr) -> std::uint32_t { return static_cast ( static_cast( hash_ptr[1U] & hash_ptr[2U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) | static_cast(static_cast(~hash_ptr[1U]) & hash_ptr[3U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ); } // BSIG1 static constexpr auto transform_function2(const std::uint32_t* hash_ptr) -> std::uint32_t { return static_cast ( static_cast(hash_ptr[1U] ^ hash_ptr[2U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ^ hash_ptr[3U] // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ); } // SSIG0 static constexpr auto transform_function3(const std::uint32_t* hash_ptr) -> std::uint32_t { return static_cast ( static_cast(hash_ptr[1U] & hash_ptr[2U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) | static_cast(hash_ptr[1U] & hash_ptr[3U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) | static_cast(hash_ptr[2U] & hash_ptr[3U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ); } // SSIG1 static constexpr auto transform_function4(const std::uint32_t* hash_ptr) -> std::uint32_t { return static_cast ( static_cast(hash_ptr[1U] ^ hash_ptr[2U]) // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ^ hash_ptr[3U] // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) ); } }; #if(__cplusplus >= 201703L) } // namespace al::crypto::stream::hash #else } // namespace hash } // namespace stream } // namespace crypto } // namespace al #endif #endif // HASH_SHA1_2019_01_11_H