sha256_component.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2021 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020-2021 Nikita Kaskov <nbering@nil.foundation>
4 //
5 // MIT License
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in all
15 // copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 // SOFTWARE.
24 //---------------------------------------------------------------------------//
25 // @file Declaration of interfaces for top-level SHA256 components.
26 //---------------------------------------------------------------------------//
27 
28 #ifndef CRYPTO3_ZK_BLUEPRINT_SHA256_COMPONENT_HPP
29 #define CRYPTO3_ZK_BLUEPRINT_SHA256_COMPONENT_HPP
30 
34 
35 namespace nil {
36  namespace crypto3 {
37  namespace zk {
38  namespace components {
39 
43  template<typename FieldType>
45  public:
46  std::vector<blueprint_linear_combination_vector<FieldType>> round_a;
47  std::vector<blueprint_linear_combination_vector<FieldType>> round_b;
48  std::vector<blueprint_linear_combination_vector<FieldType>> round_c;
49  std::vector<blueprint_linear_combination_vector<FieldType>> round_d;
50  std::vector<blueprint_linear_combination_vector<FieldType>> round_e;
51  std::vector<blueprint_linear_combination_vector<FieldType>> round_f;
52  std::vector<blueprint_linear_combination_vector<FieldType>> round_g;
53  std::vector<blueprint_linear_combination_vector<FieldType>> round_h;
54 
56  std::shared_ptr<sha256_message_schedule_component<FieldType>> message_schedule;
57  std::vector<sha256_round_function_component<FieldType>> round_functions;
58 
61  std::vector<lastbits_component<FieldType>> reduce_output;
62 
63  public:
67 
73  component<FieldType>(bp),
75 
76  /* message schedule and inputs for it */
78  message_schedule.reset(
80 
81  /* initalize */
102  prev_output.rbegin() + 2 * hashes::sha2<256>::word_bits));
105  prev_output.rbegin() + 1 * hashes::sha2<256>::word_bits));
106 
107  /* do the rounds */
108  for (std::size_t i = 0; i < block::detail::shacal2_policy<256>::rounds; ++i) {
109  round_h.push_back(round_g[i]);
110  round_g.push_back(round_f[i]);
111  round_f.push_back(round_e[i]);
112  round_d.push_back(round_c[i]);
113  round_c.push_back(round_b[i]);
114  round_b.push_back(round_a[i]);
115 
116  blueprint_variable_vector<FieldType> new_round_a_variables;
117  new_round_a_variables.allocate(bp, hashes::sha2<256>::word_bits);
118  round_a.emplace_back(new_round_a_variables);
119 
120  blueprint_variable_vector<FieldType> new_round_e_variables;
121  new_round_e_variables.allocate(bp, hashes::sha2<256>::word_bits);
122  round_e.emplace_back(new_round_e_variables);
123 
125  bp, round_a[i], round_b[i], round_c[i], round_d[i], round_e[i], round_f[i], round_g[i],
127  round_a[i + 1], round_e[i + 1]));
128  }
129 
130  /* finalize */
131  unreduced_output.allocate(bp, 8);
132  reduced_output.allocate(bp, 8);
133  for (std::size_t i = 0; i < 8; ++i) {
135  bp,
136  unreduced_output[i],
138  reduced_output[i],
140  output.bits.rbegin() + (7 - i) * hashes::sha2<256>::word_bits,
141  output.bits.rbegin() + (8 - i) * hashes::sha2<256>::word_bits)));
142  }
143  }
145  message_schedule->generate_r1cs_constraints();
146  for (std::size_t i = 0; i < block::detail::shacal2_policy<256>::rounds; ++i) {
147  round_functions[i].generate_r1cs_constraints();
148  }
149 
150  for (std::size_t i = 0; i < 4; ++i) {
151  this->bp.add_r1cs_constraint(snark::r1cs_constraint<FieldType>(
152  1,
153  round_functions[3 - i].packed_d + round_functions[63 - i].packed_new_a,
154  unreduced_output[i]));
155 
156  this->bp.add_r1cs_constraint(snark::r1cs_constraint<FieldType>(
157  1,
158  round_functions[3 - i].packed_h + round_functions[63 - i].packed_new_e,
159  unreduced_output[4 + i]));
160  }
161 
162  for (std::size_t i = 0; i < 8; ++i) {
163  reduce_output[i].generate_r1cs_constraints();
164  }
165  }
167  message_schedule->generate_r1cs_witness();
168 
169  for (std::size_t i = 0; i < block::detail::shacal2_policy<256>::rounds; ++i) {
170  round_functions[i].generate_r1cs_witness();
171  }
172 
173  for (std::size_t i = 0; i < 4; ++i) {
174  this->bp.val(unreduced_output[i]) = this->bp.val(round_functions[3 - i].packed_d) +
175  this->bp.val(round_functions[63 - i].packed_new_a);
176  this->bp.val(unreduced_output[4 + i]) = this->bp.val(round_functions[3 - i].packed_h) +
177  this->bp.val(round_functions[63 - i].packed_new_e);
178  }
179 
180  for (std::size_t i = 0; i < 8; ++i) {
181  reduce_output[i].generate_r1cs_witness();
182  }
183  }
184  };
185 
193  template<typename FieldType>
194  class sha256_two_to_one_hash_component : public component<FieldType> {
195  public:
196  typedef std::vector<bool> hash_value_type;
199 
200  std::shared_ptr<sha256_compression_function_component<FieldType>> f;
201 
203  const digest_variable<FieldType> &left,
204  const digest_variable<FieldType> &right,
205  const digest_variable<FieldType> &output) :
206  component<FieldType>(bp) {
207 
208  /* concatenate block = left || right */
210  block.insert(block.end(), left.bits.begin(), left.bits.end());
211  block.insert(block.end(), right.bits.begin(), right.bits.end());
212 
213  /* compute the hash itself */
215  bp, SHA256_default_IV<FieldType>(bp), block, output));
216  }
218  std::size_t block_length,
219  const block_variable<FieldType> &input_block,
220  const digest_variable<FieldType> &output) :
221  component<FieldType>(bp) {
222 
223  assert(block_length == hashes::sha2<256>::block_bits);
224  assert(input_block.bits.size() == block_length);
226  bp, SHA256_default_IV<FieldType>(bp), input_block.bits, output));
227  }
228 
229  void generate_r1cs_constraints(bool ensure_output_bitness = true) { // TODO: ignored for now
230  f->generate_r1cs_constraints();
231  }
232 
234  f->generate_r1cs_witness();
235  }
236 
237  static std::size_t get_block_len() {
239  }
240 
241  static std::size_t get_digest_len() {
243  }
244 
245  static std::vector<bool> get_hash(const std::vector<bool> &input) {
247 
251  output_variable);
252 
253  input_variable.generate_r1cs_witness(input);
254  f.generate_r1cs_witness();
255 
256  return output_variable.get_digest();
257  }
258 
259  static std::size_t
260  expected_constraints(bool ensure_output_bitness = true) { // TODO: ignored for now
261  return 27280; /* hardcoded for now */
262  }
263  };
264 
269  template<typename FieldType>
270  class sha256_hash_component : public component<FieldType> {
271  public:
272  typedef std::vector<bool> hash_value_type;
275 
276  std::vector<std::shared_ptr<sha256_compression_function_component<FieldType>>> blocks_components;
277  std::vector<blueprint_variable_vector<FieldType>> blocks_bits;
278  std::vector<std::shared_ptr<digest_variable<FieldType>>> intermediate_outputs;
279  std::shared_ptr<merkle_damagard_padding<FieldType>> padding;
280 
282  std::size_t input_len,
283  const block_variable<FieldType> &block_input,
284  const digest_variable<FieldType> &output) :
285  component<FieldType>(bp) {
286 
287  assert(input_len == block_input.block_size);
288  const int length_bits_size = 64;
289 
290  padding.reset(new merkle_damagard_padding<FieldType>(bp, input_len, length_bits_size,
292  blueprint_variable_vector<FieldType> bits = block_input.bits;
293  bits.insert(bits.end(), padding->bits.begin(), padding->bits.end());
294  assert(bits.size() % hashes::sha2<256>::block_bits == 0);
295  std::size_t num_blocks = bits.size() / hashes::sha2<256>::block_bits;
296 
297  intermediate_outputs.resize(num_blocks - 1);
298  blocks_components.resize(num_blocks);
299  blocks_bits.resize(num_blocks);
300 
301  const std::size_t chunk = hashes::sha2<256>::block_bits;
302 
303  for (std::size_t i = 0; i < num_blocks; ++i) {
304  blocks_bits[i] = blueprint_variable_vector<FieldType>(bits.begin() + i * chunk,
305  bits.begin() + (i + 1) * chunk);
306  }
307 
308  for (std::size_t i = 0; i < num_blocks - 1; ++i) {
309  intermediate_outputs[i].reset(
311  }
312 
313  if (num_blocks == 1) {
315  bp, SHA256_default_IV(bp), blocks_bits[0], output));
316  } else {
319  for (std::size_t i = 1; i < num_blocks - 1; ++i) {
322  bp, lcv, blocks_bits[i], *intermediate_outputs[i]));
323  }
325  intermediate_outputs[num_blocks - 2]->bits);
326  blocks_components[num_blocks - 1].reset(
328  bp, lcv, blocks_bits[num_blocks - 1], output));
329  }
330  }
331 
332  void generate_r1cs_constraints(bool ensure_output_bitness = true) { // TODO: ignored for now
333  padding->generate_r1cs_constraints();
334  for (auto f : blocks_components) {
335  f->generate_r1cs_constraints();
336  }
337  }
338 
340  padding->generate_r1cs_witness();
341  for (auto f : blocks_components) {
342  f->generate_r1cs_witness();
343  }
344  }
345 
346  static std::size_t get_block_len() {
348  }
349 
350  static std::size_t get_digest_len() {
352  }
353 
354  static std::vector<bool> get_hash(const std::vector<bool> &input) {
356 
357  block_variable<FieldType> input_variable(bp, input.size());
359  sha256_hash_component<FieldType> f(bp, input_variable.block_size, input_variable,
360  output_variable);
361 
362  input_variable.generate_r1cs_witness(input);
364 
365  return output_variable.get_digest();
366  }
367  };
368  } // namespace components
369  } // namespace zk
370  } // namespace crypto3
371 } // namespace nil
372 
373 #endif // CRYPTO3_ZK_BLUEPRINT_SHA256_COMPONENT_HPP
SHA2.
Definition: sha2.hpp:46
std::size_t block_size
Definition: hash_io.hpp:86
void generate_r1cs_witness(const std::vector< bool > &contents)
Definition: hash_io.hpp:116
blueprint_variable_vector< FieldType > bits
Definition: hash_io.hpp:87
Definition: blueprint_linear_combination.hpp:115
Definition: blueprint_variable.hpp:57
void allocate(blueprint< field_type > &bp, const std::size_t n)
Definition: blueprint_variable.hpp:91
Definition: blueprint.hpp:46
Definition: component.hpp:37
blueprint< FieldType > & bp
Definition: component.hpp:39
std::vector< bool > get_digest() const
Definition: hash_io.hpp:78
blueprint_variable_vector< FieldType > bits
Definition: hash_io.hpp:46
void generate_r1cs_constraints()
Definition: sha256_component.hpp:144
std::vector< blueprint_linear_combination_vector< FieldType > > round_a
Definition: sha256_component.hpp:46
digest_variable< FieldType > output
Definition: sha256_component.hpp:66
std::vector< blueprint_linear_combination_vector< FieldType > > round_d
Definition: sha256_component.hpp:49
std::vector< blueprint_linear_combination_vector< FieldType > > round_g
Definition: sha256_component.hpp:52
std::vector< blueprint_linear_combination_vector< FieldType > > round_e
Definition: sha256_component.hpp:50
std::vector< blueprint_linear_combination_vector< FieldType > > round_f
Definition: sha256_component.hpp:51
blueprint_variable_vector< FieldType > reduced_output
Definition: sha256_component.hpp:60
std::vector< sha256_round_function_component< FieldType > > round_functions
Definition: sha256_component.hpp:57
std::vector< blueprint_linear_combination_vector< FieldType > > round_b
Definition: sha256_component.hpp:47
sha256_compression_function_component(blueprint< FieldType > &bp, const blueprint_linear_combination_vector< FieldType > &prev_output, const blueprint_variable_vector< FieldType > &new_block, const digest_variable< FieldType > &output)
Definition: sha256_component.hpp:68
std::shared_ptr< sha256_message_schedule_component< FieldType > > message_schedule
Definition: sha256_component.hpp:56
std::vector< blueprint_linear_combination_vector< FieldType > > round_h
Definition: sha256_component.hpp:53
std::vector< lastbits_component< FieldType > > reduce_output
Definition: sha256_component.hpp:61
blueprint_variable_vector< FieldType > unreduced_output
Definition: sha256_component.hpp:59
blueprint_linear_combination_vector< FieldType > prev_output
Definition: sha256_component.hpp:64
std::vector< blueprint_linear_combination_vector< FieldType > > round_c
Definition: sha256_component.hpp:48
void generate_r1cs_witness()
Definition: sha256_component.hpp:166
blueprint_variable_vector< FieldType > packed_W
Definition: sha256_component.hpp:55
blueprint_variable_vector< FieldType > new_block
Definition: sha256_component.hpp:65
Definition: sha256_component.hpp:270
std::shared_ptr< merkle_damagard_padding< FieldType > > padding
Definition: sha256_component.hpp:279
static std::vector< bool > get_hash(const std::vector< bool > &input)
Definition: sha256_component.hpp:354
sha256_hash_component(blueprint< FieldType > &bp, std::size_t input_len, const block_variable< FieldType > &block_input, const digest_variable< FieldType > &output)
Definition: sha256_component.hpp:281
static std::size_t get_digest_len()
Definition: sha256_component.hpp:350
snark::merkle_authentication_path merkle_authentication_path_type
Definition: sha256_component.hpp:274
digest_variable< FieldType > hash_variable_type
Definition: sha256_component.hpp:273
std::vector< std::shared_ptr< digest_variable< FieldType > > > intermediate_outputs
Definition: sha256_component.hpp:278
std::vector< bool > hash_value_type
Definition: sha256_component.hpp:272
std::vector< std::shared_ptr< sha256_compression_function_component< FieldType > > > blocks_components
Definition: sha256_component.hpp:276
void generate_r1cs_witness()
Definition: sha256_component.hpp:339
void generate_r1cs_constraints(bool ensure_output_bitness=true)
Definition: sha256_component.hpp:332
static std::size_t get_block_len()
Definition: sha256_component.hpp:346
std::vector< blueprint_variable_vector< FieldType > > blocks_bits
Definition: sha256_component.hpp:277
void generate_r1cs_witness()
Definition: sha256_component.hpp:233
static std::vector< bool > get_hash(const std::vector< bool > &input)
Definition: sha256_component.hpp:245
void generate_r1cs_constraints(bool ensure_output_bitness=true)
Definition: sha256_component.hpp:229
std::vector< bool > hash_value_type
Definition: sha256_component.hpp:196
sha256_two_to_one_hash_component(blueprint< FieldType > &bp, std::size_t block_length, const block_variable< FieldType > &input_block, const digest_variable< FieldType > &output)
Definition: sha256_component.hpp:217
sha256_two_to_one_hash_component(blueprint< FieldType > &bp, const digest_variable< FieldType > &left, const digest_variable< FieldType > &right, const digest_variable< FieldType > &output)
Definition: sha256_component.hpp:202
static std::size_t get_digest_len()
Definition: sha256_component.hpp:241
digest_variable< FieldType > hash_variable_type
Definition: sha256_component.hpp:197
std::shared_ptr< sha256_compression_function_component< FieldType > > f
Definition: sha256_component.hpp:200
static std::size_t expected_constraints(bool ensure_output_bitness=true)
Definition: sha256_component.hpp:260
snark::merkle_authentication_path merkle_authentication_path_type
Definition: sha256_component.hpp:198
static std::size_t get_block_len()
Definition: sha256_component.hpp:237
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
blueprint_linear_combination_vector< FieldType > SHA256_default_IV(blueprint< FieldType > &bp)
Definition: sha256_construction.hpp:274
std::vector< merkle_authentication_node > merkle_authentication_path
Definition: blueprint/include/nil/crypto3/zk/merkle_tree.hpp:66
Definition: pair.hpp:31
Definition: shacal2_policy.hpp:55