barretenberg
Loading...
Searching...
No Matches
keccak.hpp
1#pragma once
2#include "barretenberg/stdlib/primitives/byte_array/byte_array.hpp"
3#include "barretenberg/stdlib/primitives/packed_byte_array/packed_byte_array.hpp"
4#include "barretenberg/stdlib/primitives/uint/uint.hpp"
5#include <array>
6
7namespace proof_system::plonk {
8namespace stdlib {
9template <typename Builder> class bit_array;
10
23template <typename Builder> class keccak {
24 public:
29 using uint32_ct = stdlib::uint32<Builder>;
30
31 // base of extended representation we use for efficient logic operations
32 static constexpr uint256_t BASE = 11;
33
34 // number of bits of hash output
35 static constexpr size_t BITS = 256;
36
37 // word size of hash lane
38 static constexpr size_t WORD_SIZE = 8;
39
40 // block size. We only support keccak256 with a 1088-bit rate! This is what Ethereum uses
41 static constexpr size_t BLOCK_SIZE = (1600 - BITS * 2) / WORD_SIZE;
42
43 // how many limbs fit into a block (17)
44 static constexpr size_t LIMBS_PER_BLOCK = BLOCK_SIZE / 8;
45
46 static constexpr size_t NUM_KECCAK_ROUNDS = 24;
47
48 // 1 "lane" = 64 bits. Instead of interpreting the keccak sponge as 1,600 bits, it's easier to work over 64-bit
49 // "lanes". 1,600 / 64 = 25.
50 static constexpr size_t NUM_KECCAK_LANES = 25;
51
52 // round constants. Used in IOTA round
53 static constexpr std::array<uint64_t, NUM_KECCAK_ROUNDS> RC = {
54 0x0000000000000001, 0x0000000000008082, 0x800000000000808a, 0x8000000080008000, 0x000000000000808b,
55 0x0000000080000001, 0x8000000080008081, 0x8000000000008009, 0x000000000000008a, 0x0000000000000088,
56 0x0000000080008009, 0x000000008000000a, 0x000000008000808b, 0x800000000000008b, 0x8000000000008089,
57 0x8000000000008003, 0x8000000000008002, 0x8000000000000080, 0x000000000000800a, 0x800000008000000a,
58 0x8000000080008081, 0x8000000000008080, 0x0000000080000001, 0x8000000080008008
59 };
60
61 // Rotation offsets, y vertically, x horizontally: r[y * 5 + x]
62 static constexpr std::array<size_t, NUM_KECCAK_LANES> ROTATIONS = {
63 0, 1, 62, 28, 27, 36, 44, 6, 55, 20, 3, 10, 43, 25, 39, 41, 45, 15, 21, 8, 18, 2, 61, 56, 14,
64 };
65
75 static constexpr uint256_t convert_to_sparse(uint256_t input)
76 {
77 std::array<uint64_t, 64> out_bits;
78 size_t count = 0;
79 while (input > 0) {
80 uint64_t bit = static_cast<uint64_t>(input & 1);
81 out_bits[count++] = bit;
82 input = input >> 1;
83 }
84 uint256_t output = 0;
85 for (size_t i = 0; i < count; ++i) {
86 output *= BASE;
87 output += out_bits[count - 1 - i];
88 }
89 return output;
90 };
91
103 static constexpr uint256_t normalize_sparse(uint256_t input)
104 {
105 std::array<uint64_t, 64> out_bits;
106 size_t count = 0;
107 while (input > 0) {
108 const auto [quotient, slice] = input.divmod(BASE);
109 uint64_t bit = static_cast<uint64_t>(slice) & 1;
110 out_bits[count++] = bit;
111 input = quotient;
112 }
113 uint256_t out;
114 for (size_t i = 0; i < count; ++i) {
115 out *= BASE;
116 out += out_bits[count - 1 - i];
117 }
118 return out;
119 }
120
126 static constexpr std::array<uint256_t, NUM_KECCAK_ROUNDS> get_sparse_round_constants()
127 {
128 std::array<uint256_t, 24> output;
129 for (size_t i = 0; i < 24; ++i) {
130 output[i] = convert_to_sparse(RC[i]);
131 }
132 return output;
133 }
134 static constexpr std::array<uint256_t, NUM_KECCAK_ROUNDS> SPARSE_RC = get_sparse_round_constants();
135
146 static constexpr uint256_t get_chi_offset()
147 {
148 uint256_t result = 0;
149 for (size_t i = 0; i < 64; ++i) {
150 result *= 11;
151 result += 1;
152 }
153 return result;
154 }
155 static constexpr uint256_t CHI_OFFSET = get_chi_offset();
156
158 std::array<field_ct, NUM_KECCAK_LANES> state;
159 std::array<field_ct, NUM_KECCAK_LANES> state_msb;
160 std::array<field_ct, NUM_KECCAK_LANES> twisted_state;
161 Builder* context;
162 };
163
164 template <size_t lane_index> static field_t<Builder> normalize_and_rotate(const field_ct& limb, field_ct& msb);
165 static void compute_twisted_state(keccak_state& internal);
166 static void theta(keccak_state& state);
167 static void rho(keccak_state& state);
168 static void pi(keccak_state& state);
169 static void chi(keccak_state& state);
170 static void iota(keccak_state& state, size_t round);
171 static void sponge_absorb(keccak_state& internal,
172 const std::vector<field_ct>& input_buffer,
173 const std::vector<field_ct>& msb_buffer,
174 const field_ct& num_blocks_with_data);
175 static byte_array_ct sponge_squeeze(keccak_state& internal);
176 static void keccakf1600(keccak_state& state);
177 static byte_array_ct hash(byte_array_ct& input, const uint32_ct& num_bytes);
178 static byte_array_ct hash(byte_array_ct& input) { return hash(input, static_cast<uint32_t>(input.size())); };
179
180 static std::vector<field_ct> format_input_lanes(byte_array_ct& input, const uint32_ct& num_bytes);
181
182 static std::vector<uint8_t> hash_native(const std::vector<uint8_t>& data)
183 {
184 auto hash_result = ethash_keccak256(&data[0], data.size());
185
186 std::vector<uint8_t> output;
187 output.resize(32);
188
189 memcpy((void*)&output[0], (void*)&hash_result.word64s[0], 32);
190 return output;
191 }
192};
193
194EXTERN_STDLIB_ULTRA_TYPE(keccak)
195
196} // namespace stdlib
197} // namespace proof_system::plonk
Definition: uint256.hpp:25
Definition: standard_circuit_builder.hpp:12
Definition: byte_array.hpp:9
Definition: field.hpp:10
KECCAAAAAAAAAAK.
Definition: keccak.hpp:23
static void rho(keccak_state &state)
RHO round.
Definition: keccak.cpp:378
static constexpr uint256_t convert_to_sparse(uint256_t input)
Convert a binary integer into a base11 integer.
Definition: keccak.hpp:75
static constexpr uint256_t normalize_sparse(uint256_t input)
Normalize a base-11 integer where each base value can be > 1.
Definition: keccak.hpp:103
static void pi(keccak_state &state)
PI.
Definition: keccak.cpp:393
static void iota(keccak_state &state, size_t round)
IOTA.
Definition: keccak.cpp:462
static std::vector< field_ct > format_input_lanes(byte_array_ct &input, const uint32_ct &num_bytes)
Convert the input buffer into 8-bit keccak lanes in little-endian form. Additionally,...
Definition: keccak.cpp:570
static void chi(keccak_state &state)
CHI.
Definition: keccak.cpp:429
static void theta(keccak_state &state)
THETA round.
Definition: keccak.cpp:244
static void compute_twisted_state(keccak_state &internal)
Compute twisted representation of hash lane.
Definition: keccak.cpp:190
static field_t< Builder > normalize_and_rotate(const field_ct &limb, field_ct &msb)
Normalize a base-11 limb and left-rotate by keccak::ROTATIONS[lane_index] bits. This method also extr...
Definition: keccak.cpp:28
static constexpr uint256_t get_chi_offset()
Compute the constant offset added in the Chi round.
Definition: keccak.hpp:146
static constexpr std::array< uint256_t, NUM_KECCAK_ROUNDS > get_sparse_round_constants()
Get the sparse round constants object.
Definition: keccak.hpp:126
Definition: witness.hpp:10
Definition: widget.bench.cpp:13