block/include/nil/crypto3/detail/digest.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2020 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 
26 #ifndef CRYPTO3_DIGEST_HPP
27 #define CRYPTO3_DIGEST_HPP
28 
29 #include <iostream>
30 
31 #include <boost/static_assert.hpp>
32 #include <boost/assert.hpp>
33 
34 #include <boost/container/small_vector.hpp>
35 
36 #include <nil/crypto3/detail/pack.hpp>
37 #include <nil/crypto3/detail/octet.hpp>
38 
39 namespace nil {
40  namespace crypto3 {
71  template<std::size_t DigestBits>
72  struct digest : public boost::container::small_vector<octet_type, DigestBits / octet_bits> {
73 
74  digest(): boost::container::small_vector<octet_type, DigestBits / octet_bits>(){};
75 
76  digest(std::size_t sz, octet_type ot): boost::container::small_vector<octet_type, DigestBits / octet_bits>(sz, ot){};
77  };
78 
79 
80  //template<std::size_t DigestBits>
81  //using digest = boost::container::small_vector<octet_type, DigestBits / octet_bits>;
82 
83 
84  namespace detail {
85  template<std::size_t DigestBits, typename OutputIterator>
86  OutputIterator to_ascii(const digest<DigestBits> &d,
87  OutputIterator it) {
88  for (std::size_t j = 0; j < d.size(); ++j) {
89  octet_type b = d[j];
90  *it++ = "0123456789abcdef"[(b >> 4) & 0xF];
91  *it++ = "0123456789abcdef"[(b >> 0) & 0xF];
92  }
93  return it;
94  }
95 
96  template<std::size_t DigestBits>
97  digest<DigestBits / 4 + 1>
99  digest<DigestBits / 4 + 1> s;
100  to_ascii<DigestBits>(d, std::back_inserter(s));
101  s.push_back('\0');
102  return s;
103  }
104  } // namespace detail
105 
114  template<unsigned NewBits, unsigned OldBits>
116  digest<NewBits> nd;
117  unsigned bytes = sizeof(octet_type) * (NewBits < OldBits ? NewBits : OldBits) / octet_bits;
118  std::memcpy(nd.data(), od.data(), bytes);
119  return nd;
120  }
121 
130  template<std::size_t DigestBits>
131  digest<DigestBits> resize(const digest<DigestBits> &od, std::size_t new_size) {
132 
133  std::size_t old_size = od.size();
134 
135  if (new_size == old_size)
136  return od;
137 
138  digest<DigestBits> nd(new_size, octet_type());
139  std::size_t bytes = sizeof(octet_type) * (old_size < new_size ? old_size : new_size);
140  std::memcpy(nd.data(), od.data(), bytes);
141  return nd;
142  }
143 
154  template<unsigned NewBits, unsigned OldBits>
156  BOOST_STATIC_ASSERT(NewBits <= OldBits);
157  return resize<NewBits>(od);
158  }
159 
160  template<unsigned DB1, unsigned DB2>
161  bool operator==(const digest<DB1> &a, const digest<DB2> &b) {
162  unsigned const DB = DB1 < DB2 ? DB2 : DB1;
163  return resize<DB>(a).base_array() == resize<DB>(b).base_array();
164  }
165 
166  template<unsigned DB1, unsigned DB2>
167  bool operator!=(const digest<DB1> &a, const digest<DB2> &b) {
168  return !(a == b);
169  }
170 
171  template<unsigned DB1, unsigned DB2>
172  bool operator<(const digest<DB1> &a, const digest<DB2> &b) {
173  unsigned const DB = DB1 < DB2 ? DB2 : DB1;
174  return resize<DB>(a).base_array() < resize<DB>(b).base_array();
175  }
176 
177  template<unsigned DB1, unsigned DB2>
178  bool operator>(const digest<DB1> &a, const digest<DB2> &b) {
179  return b < a;
180  }
181 
182  template<unsigned DB1, unsigned DB2>
183  bool operator<=(const digest<DB1> &a, const digest<DB2> &b) {
184  return !(b < a);
185  }
186 
187  template<unsigned DB1, unsigned DB2>
188  bool operator>=(const digest<DB1> &a, const digest<DB2> &b) {
189  return !(b > a);
190  }
191 
192  template<unsigned DB>
193  bool operator!=(digest<DB> const &a, char const *b) {
194  BOOST_ASSERT(std::strlen(b) == DB / 4);
195  return static_cast<bool>(std::strcmp(a.cstring().data(), b));
196  }
197 
198  template<unsigned DB>
199  bool operator==(digest<DB> const &a, char const *b) {
200  return !(a != b);
201  }
202 
203  template<unsigned DB>
204  bool operator!=(char const *b, digest<DB> const &a) {
205  return a != b;
206  }
207 
208  template<unsigned DB>
209  bool operator==(char const *b, digest<DB> const &a) {
210  return a == b;
211  }
212 
213  template<unsigned DB>
214  std::ostream &operator<<(std::ostream &sink, digest<DB> const &d) {
215  d.to_ascii(std::ostream_iterator<char>(sink));
216  return sink;
217  }
218 
219  template<unsigned DB>
220  std::istream &operator>>(std::istream &source, digest<DB> &d) {
221  std::array<char, DB / 4> a = {{}};
222  for (unsigned i = 0; i < a.size(); ++i) {
223  char c;
224  if (!source.get(c)) {
225  source.setstate(std::ios::failbit);
226  break;
227  }
228  if (!std::isxdigit(c, source.getloc())) {
229  source.unget();
230  source.setstate(std::ios::failbit);
231  break;
232  }
233 
234  if (std::isdigit(c, source.getloc())) {
235  a[i] = (c - '0');
236  } else {
237  a[i] = std::toupper(c, source.getloc()) - 'A' + 0xA;
238  }
239  }
240  detail::pack<stream_endian::big_bit, stream_endian::big_bit, 4, 8>(a.begin(), a.end(), d.begin());
241  return source;
242  }
243  } // namespace crypto3
244 } // namespace nil
245 
246 namespace std {
247  template<std::size_t DigestBits>
249  nil::crypto3::digest<DigestBits / 4 + 1> cstr = nil::crypto3::detail::c_str(d);
250  return std::string(cstr.begin(), cstr.begin() + cstr.size() - 1);
251  }
252 } // namespace std
253 
254 #endif // CRYPTO3_DIGEST_HPP
std::string to_string(const nil::crypto3::digest< DigestBits > &d)
Definition: block/include/nil/crypto3/detail/digest.hpp:248
OutputIterator to_ascii(const digest< DigestBits > &d, OutputIterator it)
Definition: block/include/nil/crypto3/detail/digest.hpp:86
digest< DigestBits/4+1 > c_str(const digest< DigestBits > &d)
Definition: block/include/nil/crypto3/detail/digest.hpp:98
boost::uint_t< octet_bits >::least octet_type
Definition: algebra/include/nil/crypto3/detail/octet.hpp:33
std::istream & operator>>(std::istream &source, digest< DB > &d)
Definition: block/include/nil/crypto3/detail/digest.hpp:220
bool operator>(const digest< DB1 > &a, const digest< DB2 > &b)
Definition: block/include/nil/crypto3/detail/digest.hpp:178
bool operator<(const digest< DB1 > &a, const digest< DB2 > &b)
Definition: block/include/nil/crypto3/detail/digest.hpp:172
bool operator!=(const secure_allocator< T > &, const secure_allocator< U > &)
Definition: secure_allocator.hpp:98
std::ostream & operator<<(std::ostream &sink, digest< DB > const &d)
Definition: block/include/nil/crypto3/detail/digest.hpp:214
bool operator==(const secure_allocator< T > &, const secure_allocator< U > &)
Definition: secure_allocator.hpp:93
digest< DigestBits > resize(const digest< DigestBits > &od, std::size_t new_size)
Definition: block/include/nil/crypto3/detail/digest.hpp:131
digest< NewBits > truncate(const digest< OldBits > &od)
Definition: block/include/nil/crypto3/detail/digest.hpp:155
bool operator<=(const digest< DB1 > &a, const digest< DB2 > &b)
Definition: block/include/nil/crypto3/detail/digest.hpp:183
digest< NewBits > reserve(const digest< OldBits > &od)
Definition: block/include/nil/crypto3/detail/digest.hpp:115
bool operator>=(const digest< DB1 > &a, const digest< DB2 > &b)
Definition: block/include/nil/crypto3/detail/digest.hpp:188
Definition: pair.hpp:31
Definition: block/include/nil/crypto3/detail/digest.hpp:72
digest()
Definition: block/include/nil/crypto3/detail/digest.hpp:74
digest(std::size_t sz, octet_type ot)
Definition: block/include/nil/crypto3/detail/digest.hpp:76