codec/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 //
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_DIGEST_HPP
26 #define CRYPTO3_DIGEST_HPP
27 
28 #include <iostream>
29 
30 #include <boost/static_assert.hpp>
31 #include <boost/assert.hpp>
32 
33 #include <boost/container/small_vector.hpp>
34 
35 #include <nil/crypto3/detail/pack.hpp>
36 #include <nil/crypto3/detail/octet.hpp>
37 
38 namespace nil {
39  namespace crypto3 {
70  template<std::size_t DigestBits>
71  using digest = boost::container::small_vector<octet_type, DigestBits / octet_bits>;
72 
73  namespace detail {
74  template<std::size_t DigestBits, typename OutputIterator>
75  OutputIterator to_ascii(const boost::container::small_vector<octet_type, DigestBits / octet_bits> &d,
76  OutputIterator it) {
77  for (std::size_t j = 0; j < d.size(); ++j) {
78  octet_type b = d[j];
79  *it++ = "0123456789abcdef"[(b >> 4) & 0xF];
80  *it++ = "0123456789abcdef"[(b >> 0) & 0xF];
81  }
82  return it;
83  }
84 
85  template<std::size_t DigestBits>
86  digest<DigestBits / 4 + 1>
87  c_str(const boost::container::small_vector<octet_type, DigestBits / octet_bits> &d) {
88  digest<DigestBits / 4 + 1> s;
89  to_ascii<DigestBits>(d, std::back_inserter(s));
90  s.push_back('\0');
91  return s;
92  }
93  } // namespace detail
94 
95 
104  template<unsigned NewBits, unsigned OldBits>
105  digest<NewBits> reserve(const boost::container::small_vector<octet_type, OldBits / octet_bits> &od) {
106  digest<NewBits> nd;
107  unsigned bytes = sizeof(octet_type) * (NewBits < OldBits ? NewBits : OldBits) / octet_bits;
108  std::memcpy(nd.data(), od.data(), bytes);
109  return nd;
110  }
111 
120  template<std::size_t DigestBits>
121  digest<DigestBits> resize(const digest<DigestBits> &od, std::size_t new_size) {
122 
123  std::size_t old_size = od.size();
124 
125  if (new_size == old_size)
126  return od;
127 
128  digest<DigestBits> nd(new_size, octet_type());
129  std::size_t bytes = sizeof(octet_type) * (old_size < new_size ? old_size : new_size);
130  std::memcpy(nd.data(), od.data(), bytes);
131  return nd;
132  }
133 
144  template<unsigned NewBits, unsigned OldBits>
145  digest<NewBits> truncate(const boost::container::small_vector<octet_type, OldBits / octet_bits> &od) {
146  BOOST_STATIC_ASSERT(NewBits <= OldBits);
147  return resize<NewBits>(od);
148  }
149 
150  template<unsigned DB1, unsigned DB2>
151  bool operator==(const digest<DB1> &a, const digest<DB2> &b) {
152  unsigned const DB = DB1 < DB2 ? DB2 : DB1;
153  return resize<DB>(a).base_array() == resize<DB>(b).base_array();
154  }
155 
156  template<unsigned DB1, unsigned DB2>
157  bool operator!=(const digest<DB1> &a, const digest<DB2> &b) {
158  return !(a == b);
159  }
160 
161  template<unsigned DB1, unsigned DB2>
162  bool operator<(const digest<DB1> &a, const digest<DB2> &b) {
163  unsigned const DB = DB1 < DB2 ? DB2 : DB1;
164  return resize<DB>(a).base_array() < resize<DB>(b).base_array();
165  }
166 
167  template<unsigned DB1, unsigned DB2>
168  bool operator>(const digest<DB1> &a, const digest<DB2> &b) {
169  return b < a;
170  }
171 
172  template<unsigned DB1, unsigned DB2>
173  bool operator<=(const digest<DB1> &a, const digest<DB2> &b) {
174  return !(b < a);
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 DB>
183  bool operator!=(digest<DB> const &a, char const *b) {
184  BOOST_ASSERT(std::strlen(b) == DB / 4);
185  return static_cast<bool>(std::strcmp(a.cstring().data(), b));
186  }
187 
188  template<unsigned DB>
189  bool operator==(digest<DB> const &a, char const *b) {
190  return !(a != b);
191  }
192 
193  template<unsigned DB>
194  bool operator!=(char const *b, digest<DB> const &a) {
195  return a != b;
196  }
197 
198  template<unsigned DB>
199  bool operator==(char const *b, digest<DB> const &a) {
200  return a == b;
201  }
202 
203  template<unsigned DB>
204  std::ostream &operator<<(std::ostream &sink, digest<DB> const &d) {
205  d.to_ascii(std::ostream_iterator<char>(sink));
206  return sink;
207  }
208 
209  template<unsigned DB>
210  std::istream &operator>>(std::istream &source, digest<DB> &d) {
211  std::array<char, DB / 4> a = {{}};
212  for (unsigned i = 0; i < a.size(); ++i) {
213  char c;
214  if (!source.get(c)) {
215  source.setstate(std::ios::failbit);
216  break;
217  }
218  if (!std::isxdigit(c, source.getloc())) {
219  source.unget();
220  source.setstate(std::ios::failbit);
221  break;
222  }
223 
224  if (std::isdigit(c, source.getloc())) {
225  a[i] = (c - '0');
226  } else {
227  a[i] = std::toupper(c, source.getloc()) - 'A' + 0xA;
228  }
229  }
230  detail::pack<stream_endian::big_bit, stream_endian::big_bit, 4, 8>(a.begin(), a.end(), d.begin());
231  return source;
232  }
233  } // namespace crypto3
234 } // namespace nil
235 
236 namespace std {
237  template<std::size_t DigestBits>
238  std::string to_string(const nil::crypto3::digest<DigestBits> &d) {
239  nil::crypto3::digest<DigestBits / 4 + 1> cstr = nil::crypto3::detail::c_str(d);
240  return std::string(cstr.begin(), cstr.begin() + cstr.size() - 1);
241  }
242 } // namespace std
243 
244 #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