block/include/nil/crypto3/detail/static_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_STATIC_DIGEST_HPP
26 #define CRYPTO3_STATIC_DIGEST_HPP
27 
28 #include <boost/static_assert.hpp>
29 #include <boost/assert.hpp>
30 
31 #include <array>
32 #include <string>
33 #include <cstring>
34 #include <iostream>
35 
36 #include <nil/crypto3/detail/octet.hpp>
37 #include <nil/crypto3/detail/pack.hpp>
38 
39 namespace nil {
40  namespace crypto3 {
71  template<std::size_t DigestBits>
72  class static_digest : public std::array<octet_type, DigestBits / octet_bits> { };
73 
74  namespace detail {
75  template<std::size_t DigestBits, typename OutputIterator>
76  OutputIterator to_ascii(const static_digest<DigestBits> &d, OutputIterator it) {
77  for (std::size_t j = 0; j < DigestBits / octet_bits; ++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  std::array<char, DigestBits / 4 + 1> c_str(const static_digest<DigestBits> &d) {
87  std::array<char, DigestBits / 4 + 1> s;
88  char *p = to_ascii<DigestBits>(d, s.data());
89  *p++ = '\0';
90  return s;
91  }
92  } // namespace detail
93  } // namespace crypto3
94 } // namespace nil
95 
96 namespace std {
97  template<std::size_t DigestBits>
99  std::array<char, DigestBits / 4 + 1> cstr = nil::crypto3::detail::c_str(d);
100  return std::string(cstr.data(), cstr.size() - 1);
101  }
102 } // namespace std
103 
104 namespace nil {
105  namespace crypto3 {
106 
115  template<std::size_t NewBits, std::size_t OldBits>
118  nd.fill(0);
119  std::size_t bytes = sizeof(octet_type) * (NewBits < OldBits ? NewBits : OldBits) / octet_bits;
120  std::memcpy(nd.data(), od.data(), bytes);
121  return nd;
122  }
123 
134  template<std::size_t NewBits, std::size_t OldBits>
136  BOOST_STATIC_ASSERT(NewBits <= OldBits);
137  return resize<NewBits>(od);
138  }
139 
140  template<std::size_t DB1, std::size_t DB2>
142  // TODO: Think about size of static_digest. We can't use resize here because
143  // it's change element which we compare
144  return static_cast<bool>(DB1 == DB2 ? std::equal(std::begin(a), std::end(a), std::begin(b), std::end(b)) :
145  0);
146  }
147 
148  template<std::size_t DB1, std::size_t DB2>
150  return !(a == b);
151  }
152 
153  template<std::size_t DB1, std::size_t DB2>
155  // #TODO: Implement this right
156  return DB1 < DB2;
157  }
158 
159  template<std::size_t DB1, std::size_t DB2>
161  return b < a;
162  }
163 
164  template<std::size_t DB1, std::size_t DB2>
166  return !(b < a);
167  }
168 
169  template<std::size_t DB1, std::size_t DB2>
171  return !(b > a);
172  }
173 
174  template<std::size_t DB>
175  bool operator!=(const static_digest<DB> &a, char const *b) {
176  BOOST_ASSERT(std::strlen(b) == DB / 4);
177  return std::to_string(a) != b;
178  }
179 
180  template<std::size_t DB>
181  bool operator==(const static_digest<DB> &a, char const *b) {
182  return !(a != b);
183  }
184 
185  template<std::size_t DB>
186  bool operator!=(char const *b, const static_digest<DB> &a) {
187  return a != b;
188  }
189 
190  template<std::size_t DB>
191  bool operator==(char const *b, const static_digest<DB> &a) {
192  return a == b;
193  }
194 
195  template<std::size_t DigestBits>
196  std::ostream &operator<<(std::ostream &sink, const static_digest<DigestBits> &d) {
197  detail::to_ascii<DigestBits>(d, std::ostream_iterator<char>(sink));
198  return sink;
199  }
200 
201  template<std::size_t DigestBits>
202  std::istream &operator>>(std::istream &source, static_digest<DigestBits> &d) {
203  std::array<char, DigestBits / 4> a = {{}};
204  for (unsigned i = 0; i < a.size(); ++i) {
205  char c;
206  if (!source.get(c)) {
207  source.setstate(std::ios::failbit);
208  break;
209  }
210  if (!std::isxdigit(c, source.getloc())) {
211  source.unget();
212  source.setstate(std::ios::failbit);
213  break;
214  }
215 
216  if (std::isdigit(c, source.getloc())) {
217  a[i] = (c - '0');
218  } else {
219  a[i] = std::toupper(c, source.getloc()) - 'A' + 0xA;
220  }
221  }
222  detail::pack<stream_endian::big_bit, stream_endian::big_bit, 4, 8>(a.begin(), a.end(), d.begin());
223  return source;
224  }
225  } // namespace crypto3
226 } // namespace nil
227 
228 #endif // CRYPTO3_HASH_DIGEST_HPP
std::string to_string(const nil::crypto3::digest< DigestBits > &d)
Definition: block/include/nil/crypto3/detail/digest.hpp:248
Definition: block/include/nil/crypto3/detail/static_digest.hpp:72
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
bool operator>=(const digest< DB1 > &a, const digest< DB2 > &b)
Definition: block/include/nil/crypto3/detail/digest.hpp:188
Definition: pair.hpp:31