emsa_pkcs1.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_PKCS1_HPP
26 #define CRYPTO3_EMSA_PKCS1_HPP
27 
29 
30 namespace nil {
31  namespace crypto3 {
32  namespace pubkey {
33  namespace padding {
34  namespace detail {
35  secure_vector<uint8_t> emsa3_encoding(const secure_vector<uint8_t> &msg, size_t output_bits,
36  const uint8_t hash_id[], size_t hash_id_length) {
37  size_t output_length = output_bits / 8;
38  if (output_length < hash_id_length + msg.size() + 10) {
39  throw encoding_error("emsa3_encoding: Output length is too small");
40  }
41 
42  secure_vector<uint8_t> T(output_length);
43  const size_t P_LENGTH = output_length - msg.size() - hash_id_length - 2;
44 
45  T[0] = 0x01;
46  set_mem(&T[1], P_LENGTH, 0xFF);
47  T[P_LENGTH + 1] = 0x00;
48 
49  if (hash_id_length > 0) {
50  BOOST_ASSERT(hash_id != nullptr)
51  buffer_insert(T, P_LENGTH + 2, hash_id, hash_id_length);
52  }
53 
54  buffer_insert(T, output_length - msg.size(), msg.data(), msg.size());
55  return T;
56  }
57  } // namespace detail
58 
59  template<typename Scheme, typename Hash>
60  struct emsa_pkcs1v15_base : public emsa<Scheme, Hash> {
61  template<typename InputMessageIterator, typename OutputIterator>
62  secure_vector<uint8_t> emsa3_encoding(InputMessageIterator first1, InputMessageIterator last1,
63  size_t output_bits) {
64  size_t output_length = output_bits / 8;
65  std::ptrdiff_t message_length = std::distance(first1, last1);
66 
67  if (output_length < Hash::policy_type::pkcs_id.size() + message_length + 10) {
68  throw encoding_error("emsa3_encoding: Output length is too small");
69  }
70 
71  secure_vector<uint8_t> T(output_length);
72  const size_t P_LENGTH = output_length - message_length - Hash::policy_type::pkcs_id.size() - 2;
73 
74  T[0] = 0x01;
75  set_mem(&T[1], P_LENGTH, 0xFF);
76  T[P_LENGTH + 1] = 0x00;
77 
78  if (Hash::policy_type::pkcs_id.size() > 0) {
79  BOOST_ASSERT(Hash::policy_type::pkcs_id != nullptr);
80  buffer_insert(T, P_LENGTH + 2, Hash::policy_type::pkcs_id,
81  Hash::policy_type::pkcs_id.size());
82  }
83 
84  buffer_insert(T, output_length - message_length, msg.data(), message_length);
85  return T;
86  }
87  };
88 
93  template<typename Scheme, typename Hash>
94  struct emsa_pkcs1v15 : public emsa_pkcs1v15_base<Hash> {
95  template<typename InputIterator1, typename InputIterator2>
96  bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
97  InputIterator2 last2, std::size_t key_bits) const {
98  std::ptrdiff_t raw_length = std::distance(first2, last2);
99  if (raw_length != Hash::policy_type::digest_bits) {
100  return false;
101  }
102 
103  try {
104  return std::equal(first1, last1, emsa3_encoding(first2, last2, key_bits));
105  } catch (const std::exception &) {
106  return false;
107  }
108  }
109 
110  template<typename SinglePassRange1, typename SinglePassRange2>
111  bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2,
112  std::size_t key_bits) const {
113  return verify(boost::begin(range1), boost::end(range1), boost::begin(range2),
114  boost::end(range2), key_bits);
115  }
116  };
117 
127  template<typename Scheme, typename Hash>
128  struct emsa_pkcs1v15_raw : public emsa_pkcs1v15_base<Hash> {
129  template<typename InputIterator1, typename InputIterator2>
130  bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2,
131  InputIterator2 last2, std::size_t key_bits) const {
132  if (Hash::policy_type::digest_bits > 0 &&
133  std::distance(first2, last2) != Hash::policy_type::digest_bits) {
134  return false;
135  }
136 
137  try {
138  return std::equal(first1, last1, emsa3_encoding(first2, last2, key_bits));
139  } catch (const std::exception &) {
140  return false;
141  }
142  }
143 
144  template<typename SinglePassRange1, typename SinglePassRange2>
145  bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2,
146  std::size_t key_bits) const {
147  return verify(boost::begin(range1), boost::end(range1), boost::begin(range2),
148  boost::end(range2), 0);
149  }
150  };
151  } // namespace padding
152  } // namespace pubkey
153  } // namespace crypto3
154 } // namespace nil
155 
156 #endif
boost::mpl::apply< AccumulatorSet, tag::pubkey< ProcessingMode > >::type::result_type pubkey(const AccumulatorSet &acc)
Definition: accumulators/pubkey.hpp:106
secure_vector< uint8_t > emsa3_encoding(const secure_vector< uint8_t > &msg, size_t output_bits, const uint8_t hash_id[], size_t hash_id_length)
Definition: emsa_pkcs1.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
secure_vector< uint8_t > emsa3_encoding(InputMessageIterator first1, InputMessageIterator last1, size_t output_bits)
Definition: emsa_pkcs1.hpp:62
EMSA_PKCS1v15_Raw which is EMSA_PKCS1v15 without a hash or digest id (which according to QCA docs is ...
Definition: emsa_pkcs1.hpp:128
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: emsa_pkcs1.hpp:145
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: emsa_pkcs1.hpp:130
PKCS #1 v1.5 signature padding aka PKCS #1 block type 1 aka EMSA3 from IEEE 1363
Definition: emsa_pkcs1.hpp:94
bool verify(const SinglePassRange1 &range1, const SinglePassRange2 &range2, std::size_t key_bits) const
Definition: emsa_pkcs1.hpp:111
bool verify(InputIterator1 first1, InputIterator1 last1, InputIterator2 first2, InputIterator2 last2, std::size_t key_bits) const
Definition: emsa_pkcs1.hpp:96