emsa_x931.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 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_EMSA_X931_HPP
26 #define CRYPTO3_EMSA_X931_HPP
27 
29 
30 namespace nil {
31  namespace crypto3 {
32  namespace pubkey {
33  namespace padding {
34  namespace detail {
35  secure_vector<uint8_t> emsa2_encoding(const secure_vector<uint8_t> &msg, size_t output_bits,
36  const secure_vector<uint8_t> &empty_hash, uint8_t hash_id) {
37  const size_t HASH_SIZE = empty_hash.size();
38 
39  size_t output_length = (output_bits + 1) / 8;
40 
41  if (msg.size() != HASH_SIZE) {
42  throw encoding_error("EMSA_X931::encoding_of: Bad input length");
43  }
44  if (output_length < HASH_SIZE + 4) {
45  throw encoding_error("EMSA_X931::encoding_of: Output length is too small");
46  }
47 
48  const bool empty_input = (msg == empty_hash);
49 
50  secure_vector<uint8_t> output(output_length);
51 
52  output[0] = (empty_input ? 0x4B : 0x6B);
53  output[output_length - 3 - HASH_SIZE] = 0xBA;
54  set_mem(&output[1], output_length - 4 - HASH_SIZE, 0xBB);
55  buffer_insert(output, output_length - (HASH_SIZE + 2), msg.data(), msg.size());
56  output[output_length - 2] = hash_id;
57  output[output_length - 1] = 0xCC;
58 
59  return output;
60  }
61  } // namespace detail
62  template<typename Scheme, typename Hash>
63  struct emsa_x931 : public emsa<Scheme, Hash> {
64  template<typename InputIterator1, typename InputIterator2>
65  bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
66  InputIterator2 last2, std::size_t key_bits) const {
67  try {
68  return (std::equal(first1, last1, emsa2_encoding(first2, last2, key_bits, )));
69  } catch (const std::exception &exception) {
70  return false;
71  }
72  }
73 
74  template<typename SinglePassRange1, typename SinglePassRange2>
75  bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2,
76  std::size_t key_bits) const {
77  return verify(boost::begin(range1), boost::end(range1), boost::begin(range2),
78  boost::end(range2), 0);
79  }
80 
81  protected:
82  typedef SequenceContainer<uint8_t, Allocator<uint8_t>> empty_hash_type;
83 
84  template<typename InputIterator1, typename InputIterator2, typename OutputIterator>
85  OutputIterator emsa2_encoding(InputIterator1 first1, InputIterator1 last1, std::size_t output_bits,
86  InputIterator2 key_first2, InputIterator2 key_last2,
87  OutputIterator out) {
88  std::ptrdiff_t msg_size = std::distance(first1, last1);
89  std::ptrdiff_t empty_hash_size = std::distance(key_first2, key_last2);
90 
91  size_t output_length = (output_bits + 1) / 8;
92 
93  if (msg_size != empty_hash_size) {
94  throw encoding_error("EMSA_X931::encoding_of: Bad input length");
95  }
96 
97  if (output_length < empty_hash_size + 4) {
98  throw encoding_error("EMSA_X931::encoding_of: Output length is too small");
99  }
100 
101  const bool empty_input = std::equal(first1, last1, key_first2, key_last2);
102 
103  secure_vector<uint8_t> output(output_length);
104 
105  *out = (empty_input ? 0x4B : 0x6B);
106  *(out + output_length - 3 - empty_hash_size) = 0xBA;
107  set_mem(&output[1], output_length - 4 - empty_hash_size, 0xBB);
108  buffer_insert(output, output_length - (empty_hash_size + 2), msg.data(), msg.size());
109  output[output_length - 2] = Hash::policy_type::ieee1363_hash_id;
110  output[output_length - 1] = 0xCC;
111 
112  return out;
113  }
114 
115  protected:
117  };
118  } // namespace padding
119  } // namespace pubkey
120  } // namespace crypto3
121 } // namespace nil
122 
123 #endif
boost::mpl::apply< AccumulatorSet, tag::pubkey< ProcessingMode > >::type::result_type pubkey(const AccumulatorSet &acc)
Definition: accumulators/pubkey.hpp:106
secure_vector< uint8_t > emsa2_encoding(const secure_vector< uint8_t > &msg, size_t output_bits, const secure_vector< uint8_t > &empty_hash, uint8_t hash_id)
Definition: emsa_x931.hpp:35
void set_mem(T *ptr, size_t n, uint8_t val)
Definition: memory_operations.hpp:199
Definition: pair.hpp:31
EMSA, from IEEE 1363s Encoding Method for Signatures, Appendix.
Definition: emsa.hpp:48
Definition: emsa_x931.hpp:63
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: emsa_x931.hpp:75
empty_hash_type empty_hash
Definition: emsa_x931.hpp:116
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: emsa_x931.hpp:65
OutputIterator emsa2_encoding(InputIterator1 first1, InputIterator1 last1, std::size_t output_bits, InputIterator2 key_first2, InputIterator2 key_last2, OutputIterator out)
Definition: emsa_x931.hpp:85
SequenceContainer< uint8_t, Allocator< uint8_t > > empty_hash_type
Definition: emsa_x931.hpp:82