pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 //
3 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@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 
26 #ifndef CRYPTO3_PBKDF_HPP
27 #define CRYPTO3_PBKDF_HPP
28 
29 #include <boost/assert.hpp>
30 #include <boost/concept_check.hpp>
31 
32 #include <boost/core/enable_if.hpp>
33 
34 #include <boost/range/begin.hpp>
35 #include <boost/range/end.hpp>
36 #include <boost/range/concepts.hpp>
37 #include <boost/range/any_range.hpp>
38 
39 #include <nil/crypto3/detail/type_traits.hpp>
40 
41 namespace nil {
42  namespace crypto3 {
43  namespace pbkdf {
72  namespace detail {
73  template<typename Hasher, typename SinglePassRange>
74  using range_stream_hash_traits = typename Hasher::template stream_hash<
75  std::numeric_limits<
76  typename std::iterator_traits<typename SinglePassRange::iterator>::value_type>::digits +
77  std::numeric_limits<typename std::iterator_traits<typename SinglePassRange::iterator>::value_type>::
78  is_signed>::type;
79 
80  template<typename Hasher, typename InputIterator>
81  using iterator_stream_hash_traits = typename Hasher::template stream_hash<
82  std::numeric_limits<typename std::iterator_traits<InputIterator>::value_type>::digits +
83  std::numeric_limits<typename std::iterator_traits<InputIterator>::value_type>::is_signed>::type;
84 
85 #ifdef CRYPTO3_RAW_PBKDF_STRING_OUTPUT
86 
87  template<typename Hash, typename InputIterator, typename StreamHasher>
88  typename Hash::digest_type hash_impl_f(InputIterator first, InputIterator last,
89  StreamHasher accumulator) {
90  typedef typename std::iterator_traits<InputIterator>::value_type value_type;
91 
92  BOOST_STATIC_ASSERT(std::numeric_limits<value_type>::is_specialized);
93 
94  return accumulator.update(first, last).end_message();
95  };
96 
97  template<typename Hash, typename SinglePassRange, typename StreamHasher,
98  typename = typename std::enable_if<boost::has_range_iterator<SinglePassRange>::value>::type>
99  typename Hash::digest_type hash_impl_f(const SinglePassRange &rng, StreamHasher accumulator) {
100  BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<SinglePassRange>));
101 
102  typedef typename std::iterator_traits<typename SinglePassRange::iterator>::value_type value_type;
103 
104  BOOST_STATIC_ASSERT(std::numeric_limits<value_type>::is_specialized);
105 
106  return accumulator.update(boost::begin(rng), boost::end(rng)).end_message();
107  }
108 #else
109 
110  struct hash_impl {};
111 
112  template<typename Hasher, typename StreamHash>
114  private:
115  mutable StreamHash sh;
116 
117  public:
118  template<typename SinglePassRange>
119  range_value_hash_impl(const SinglePassRange &range, StreamHash stream_hash) :
120  sh(std::move(stream_hash)) {
121  BOOST_RANGE_CONCEPT_ASSERT((boost::SinglePassRangeConcept<SinglePassRange>));
122 
123  typedef
124  typename std::iterator_traits<typename SinglePassRange::iterator>::value_type value_type;
125 
126  BOOST_STATIC_ASSERT(std::numeric_limits<value_type>::is_specialized);
127 
128  sh.update(boost::begin(range), boost::end(range));
129  }
130 
131  template<typename OutputRange>
132  operator OutputRange() const {
133  typename Hasher::digest_type range = sh.end_message();
134 
135  return OutputRange(range.begin(), range.end());
136  }
137 
138  operator typename Hasher::digest_type() const {
139  return sh.end_message();
140  }
141 
142  template<typename Char, typename CharTraits, typename Alloc>
143  operator std::basic_string<Char, CharTraits, Alloc>() const {
144  return sh.end_message().str();
145  }
146  };
147 
148  template<typename Hasher, typename OutputIterator, typename StreamHash>
149  struct range_itr_hash_impl : public hash_impl {
150  private:
151  mutable StreamHash sh;
152 
153  mutable OutputIterator out;
154 
155  public:
156  template<typename SinglePassRange>
157  range_itr_hash_impl(const SinglePassRange &range, OutputIterator out, StreamHash stream_hash) :
158  out(std::move(out)), sh(std::move(stream_hash)) {
159  BOOST_CONCEPT_ASSERT((boost::SinglePassRangeConcept<SinglePassRange>));
160 
161  typedef
162  typename std::iterator_traits<typename SinglePassRange::iterator>::value_type value_type;
163 
164  BOOST_STATIC_ASSERT(std::numeric_limits<value_type>::is_specialized);
165 
166  sh.update(boost::begin(range), boost::end(range));
167  }
168 
169  operator OutputIterator() const {
170  const auto &result = sh.end_message();
171 
172  return std::move(result.begin(), result.end(), std::move(out));
173  }
174  };
175 
176  template<typename Hasher, typename OutputIterator, typename StreamHash>
177  struct itr_itr_hash_impl : public hash_impl {
178  private:
179  mutable StreamHash sh;
180 
181  mutable OutputIterator out;
182 
183  public:
184  template<typename InputIterator>
185  explicit itr_itr_hash_impl(InputIterator first, InputIterator last, OutputIterator out,
186  StreamHash stream_hash) :
187  out(std::move(out)),
188  sh(std::move(stream_hash)) {
189  BOOST_CONCEPT_ASSERT((boost::InputIteratorConcept<InputIterator>));
190 
191  typedef typename std::iterator_traits<InputIterator>::value_type value_type;
192 
193  BOOST_STATIC_ASSERT(std::numeric_limits<value_type>::is_specialized);
194 
195  sh.update(first, last);
196  }
197 
198  operator OutputIterator() const {
199  const auto &result = sh.end_message();
200 
201  return std::move(result.begin(), result.end(), std::move(out));
202  }
203  };
204 
212  template<typename Hasher, typename Input>
213  class hash {
214  private:
215  const detail::hash_impl &impl;
216 
217  public:
218  template<typename OutputIterator, typename StreamHash>
219  explicit hash(Input first, Input last, OutputIterator out, StreamHash sh) :
220  impl(std::move(detail::itr_itr_hash_impl<Hasher, OutputIterator, StreamHash>(
221  first, last, std::move(out), std::move(sh)))) {
222  }
223 
224  template<typename OutputIterator, typename StreamHash>
225  explicit hash(const Input &range, OutputIterator out, StreamHash sh) :
226  impl(std::move(detail::range_itr_hash_impl<Hasher, OutputIterator, StreamHash>(
227  range, std::move(out), std::move(sh)))) {
228  }
229 
230  template<typename StreamHash>
231  explicit hash(const Input &range, StreamHash sh) :
232  impl(std::move(detail::range_value_hash_impl<Hasher, StreamHash>(range, sh))) {
233  }
234 
235  private:
236  template<typename OutputIterator,
237  typename std::enable_if<detail::is_iterator<OutputIterator>::value &&
239  bool>::type = false>
240  OutputIterator to() const {
241  return static_cast<const detail::itr_itr_hash_impl<
242  Hasher, OutputIterator, detail::iterator_stream_hash_traits<Hasher, Input>> &>(impl);
243  }
244 
245  template<typename OutputIterator,
246  typename std::enable_if<detail::is_iterator<OutputIterator>::value &&
248  bool>::type = false>
249  OutputIterator to() const {
250  return static_cast<const detail::range_itr_hash_impl<
251  Hasher, OutputIterator, detail::range_stream_hash_traits<Hasher, Input>> &>(impl);
252  }
253 
254  template<typename OutputRange, typename std::enable_if<!detail::is_iterator<Input>::value &&
256  bool>::type = false>
257  OutputRange to() const {
258  return static_cast<const detail::range_value_hash_impl<
259  Hasher, detail::range_stream_hash_traits<Hasher, Input>> &>(impl);
260  }
261 
262  public:
263  template<typename Output>
264  operator Output() const {
265  return to<Output>();
266  }
267 
268  template<typename Char, typename CharTraits, typename Alloc>
269  operator std::basic_string<Char, CharTraits, Alloc>() const {
270  return static_cast<const detail::range_value_hash_impl<
272  }
273  };
274 
275 #endif
276  } // namespace detail
277 
293  template<typename Hasher, typename InputIterator, typename OutputIterator,
294  typename StreamHash = detail::iterator_stream_hash_traits<Hasher, InputIterator>,
295  typename = typename std::enable_if<detail::is_stream_hash<StreamHash>::value>::type>
296  OutputIterator hash(InputIterator first, InputIterator last, OutputIterator out,
297  StreamHash sh = StreamHash()) {
298  return detail::hash<Hasher, InputIterator>(first, last, std::move(out), std::move(sh));
299  };
300 
314  template<typename Hasher, typename InputIterator,
315  typename StreamHash = detail::iterator_stream_hash_traits<Hasher, InputIterator>,
316  typename = typename std::enable_if<detail::is_stream_hash<StreamHash>::value>::type>
317  detail::hash<Hasher, InputIterator> hash(InputIterator first, InputIterator last,
318  StreamHash sh = StreamHash()) {
319  return detail::hash<Hasher, InputIterator>(boost::any_range(first, last), std::move(sh));
320  };
321 
336  template<typename Hasher, typename SinglePassRange, typename OutputIterator,
337  typename StreamHash = detail::range_stream_hash_traits<Hasher, SinglePassRange>,
338  typename = typename std::enable_if<detail::is_stream_hash<StreamHash>::value>::type>
339  OutputIterator hash(const SinglePassRange &rng, OutputIterator out, StreamHash sh = StreamHash()) {
341  };
342 
355  template<typename Hasher, typename SinglePassRange,
356  typename StreamHash = detail::range_stream_hash_traits<Hasher, SinglePassRange>,
357  typename = typename std::enable_if<detail::is_stream_hash<StreamHash>::value>::type>
358  detail::hash<Hasher, SinglePassRange> hash(const SinglePassRange &rng, StreamHash sh = StreamHash()) {
360  };
361  } // namespace pbkdf
362  } // namespace crypto3
363 } // namespace nil
364 
365 #endif // CRYPTO3_PBKDF_HPP
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:213
hash(const Input &range, OutputIterator out, StreamHash sh)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:225
hash(const Input &range, StreamHash sh)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:231
hash(Input first, Input last, OutputIterator out, StreamHash sh)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:219
OutputIterator hash(InputIterator first, InputIterator last, OutputIterator out, StreamHash sh=StreamHash())
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:296
OutputIterator move(const SinglePassRange &rng, OutputIterator result)
Definition: move.hpp:45
typename Hasher::template stream_hash< std::numeric_limits< typename std::iterator_traits< InputIterator >::value_type >::digits+std::numeric_limits< typename std::iterator_traits< InputIterator >::value_type >::is_signed >::type iterator_stream_hash_traits
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:83
typename Hasher::template stream_hash< std::numeric_limits< typename std::iterator_traits< typename SinglePassRange::iterator >::value_type >::digits+std::numeric_limits< typename std::iterator_traits< typename SinglePassRange::iterator >::value_type >::is_signed >::type range_stream_hash_traits
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:78
Definition: pair.hpp:31
Definition: algebra/include/nil/crypto3/detail/type_traits.hpp:78
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:110
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:177
itr_itr_hash_impl(InputIterator first, InputIterator last, OutputIterator out, StreamHash stream_hash)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:185
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:149
range_itr_hash_impl(const SinglePassRange &range, OutputIterator out, StreamHash stream_hash)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:157
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:113
range_value_hash_impl(const SinglePassRange &range, StreamHash stream_hash)
Definition: pbkdf/include/nil/crypto3/pbkdf/algorithm/derive.hpp:119