ecdsa.hpp
Go to the documentation of this file.
1 //---------------------------------------------------------------------------//
2 // Copyright (c) 2018-2020 Mikhail Komarov <nemo@nil.foundation>
3 // Copyright (c) 2021 Ilias Khairullin <ilias@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_PUBKEY_ECDSA_HPP
27 #define CRYPTO3_PUBKEY_ECDSA_HPP
28 
29 #include <utility>
30 
31 #include <nil/crypto3/random/rfc6979.hpp>
32 
34 
36 
38 
39 namespace nil {
40  namespace crypto3 {
41  namespace pubkey {
42  // TODO: add distribution support
43  // TODO: review ECDSA implementation and add auxiliary functional provided by the standard
44  // TODO: review generator passing
45  template<typename CurveType,
46  typename Padding,
47  typename GeneratorType,
48  typename DistributionType = void,
49  typename = typename std::enable_if<std::is_same<typename CurveType::scalar_field_type::value_type,
50  typename GeneratorType::result_type>::value>::type>
51  struct ecdsa {
53  typedef CurveType curve_type;
54  typedef Padding padding_policy;
55  typedef GeneratorType generator_type;
56  typedef DistributionType distribution_type;
57  typedef typename Padding::hash_type hash_type;
58 
61  };
62 
63  template<typename CurveType,
64  typename Padding,
65  typename GeneratorResultType,
66  typename GeneratorHash,
67  typename DistributionType>
68  struct ecdsa<CurveType,
69  Padding,
70  random::rfc6979<GeneratorResultType, GeneratorHash>,
71  DistributionType,
72  typename std::enable_if<std::is_same<typename Padding::hash_type, GeneratorHash>::value &&
73  std::is_same<typename CurveType::scalar_field_type::value_type,
74  GeneratorResultType>::value>::type> {
75  typedef random::rfc6979<GeneratorResultType, GeneratorHash> generator_type;
77  typedef CurveType curve_type;
78  typedef Padding padding_policy;
79  typedef DistributionType distribution_type;
80  typedef typename Padding::hash_type hash_type;
81 
84  };
85 
86  template<typename CurveType, typename Padding, typename GeneratorType, typename DistributionType>
87  struct public_key<ecdsa<CurveType, Padding, GeneratorType, DistributionType>> {
89 
92 
94 
95  typedef typename curve_type::scalar_field_type scalar_field_type;
96  typedef typename scalar_field_type::value_type scalar_field_value_type;
97  typedef typename curve_type::template g1_type<> g1_type;
98  typedef typename g1_type::value_type g1_value_type;
99  typedef typename curve_type::base_field_type::integral_type base_integral_type;
100  typedef typename scalar_field_type::modular_type scalar_modular_type;
101 
103  typedef std::pair<scalar_field_value_type, scalar_field_value_type> signature_type;
104 
105  public_key(const public_key_type &key) : pubkey(key) {
106  }
107 
108  static inline void init_accumulator(internal_accumulator_type &acc) {
109  }
110 
111  template<typename InputRange>
112  inline void update(internal_accumulator_type &acc, const InputRange &range) const {
113  encode<padding_policy>(range, acc);
114  }
115 
116  template<typename InputIterator>
117  inline void update(internal_accumulator_type &acc, InputIterator first, InputIterator last) const {
118  encode<padding_policy>(first, last, acc);
119  }
120 
121  inline bool verify(internal_accumulator_type &acc, const signature_type &signature) const {
122  scalar_field_value_type encoded_m =
123  padding::accumulators::extract::encode<padding::encoding_policy<padding_policy>>(acc);
124 
125  scalar_field_value_type w = signature.second.inversed();
126  g1_value_type X = (encoded_m * w) * g1_value_type::one() + (signature.first * w) * pubkey;
127  if (X.is_zero()) {
128  return false;
129  }
130  return signature.first == scalar_field_value_type(scalar_modular_type(
131  static_cast<base_integral_type>(X.to_affine().X.data),
132  scalar_field_value_type::modulus));
133  }
134 
135  inline public_key_type pubkey_data() const {
136  return pubkey;
137  }
138 
139  protected:
141  };
142 
143  template<typename CurveType, typename Padding, typename GeneratorType, typename DistributionType>
144  struct private_key<
145  ecdsa<CurveType, Padding, GeneratorType, DistributionType>,
146  typename std::enable_if<!std::is_same<
147  GeneratorType,
148  random::rfc6979<typename CurveType::scalar_field_type::value_type,
149  typename ecdsa<CurveType, Padding, GeneratorType, DistributionType>::hash_type>>::
150  value>::type>
151  : public public_key<ecdsa<CurveType, Padding, GeneratorType, DistributionType>> {
154 
160 
162 
163  typedef typename base_type::scalar_field_value_type scalar_field_value_type;
164  typedef typename base_type::g1_value_type g1_value_type;
165  typedef typename base_type::base_integral_type base_integral_type;
166  typedef typename base_type::scalar_modular_type scalar_modular_type;
167 
169  typedef typename base_type::public_key_type public_key_type;
170  typedef typename base_type::signature_type signature_type;
171 
172  private_key(const private_key_type &key) : privkey(key), base_type(generate_public_key(key)) {
173  }
174 
176  return key * public_key_type::one();
177  }
178 
179  static inline void init_accumulator(internal_accumulator_type &acc) {
180  }
181 
182  template<typename InputRange>
183  inline void update(internal_accumulator_type &acc, const InputRange &range) const {
184  encode<padding_policy>(range, acc);
185  }
186 
187  template<typename InputIterator>
188  inline void update(internal_accumulator_type &acc, InputIterator first, InputIterator last) const {
189  encode<padding_policy>(first, last, acc);
190  }
191 
192  // TODO: review to make blind signing
193  // TODO: add support of HMAC based generator (https://datatracker.ietf.org/doc/html/rfc6979)
194  // TODO: review passing of generator seed
196  generator_type gen;
197  scalar_field_value_type encoded_m =
198  padding::accumulators::extract::encode<padding::encoding_policy<padding_policy>>(acc);
199 
200  // TODO: review behaviour if k, r or s generation produced zero, maybe return status instead cycled
201  // generation
205  do {
206  while ((k = gen()).is_zero()) {
207  }
208  // TODO: review converting of kG x-coordinate to r - in case of 2^n order (binary) fields
209  // procedure seems not to be trivial
211  static_cast<base_integral_type>((k * g1_value_type::one()).to_affine().X.data),
212  scalar_field_value_type::modulus));
213  s = k.inversed() * (privkey * r + encoded_m);
214  } while (r.is_zero() || s.is_zero());
215 
216  return signature_type(r, s);
217  }
218 
219  protected:
221  };
222 
223  template<typename CurveType, typename Padding, typename GeneratorType, typename DistributionType>
224  struct private_key<
225  ecdsa<CurveType, Padding, GeneratorType, DistributionType>,
226  typename std::enable_if<std::is_same<
227  GeneratorType,
228  random::rfc6979<typename CurveType::scalar_field_type::value_type,
229  typename ecdsa<CurveType, Padding, GeneratorType, DistributionType>::hash_type>>::
230  value>::type>
231  : public public_key<ecdsa<CurveType, Padding, GeneratorType, DistributionType>> {
234 
240 
241  typedef std::pair<accumulator_set<hash_type>, padding::encoding_accumulator_set<padding_policy>>
243 
244  typedef typename base_type::scalar_field_value_type scalar_field_value_type;
245  typedef typename base_type::g1_value_type g1_value_type;
246  typedef typename base_type::base_integral_type base_integral_type;
247  typedef typename base_type::scalar_modular_type scalar_modular_type;
248 
250  typedef typename base_type::public_key_type public_key_type;
251  typedef typename base_type::signature_type signature_type;
252 
253  private_key(const private_key_type &key) : privkey(key), base_type(generate_public_key(key)) {
254  }
255 
257  return key * public_key_type::one();
258  }
259 
260  static inline void init_accumulator(internal_accumulator_type &acc) {
261  }
262 
263  template<typename InputRange>
264  inline void update(internal_accumulator_type &acc, const InputRange &range) const {
265  hash<hash_type>(range, acc.first);
266  encode<padding_policy>(range, acc.second);
267  }
268 
269  template<typename InputIterator>
270  inline void update(internal_accumulator_type &acc, InputIterator first, InputIterator last) const {
271  hash<hash_type>(first, last, acc.first);
272  encode<padding_policy>(first, last, acc.second);
273  }
274 
276  scalar_field_value_type encoded_m =
277  padding::accumulators::extract::encode<padding::encoding_policy<padding_policy>>(acc.second);
278 
279  auto h = ::nil::crypto3::accumulators::extract::hash<hash_type>(acc.first);
280  generator_type gen(privkey, h);
281 
282  // TODO: review behaviour if k, r or s generation produced zero, maybe return status instead cycled
283  // generation
287  do {
288  while ((k = gen()).is_zero()) {
289  }
290  // TODO: review converting of kG x-coordinate to r - in case of 2^n order (binary) fields
291  // procedure seems not to be trivial
293  static_cast<base_integral_type>((k * g1_value_type::one()).to_affine().X.data),
294  scalar_field_value_type::modulus));
295  s = (privkey * r + encoded_m) / k;
296  } while (r.is_zero() || s.is_zero());
297 
298  return signature_type(r, s);
299  }
300 
301  protected:
303  };
304  } // namespace pubkey
305  } // namespace crypto3
306 } // namespace nil
307 
308 #endif // CRYPTO3_PUBKEY_ECDSA_HPP
bool is_zero(const Range &a)
Definition: basic_operations.hpp:43
boost::mpl::apply< AccumulatorSet, tag::pubkey< ProcessingMode > >::type::result_type pubkey(const AccumulatorSet &acc)
Definition: accumulators/pubkey.hpp:106
boost::accumulators::accumulator_set< typename Padding::encoding_policy::result_type, boost::accumulators::features< accumulators::tag::encode< typename Padding::encoding_policy > >> encoding_accumulator_set
Accumulator set with pre-defined signing accumulator params.
Definition: padding_state.hpp:51
Definition: pair.hpp:31
Definition: ecdsa.hpp:51
DistributionType distribution_type
Definition: ecdsa.hpp:56
GeneratorType generator_type
Definition: ecdsa.hpp:55
Padding padding_policy
Definition: ecdsa.hpp:54
public_key< self_type > public_key_type
Definition: ecdsa.hpp:59
private_key< self_type > private_key_type
Definition: ecdsa.hpp:60
CurveType curve_type
Definition: ecdsa.hpp:53
ecdsa< CurveType, Padding, GeneratorType, DistributionType > self_type
Definition: ecdsa.hpp:52
Padding::hash_type hash_type
Definition: ecdsa.hpp:57
Private key - a key known only to its owner. Only the user keeping his private key secret guarantees ...
Definition: private_key.hpp:47
void update(internal_accumulator_type &acc, InputIterator first, InputIterator last) const
Definition: ecdsa.hpp:117
bool verify(internal_accumulator_type &acc, const signature_type &signature) const
Definition: ecdsa.hpp:121
ecdsa< CurveType, Padding, GeneratorType, DistributionType > policy_type
Definition: ecdsa.hpp:88
curve_type::base_field_type::integral_type base_integral_type
Definition: ecdsa.hpp:99
void update(internal_accumulator_type &acc, const InputRange &range) const
Definition: ecdsa.hpp:112
std::pair< scalar_field_value_type, scalar_field_value_type > signature_type
Definition: ecdsa.hpp:103
static void init_accumulator(internal_accumulator_type &acc)
Definition: ecdsa.hpp:108
padding::encoding_accumulator_set< padding_policy > internal_accumulator_type
Definition: ecdsa.hpp:93
Public key - a key that can be published and used to verify the authenticity of the signed document,...
Definition: public_key.hpp:43