11#ifndef CTHASH_SHA3_KECCAK_HPP
22#define CTHASH_SHA3_KECCAK_HPP
33
4- #include < array>
5- #include < bit>
6- #include < span>
7- #include < type_traits>
8- #include < utility>
9- #include < concepts>
10- #include < cstdint>
4+ #include " common.hpp"
115
12- namespace cthash ::keccak {
6+ namespace cthash {
137
14- // inspired by tiny-keccak (https://github.com/debris/tiny-keccak from Marek Kotewicz)
8+ template <unsigned N> struct prenist_keccak_config {
9+ static constexpr size_t digest_length_bit = N;
10+ static constexpr size_t capacity_bit = digest_length_bit * 2u ;
11+ static constexpr size_t rate_bit = 1600u - capacity_bit;
1512
16- static constexpr auto rho = std::array<uint8_t , 24 >{1u , 3u , 6u , 10u , 15u , 21u , 28u , 36u , 45u , 55u , 2u , 14u , 27u , 41u , 56u , 8u , 25u , 43u , 62u , 18u , 39u , 61u , 20u , 44u };
17-
18- static constexpr auto pi = std::array<uint8_t , 24 >{10u , 7u , 11u , 17u , 18u , 3u , 5u , 16u , 8u , 21u , 24u , 4u , 15u , 23u , 19u , 13u , 12u , 2u , 20u , 14u , 22u , 9u , 6u , 1u };
19-
20- static constexpr auto rc = std::array<uint64_t , 24 >{0x1ULL , 0x8082ULL , 0x800000000000808aULL , 0x8000000080008000ULL , 0x808bULL , 0x80000001ULL , 0x8000000080008081ULL , 0x8000000000008009ULL , 0x8aULL , 0x88ULL , 0x80008009ULL , 0x8000000aULL , 0x8000808bULL , 0x800000000000008bULL , 0x8000000000008089ULL , 0x8000000000008003ULL , 0x8000000000008002ULL , 0x8000000000000080ULL , 0x800aULL , 0x800000008000000aULL , 0x8000000080008081ULL , 0x8000000000008080ULL , 0x80000001ULL , 0x8000000080008008ULL };
21-
22- struct state_1600 : std::array<uint64_t , (5u * 5u )> { };
23-
24- struct state_1600_ref : std::span<uint64_t , (5u * 5u )> {
25- using super = std::span<uint64_t , (5u * 5u )>;
26- using super::super;
13+ // Keccak (pre-NIST) domain bit = 0x01
14+ static constexpr auto suffix = keccak_suffix(0 , 0x00 );
2715};
2816
29- [[gnu::always_inline, gnu::flatten]] constexpr void theta (state_1600_ref state) noexcept {
30- // xor of columns
31- const auto b = std::array<uint64_t , 5 >{
32- state[0 ] xor state[5 ] xor state[10 ] xor state[15 ] xor state[20 ],
33- state[1 ] xor state[6 ] xor state[11 ] xor state[16 ] xor state[21 ],
34- state[2 ] xor state[7 ] xor state[12 ] xor state[17 ] xor state[22 ],
35- state[3 ] xor state[8 ] xor state[13 ] xor state[18 ] xor state[23 ],
36- state[4 ] xor state[9 ] xor state[14 ] xor state[19 ] xor state[24 ],
37- };
38-
39- const auto tmp = std::array<uint64_t , 5 >{
40- b[4 ] xor std::rotl (b[1 ], 1 ),
41- b[0 ] xor std::rotl (b[2 ], 1 ),
42- b[1 ] xor std::rotl (b[3 ], 1 ),
43- b[2 ] xor std::rotl (b[4 ], 1 ),
44- b[3 ] xor std::rotl (b[0 ], 1 ),
45- };
17+ static_assert ((prenist_keccak_config<256 >::capacity_bit + prenist_keccak_config<256 >::rate_bit) == 1600u );
4618
47- [&]<size_t ... Idx>(std::index_sequence<Idx...>) {
48- ((state[Idx] ^= tmp[Idx % 5u ]), ...);
49- }(std::make_index_sequence<25 >());
50- }
19+ using keccak_256 = cthash::keccak_hasher<prenist_keccak_config<256 >>;
20+ using keccak_256_value = tagged_hash_value<prenist_keccak_config<256 >>;
21+ using keccak_384 = cthash::keccak_hasher<prenist_keccak_config<384 >>;
22+ using keccak_384_value = tagged_hash_value<prenist_keccak_config<384 >>;
23+ using keccak_512 = cthash::keccak_hasher<prenist_keccak_config<512 >>;
24+ using keccak_512_value = tagged_hash_value<prenist_keccak_config<512 >>;
5125
52- [[gnu::always_inline, gnu::flatten]] constexpr void rho_pi (state_1600_ref state) noexcept {
53- uint64_t tmp = state[1 ];
26+ namespace literals {
5427
55- [&]<size_t ... Idx>(std::index_sequence<Idx...>) {
56- ((state[pi[Idx]] = std::rotl (std::exchange (tmp, state[pi[Idx]]), rho[Idx])), ...);
57- }(std::make_index_sequence<24 >());
58- }
59-
60- [[gnu::always_inline, gnu::flatten]] constexpr void chi (state_1600_ref state) noexcept {
61- constexpr auto chi_helper = [](std::span<uint64_t , 5 > row) {
62- const auto b = std::array<uint64_t , 5 >{row[0 ], row[1 ], row[2 ], row[3 ], row[4 ]};
63-
64- row[0 ] = b[0 ] xor ((~b[1 ]) bitand b[2 ]);
65- row[1 ] = b[1 ] xor ((~b[2 ]) bitand b[3 ]);
66- row[2 ] = b[2 ] xor ((~b[3 ]) bitand b[4 ]);
67- row[3 ] = b[3 ] xor ((~b[4 ]) bitand b[0 ]);
68- row[4 ] = b[4 ] xor ((~b[0 ]) bitand b[1 ]);
69- };
28+ template <fixed_string Value>
29+ consteval auto operator " " _keccak_256() {
30+ return keccak_256_value (Value);
31+ }
7032
71- chi_helper (state.subspan <0 >().first <5 >());
72- chi_helper (state.subspan <5 >().first <5 >());
73- chi_helper (state.subspan <10 >().first <5 >());
74- chi_helper (state.subspan <15 >().first <5 >());
75- chi_helper (state.subspan <20 >().first <5 >());
76- }
33+ template <fixed_string Value>
34+ consteval auto operator " " _keccak_384() {
35+ return keccak_384_value (Value);
36+ }
7737
78- [[gnu::flatten]] constexpr void keccak_f (state_1600 & state) noexcept {
79- // rounds
80- for (int i = 0 ; i != 24 ; ++i) {
81- // theta (xor each column together)
82- theta (state);
83- rho_pi (state);
84- chi (state);
85- state[0 ] ^= rc[static_cast <size_t >(i)];
38+ template <fixed_string Value>
39+ consteval auto operator " " _keccak_512() {
40+ return keccak_512_value (Value);
8641 }
87- }
8842
89- } // namespace cthash::keccak
43+ } // namespace literals
44+
45+ } // namespace cthash
9046
91- #endif
47+ #endif
0 commit comments