accumulators/stream.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 //
4 // MIT License
5 //
6 // Permission is hereby granted, free of charge, to any person obtaining a copy
7 // of this software and associated documentation files (the "Software"), to deal
8 // in the Software without restriction, including without limitation the rights
9 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 // copies of the Software, and to permit persons to whom the Software is
11 // furnished to do so, subject to the following conditions:
12 //
13 // The above copyright notice and this permission notice shall be included in all
14 // copies or substantial portions of the Software.
15 //
16 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 // SOFTWARE.
23 //---------------------------------------------------------------------------//
24 
25 #ifndef CRYPTO3_ACCUMULATORS_STREAM_HPP
26 #define CRYPTO3_ACCUMULATORS_STREAM_HPP
27 
28 #include <boost/parameter/value_type.hpp>
29 
30 #include <boost/accumulators/framework/accumulator_base.hpp>
31 #include <boost/accumulators/framework/extractor.hpp>
32 #include <boost/accumulators/framework/depends_on.hpp>
33 #include <boost/accumulators/framework/parameters/sample.hpp>
34 
35 #include <boost/container/static_vector.hpp>
36 
38 
39 #include <nil/crypto3/detail/make_array.hpp>
40 #include <nil/crypto3/detail/digest.hpp>
41 
42 namespace nil {
43  namespace crypto3 {
44  namespace accumulators {
45  namespace impl {
46  template<typename StreamCipherMode>
47  struct stream_impl : boost::accumulators::accumulator_base {
48  protected:
49  typedef StreamCipherMode stream_mode_type;
50 
51  typedef typename stream_mode_type::finalizer_type finalizer_type;
52 
53  constexpr static const std::size_t input_block_bits = stream_mode_type::input_block_bits;
54  constexpr static const std::size_t input_block_values = stream_mode_type::input_block_values;
55  typedef typename stream_mode_type::input_block_type input_block_type;
56 
57  constexpr static const std::size_t input_value_bits = stream_mode_type::input_value_bits;
58  typedef typename input_block_type::value_type input_value_type;
59 
60  constexpr static const std::size_t output_block_bits = stream_mode_type::output_block_bits;
61  constexpr static const std::size_t output_block_values = stream_mode_type::output_block_values;
62  typedef typename stream_mode_type::output_block_type output_block_type;
63 
64  constexpr static const std::size_t output_value_bits = stream_mode_type::output_value_bits;
65  typedef typename output_block_type::value_type output_value_type;
66 
67  typedef boost::container::static_vector<input_value_type, input_block_values> cache_type;
68 
69  public:
71 
72  template<typename Args>
73  // The constructor takes an argument pack.
74  stream_impl(const Args &args) : seen(0) {
75  }
76 
77  template<typename ArgumentPack>
78  inline void operator()(const ArgumentPack &args) {
79  resolve_type(args[boost::accumulators::sample], args[bits | std::size_t()]);
80  }
81 
82  template<typename ArgumentPack>
83  inline result_type result(const ArgumentPack &args) const {
85 
86  if (!cache.empty()) {
87  input_block_type ib = {0};
88  std::move(cache.begin(), cache.end(), ib.begin());
89  output_block_type ob = stream_mode_type::process_block(ib);
90  std::move(ob.begin(), ob.end(), std::inserter(res, res.end()));
91  }
92 
93  if (seen % input_block_bits) {
95  } else {
96  finalizer_type(0)(res);
97  }
98 
99  return res;
100  }
101 
102  protected:
103  inline void resolve_type(const input_value_type &value, std::size_t bits) {
104  if (bits == std::size_t()) {
105  process(value, input_value_bits);
106  } else {
107  process(value, bits);
108  }
109  }
110 
111  inline void resolve_type(const input_block_type &value, std::size_t bits) {
112  if (bits == std::size_t()) {
113  process(value, input_block_bits);
114  } else {
115  process(value, bits);
116  }
117  }
118 
119  inline void process(const input_value_type &value, std::size_t bits) {
120  if (cache.size() == cache.max_size()) {
121  input_block_type ib = {0};
122  std::move(cache.begin(), cache.end(), ib.begin());
123  output_block_type ob = stream_mode_type::process_block(ib);
124  std::move(ob.begin(), ob.end(), std::inserter(internal_digest, internal_digest.end()));
125 
126  cache.clear();
127  }
128 
129  cache.push_back(value);
131  }
132 
133  inline void process(const input_block_type &block, std::size_t bits) {
135  if (cache.empty()) {
136  ob = stream_mode_type::process_block(block);
137  } else {
138  input_block_type b = make_array<input_block_values>(cache.begin(), cache.end());
139  typename input_block_type::const_iterator itr =
140  block.begin() + (cache.max_size() - cache.size());
141 
142  std::move(block.begin(), itr, b.end());
143 
144  ob = stream_mode_type::process_block(b);
145 
146  cache.clear();
147  cache.insert(cache.end(), itr, block.end());
148  }
149 
150  std::move(ob.begin(), ob.end(), std::inserter(internal_digest, internal_digest.end()));
152  }
153 
154  std::size_t seen;
157  };
158  } // namespace impl
159 
160  namespace tag {
161  template<typename ProcessingMode>
162  struct stream : boost::accumulators::depends_on<> {
163  typedef ProcessingMode mode_type;
164 
167 
168  typedef boost::mpl::always<accumulators::impl::stream_impl<mode_type>> impl;
169  };
170  } // namespace tag
171 
172  namespace extract {
173  template<typename Mode, typename AccumulatorSet>
174  typename boost::mpl::apply<AccumulatorSet, tag::stream<Mode>>::type::result_type
175  stream(const AccumulatorSet &acc) {
176  return boost::accumulators::extract_result<tag::stream<Mode>>(acc);
177  }
178 
179  template<typename StreamCipher, typename AccumulatorSet>
180  typename boost::mpl::apply<AccumulatorSet,
182  encrypt(const AccumulatorSet &acc) {
183  return boost::accumulators::extract_result<tag::stream<typename StreamCipher::stream_encoder_type>>(
184  acc);
185  }
186 
187  template<typename StreamCipher, typename AccumulatorSet>
188  typename boost::mpl::apply<AccumulatorSet,
190  decrypt(const AccumulatorSet &acc) {
191  return boost::accumulators::extract_result<tag::stream<typename StreamCipher::stream_decoder_type>>(
192  acc);
193  }
194  } // namespace extract
195  } // namespace accumulators
196  } // namespace crypto3
197 } // namespace nil
198 
199 #endif // CRYPTO3_ACCUMULATORS_STREAM_HPP
boost::mpl::apply< AccumulatorSet, tag::block< Mode > >::type::result_type block(const AccumulatorSet &acc)
Definition: accumulators/block.hpp:259
boost::mpl::apply< AccumulatorSet, tag::stream< typename StreamCipher::stream_decoder_type > >::type::result_type decrypt(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:190
boost::mpl::apply< AccumulatorSet, tag::stream< Mode > >::type::result_type stream(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:175
boost::mpl::apply< AccumulatorSet, tag::stream< typename StreamCipher::stream_encoder_type > >::type::result_type encrypt(const AccumulatorSet &acc)
Definition: accumulators/stream.hpp:182
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
Definition: pair.hpp:31
Definition: accumulators/stream.hpp:47
constexpr static const std::size_t output_value_bits
Definition: accumulators/stream.hpp:64
result_type internal_digest
Definition: accumulators/stream.hpp:156
stream_impl(const Args &args)
Definition: accumulators/stream.hpp:74
constexpr static const std::size_t output_block_bits
Definition: accumulators/stream.hpp:60
void resolve_type(const input_value_type &value, std::size_t bits)
Definition: accumulators/stream.hpp:103
digest< output_block_bits > result_type
Definition: accumulators/stream.hpp:70
output_block_type::value_type output_value_type
Definition: accumulators/stream.hpp:65
void process(const input_value_type &value, std::size_t bits)
Definition: accumulators/stream.hpp:119
constexpr static const std::size_t input_block_values
Definition: accumulators/stream.hpp:54
result_type result(const ArgumentPack &args) const
Definition: accumulators/stream.hpp:83
boost::container::static_vector< input_value_type, input_block_values > cache_type
Definition: accumulators/stream.hpp:67
std::size_t seen
Definition: accumulators/stream.hpp:154
void operator()(const ArgumentPack &args)
Definition: accumulators/stream.hpp:78
cache_type cache
Definition: accumulators/stream.hpp:155
void resolve_type(const input_block_type &value, std::size_t bits)
Definition: accumulators/stream.hpp:111
stream_mode_type::output_block_type output_block_type
Definition: accumulators/stream.hpp:62
stream_mode_type::finalizer_type finalizer_type
Definition: accumulators/stream.hpp:51
input_block_type::value_type input_value_type
Definition: accumulators/stream.hpp:58
constexpr static const std::size_t output_block_values
Definition: accumulators/stream.hpp:61
stream_mode_type::input_block_type input_block_type
Definition: accumulators/stream.hpp:55
void process(const input_block_type &block, std::size_t bits)
Definition: accumulators/stream.hpp:133
constexpr static const std::size_t input_block_bits
Definition: accumulators/stream.hpp:53
constexpr static const std::size_t input_value_bits
Definition: accumulators/stream.hpp:57
StreamCipherMode stream_mode_type
Definition: accumulators/stream.hpp:49
Definition: accumulators/stream.hpp:162
ProcessingMode mode_type
Definition: accumulators/stream.hpp:163
boost::mpl::always< accumulators::impl::stream_impl< mode_type > > impl
Definition: accumulators/stream.hpp:168