Electroneum
crypto.cpp
Go to the documentation of this file.
1 // Copyrights(c) 2017-2021, The Electroneum Project
2 // Copyrights(c) 2014-2019, The Monero Project
3 //
4 // All rights reserved.
5 //
6 // Redistribution and use in source and binary forms, with or without modification, are
7 // permitted provided that the following conditions are met:
8 //
9 // 1. Redistributions of source code must retain the above copyright notice, this list of
10 // conditions and the following disclaimer.
11 //
12 // 2. Redistributions in binary form must reproduce the above copyright notice, this list
13 // of conditions and the following disclaimer in the documentation and/or other
14 // materials provided with the distribution.
15 //
16 // 3. Neither the name of the copyright holder nor the names of its contributors may be
17 // used to endorse or promote products derived from this software without specific
18 // prior written permission.
19 //
20 // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21 // EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22 // MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23 // THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 // SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
25 // PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
27 // STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
28 // THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
29 //
30 // Parts of this file are originally copyright (c) 2012-2013 The Cryptonote developers
31 
32 #include <unistd.h>
33 #include <cassert>
34 #include <cstddef>
35 #include <cstdint>
36 #include <cstdlib>
37 #include <cstring>
38 #include <boost/thread/mutex.hpp>
39 #include <boost/thread/lock_guard.hpp>
40 #include <boost/shared_ptr.hpp>
41 
42 #include "common/varint.h"
43 #include "crypto.h"
44 #include "hash.h"
45 
46 namespace {
47  static void local_abort(const char *msg)
48  {
49  fprintf(stderr, "%s\n", msg);
50 #ifdef NDEBUG
51  _exit(1);
52 #else
53  abort();
54 #endif
55  }
56 }
57 
58 namespace crypto {
59 
60  using std::abort;
61  using std::int32_t;
62  using std::int64_t;
63  using std::size_t;
64  using std::uint32_t;
65  using std::uint64_t;
66 
67  extern "C" {
68 #include "crypto-ops.h"
69 #include "random.h"
70  }
71 
74 
75  static inline unsigned char *operator &(ec_point &point) {
76  return &reinterpret_cast<unsigned char &>(point);
77  }
78 
79  static inline const unsigned char *operator &(const ec_point &point) {
80  return &reinterpret_cast<const unsigned char &>(point);
81  }
82 
83  static inline unsigned char *operator &(ec_scalar &scalar) {
84  return &reinterpret_cast<unsigned char &>(scalar);
85  }
86 
87  static inline const unsigned char *operator &(const ec_scalar &scalar) {
88  return &reinterpret_cast<const unsigned char &>(scalar);
89  }
90 
92  {
93  static boost::mutex random_lock;
94  boost::lock_guard<boost::mutex> lock(random_lock);
96  }
97 
98  static inline bool less32(const unsigned char *k0, const unsigned char *k1)
99  {
100  for (int n = 31; n >= 0; --n)
101  {
102  if (k0[n] < k1[n])
103  return true;
104  if (k0[n] > k1[n])
105  return false;
106  }
107  return false;
108  }
109 
110  void random32_unbiased(unsigned char *bytes)
111  {
112  // l = 2^252 + 27742317777372353535851937790883648493.
113  // it fits 15 in 32 bytes
114  static const unsigned char limit[32] = { 0xe3, 0x6a, 0x67, 0x72, 0x8b, 0xce, 0x13, 0x29, 0x8f, 0x30, 0x82, 0x8c, 0x0b, 0xa4, 0x10, 0x39, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf0 };
115  do
116  {
118  } while (!sc_isnonzero(bytes) && !less32(bytes, limit)); // should be good about 15/16 of the time
119  sc_reduce32(bytes);
120  }
121  /* generate a random 32-byte (256-bit) integer and copy it to res */
123  random32_unbiased((unsigned char*)res.data);
124  }
125 
126  void hash_to_scalar(const void *data, size_t length, ec_scalar &res) {
127  cn_fast_hash(data, length, reinterpret_cast<hash &>(res));
128  sc_reduce32(&res);
129  }
130 
131  /*
132  * generate public and secret keys from a random 256-bit integer
133  * TODO: allow specifying random value (for wallet recovery)
134  *
135  */
136  secret_key crypto_ops::generate_keys(public_key &pub, secret_key &sec, const secret_key& recovery_key, bool recover) {
137  ge_p3 point;
138 
139  secret_key rng;
140 
141  if (recover)
142  {
143  rng = recovery_key;
144  }
145  else
146  {
147  random_scalar(rng);
148  }
149  sec = rng;
150  sc_reduce32(&unwrap(sec)); // reduce in case second round of keys (sendkeys)
151 
152  ge_scalarmult_base(&point, &unwrap(sec));
153  ge_p3_tobytes(&pub, &point);
154 
155  return rng;
156  }
157 
158  bool crypto_ops::check_key(const public_key &key) {
159  ge_p3 point;
160  return ge_frombytes_vartime(&point, &key) == 0;
161  }
162 
163  bool crypto_ops::secret_key_to_public_key(const secret_key &sec, public_key &pub) {
164  ge_p3 point;
165  if (sc_check(&unwrap(sec)) != 0) {
166  return false;
167  }
168  ge_scalarmult_base(&point, &unwrap(sec));
169  ge_p3_tobytes(&pub, &point);
170  return true;
171  }
172 
173  bool crypto_ops::generate_key_derivation(const public_key &key1, const secret_key &key2, key_derivation &derivation) {
174  ge_p3 point;
175  ge_p2 point2;
176  ge_p1p1 point3;
177  assert(sc_check(&key2) == 0);
178  if (ge_frombytes_vartime(&point, &key1) != 0) {
179  return false;
180  }
181  ge_scalarmult(&point2, &unwrap(key2), &point);
182  ge_mul8(&point3, &point2);
183  ge_p1p1_to_p2(&point2, &point3);
184  ge_tobytes(&derivation, &point2);
185  return true;
186  }
187 
188  void crypto_ops::derivation_to_scalar(const key_derivation &derivation, size_t output_index, ec_scalar &res) {
189  struct {
190  key_derivation derivation;
191  char output_index[(sizeof(size_t) * 8 + 6) / 7];
192  } buf;
193  char *end = buf.output_index;
194  buf.derivation = derivation;
196  assert(end <= buf.output_index + sizeof buf.output_index);
197  hash_to_scalar(&buf, end - reinterpret_cast<char *>(&buf), res);
198  }
199 
200  bool crypto_ops::derive_public_key(const key_derivation &derivation, size_t output_index,
201  const public_key &base, public_key &derived_key) {
202  ec_scalar scalar;
203  ge_p3 point1;
204  ge_p3 point2;
205  ge_cached point3;
206  ge_p1p1 point4;
207  ge_p2 point5;
208  if (ge_frombytes_vartime(&point1, &base) != 0) {
209  return false;
210  }
211  derivation_to_scalar(derivation, output_index, scalar);
212  ge_scalarmult_base(&point2, &scalar);
213  ge_p3_to_cached(&point3, &point2);
214  ge_add(&point4, &point1, &point3);
215  ge_p1p1_to_p2(&point5, &point4);
216  ge_tobytes(&derived_key, &point5);
217  return true;
218  }
219 
220  void crypto_ops::derive_secret_key(const key_derivation &derivation, size_t output_index,
221  const secret_key &base, secret_key &derived_key) {
222  ec_scalar scalar;
223  assert(sc_check(&base) == 0);
224  derivation_to_scalar(derivation, output_index, scalar);
225  sc_add(&unwrap(derived_key), &unwrap(base), &scalar);
226  }
227 
228  bool crypto_ops::derive_subaddress_public_key(const public_key &out_key, const key_derivation &derivation, std::size_t output_index, public_key &derived_key) {
229  ec_scalar scalar;
230  ge_p3 point1;
231  ge_p3 point2;
232  ge_cached point3;
233  ge_p1p1 point4;
234  ge_p2 point5;
235  if (ge_frombytes_vartime(&point1, &out_key) != 0) {
236  return false;
237  }
238  derivation_to_scalar(derivation, output_index, scalar);
239  ge_scalarmult_base(&point2, &scalar);
240  ge_p3_to_cached(&point3, &point2);
241  ge_sub(&point4, &point1, &point3);
242  ge_p1p1_to_p2(&point5, &point4);
243  ge_tobytes(&derived_key, &point5);
244  return true;
245  }
246 
247  struct s_comm {
251  };
252 
253  struct s_comm_2 {
258  };
259 
260  struct s_comm_3 {
265  };
266 
267  void crypto_ops::generate_signature(const hash &prefix_hash, const public_key &pub, const secret_key &sec, signature &sig) {
268  ge_p3 tmp3;
269  ec_scalar k;
270  s_comm buf;
271 #if !defined(NDEBUG)
272  {
273  ge_p3 t;
274  public_key t2;
275  assert(sc_check(&sec) == 0);
276  ge_scalarmult_base(&t, &sec);
277  ge_p3_tobytes(&t2, &t);
278  assert(pub == t2);
279  }
280 #endif
281  buf.h = prefix_hash;
282  buf.key = pub;
283  try_again:
284  random_scalar(k);
285  if (((const uint32_t*)(&k))[7] == 0) // we don't want tiny numbers here
286  goto try_again;
287  ge_scalarmult_base(&tmp3, &k);
288  ge_p3_tobytes(&buf.comm, &tmp3);
289  hash_to_scalar(&buf, sizeof(s_comm), sig.c);
290  if (!sc_isnonzero((const unsigned char*)sig.c.data))
291  goto try_again;
292  sc_mulsub(&sig.r, &sig.c, &unwrap(sec), &k);
293  if (!sc_isnonzero((const unsigned char*)sig.r.data))
294  goto try_again;
295  }
296 
297  bool crypto_ops::check_signature(const hash &prefix_hash, const public_key &pub, const signature &sig) {
298  ge_p2 tmp2;
299  ge_p3 tmp3;
300  ec_scalar c;
301  s_comm buf;
302  assert(check_key(pub));
303  buf.h = prefix_hash;
304  buf.key = pub;
305  if (ge_frombytes_vartime(&tmp3, &pub) != 0) {
306  return false;
307  }
308  if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0 || !sc_isnonzero(&sig.c)) {
309  return false;
310  }
311  ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r);
312  ge_tobytes(&buf.comm, &tmp2);
313  static const ec_point infinity = {{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
314  if (memcmp(&buf.comm, &infinity, 32) == 0)
315  return false;
316  hash_to_scalar(&buf, sizeof(s_comm), c);
317  sc_sub(&c, &c, &sig.c);
318  return sc_isnonzero(&c) == 0;
319  }
320 
321  void crypto_ops::generate_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const secret_key &r, signature &sig) {
322  // sanity check
323  ge_p3 R_p3;
324  ge_p3 A_p3;
325  ge_p3 B_p3;
326  ge_p3 D_p3;
327  if (ge_frombytes_vartime(&R_p3, &R) != 0) throw std::runtime_error("tx pubkey is invalid");
328  if (ge_frombytes_vartime(&A_p3, &A) != 0) throw std::runtime_error("recipient view pubkey is invalid");
329  if (B && ge_frombytes_vartime(&B_p3, &*B) != 0) throw std::runtime_error("recipient spend pubkey is invalid");
330  if (ge_frombytes_vartime(&D_p3, &D) != 0) throw std::runtime_error("key derivation is invalid");
331 #if !defined(NDEBUG)
332  {
333  assert(sc_check(&r) == 0);
334  // check R == r*G or R == r*B
335  public_key dbg_R;
336  if (B)
337  {
338  ge_p2 dbg_R_p2;
339  ge_scalarmult(&dbg_R_p2, &r, &B_p3);
340  ge_tobytes(&dbg_R, &dbg_R_p2);
341  }
342  else
343  {
344  ge_p3 dbg_R_p3;
345  ge_scalarmult_base(&dbg_R_p3, &r);
346  ge_p3_tobytes(&dbg_R, &dbg_R_p3);
347  }
348  assert(R == dbg_R);
349  // check D == r*A
350  ge_p2 dbg_D_p2;
351  ge_scalarmult(&dbg_D_p2, &r, &A_p3);
352  public_key dbg_D;
353  ge_tobytes(&dbg_D, &dbg_D_p2);
354  assert(D == dbg_D);
355  }
356 #endif
357 
358  // pick random k
359  ec_scalar k;
360  random_scalar(k);
361 
362  s_comm_2 buf;
363  buf.msg = prefix_hash;
364  buf.D = D;
365 
366  if (B)
367  {
368  // compute X = k*B
369  ge_p2 X_p2;
370  ge_scalarmult(&X_p2, &k, &B_p3);
371  ge_tobytes(&buf.X, &X_p2);
372  }
373  else
374  {
375  // compute X = k*G
376  ge_p3 X_p3;
377  ge_scalarmult_base(&X_p3, &k);
378  ge_p3_tobytes(&buf.X, &X_p3);
379  }
380 
381  // compute Y = k*A
382  ge_p2 Y_p2;
383  ge_scalarmult(&Y_p2, &k, &A_p3);
384  ge_tobytes(&buf.Y, &Y_p2);
385 
386  // sig.c = Hs(Msg || D || X || Y)
387  hash_to_scalar(&buf, sizeof(buf), sig.c);
388 
389  // sig.r = k - sig.c*r
390  sc_mulsub(&sig.r, &sig.c, &unwrap(r), &k);
391  }
392 
393  bool crypto_ops::check_tx_proof(const hash &prefix_hash, const public_key &R, const public_key &A, const boost::optional<public_key> &B, const public_key &D, const signature &sig) {
394  // sanity check
395  ge_p3 R_p3;
396  ge_p3 A_p3;
397  ge_p3 B_p3;
398  ge_p3 D_p3;
399  if (ge_frombytes_vartime(&R_p3, &R) != 0) return false;
400  if (ge_frombytes_vartime(&A_p3, &A) != 0) return false;
401  if (B && ge_frombytes_vartime(&B_p3, &*B) != 0) return false;
402  if (ge_frombytes_vartime(&D_p3, &D) != 0) return false;
403  if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0) return false;
404 
405  // compute sig.c*R
406  ge_p3 cR_p3;
407  {
408  ge_p2 cR_p2;
409  ge_scalarmult(&cR_p2, &sig.c, &R_p3);
410  public_key cR;
411  ge_tobytes(&cR, &cR_p2);
412  if (ge_frombytes_vartime(&cR_p3, &cR) != 0) return false;
413  }
414 
415  ge_p1p1 X_p1p1;
416  if (B)
417  {
418  // compute X = sig.c*R + sig.r*B
419  ge_p2 rB_p2;
420  ge_scalarmult(&rB_p2, &sig.r, &B_p3);
421  public_key rB;
422  ge_tobytes(&rB, &rB_p2);
423  ge_p3 rB_p3;
424  if (ge_frombytes_vartime(&rB_p3, &rB) != 0) return false;
425  ge_cached rB_cached;
426  ge_p3_to_cached(&rB_cached, &rB_p3);
427  ge_add(&X_p1p1, &cR_p3, &rB_cached);
428  }
429  else
430  {
431  // compute X = sig.c*R + sig.r*G
432  ge_p3 rG_p3;
433  ge_scalarmult_base(&rG_p3, &sig.r);
434  ge_cached rG_cached;
435  ge_p3_to_cached(&rG_cached, &rG_p3);
436  ge_add(&X_p1p1, &cR_p3, &rG_cached);
437  }
438  ge_p2 X_p2;
439  ge_p1p1_to_p2(&X_p2, &X_p1p1);
440 
441  // compute sig.c*D
442  ge_p2 cD_p2;
443  ge_scalarmult(&cD_p2, &sig.c, &D_p3);
444 
445  // compute sig.r*A
446  ge_p2 rA_p2;
447  ge_scalarmult(&rA_p2, &sig.r, &A_p3);
448 
449  // compute Y = sig.c*D + sig.r*A
450  public_key cD;
451  public_key rA;
452  ge_tobytes(&cD, &cD_p2);
453  ge_tobytes(&rA, &rA_p2);
454  ge_p3 cD_p3;
455  ge_p3 rA_p3;
456  if (ge_frombytes_vartime(&cD_p3, &cD) != 0) return false;
457  if (ge_frombytes_vartime(&rA_p3, &rA) != 0) return false;
458  ge_cached rA_cached;
459  ge_p3_to_cached(&rA_cached, &rA_p3);
460  ge_p1p1 Y_p1p1;
461  ge_add(&Y_p1p1, &cD_p3, &rA_cached);
462  ge_p2 Y_p2;
463  ge_p1p1_to_p2(&Y_p2, &Y_p1p1);
464 
465  // compute c2 = Hs(Msg || D || X || Y)
466  s_comm_2 buf;
467  buf.msg = prefix_hash;
468  buf.D = D;
469  ge_tobytes(&buf.X, &X_p2);
470  ge_tobytes(&buf.Y, &Y_p2);
471  ec_scalar c2;
472  hash_to_scalar(&buf, sizeof(s_comm_2), c2);
473 
474  // test if c2 == sig.c
475  sc_sub(&c2, &c2, &sig.c);
476  return sc_isnonzero(&c2) == 0;
477  }
478 
479  void hash_to_ec(const public_key &key, ge_p3 &res) {
480  hash h;
481  ge_p2 point;
482  ge_p1p1 point2;
483  cn_fast_hash(std::addressof(key), sizeof(public_key), h);
484  ge_fromfe_frombytes_vartime(&point, reinterpret_cast<const unsigned char *>(&h));
485  ge_mul8(&point2, &point);
486  ge_p1p1_to_p3(&res, &point2);
487  }
488  void hash_to_ec(const hash& h, ge_p3 &res) {
489  ge_p2 point;
490  ge_p1p1 point2;
491  ge_fromfe_frombytes_vartime(&point, reinterpret_cast<const unsigned char *>(&h));
492  ge_mul8(&point2, &point);
493  ge_p1p1_to_p3(&res, &point2);
494  }
495 
496  void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
497  ge_p3 point;
498  ge_p2 point2;
499  assert(sc_check(&sec) == 0);
500  hash_to_ec(pub, point);
501  ge_scalarmult(&point2, &unwrap(sec), &point);
502  ge_tobytes(&image, &point2);
503  }
504 
505  size_t rs_comm_size(size_t pubs_count) {
506  return sizeof(rs_comm) + pubs_count * sizeof(ec_point_pair);
507  }
508 
509  void crypto_ops::generate_input_signature(const hash prefix_hash, const uint32_t input_index, const secret_key sec_view, const secret_key sec_spend, signature &sig){
510 
511  // add the two secret keys and reduce modulo l to get a new valid secret key for signing.
512  secret_key sec = addSecretKeys(sec_view, sec_spend);
513 
514  //corresponding public key for the combined secret key
515  public_key pub;
516  ge_p3 t;
517  assert(sc_check(&sec) == 0);
518  ge_scalarmult_base(&t, &sec);
519  ge_p3_tobytes(&pub, &t);
520 
521  //generate signature
522  ge_p3 tmp3;
523  ec_scalar k;
524  s_comm_3 buf;
525  buf.h = prefix_hash;
526  buf.i = input_index;
527  buf.key = pub;
528  try_again:
529  random_scalar(k);
530  if (((const uint32_t*)(&k))[7] == 0) // we don't want tiny numbers here
531  goto try_again;
532  ge_scalarmult_base(&tmp3, &k);
533  ge_p3_tobytes(&buf.comm, &tmp3);
534  hash_to_scalar(&buf, sizeof(s_comm_3), sig.c);
535  if (!sc_isnonzero((const unsigned char*)sig.c.data))
536  goto try_again;
537  sc_mulsub(&sig.r, &sig.c, &unwrap(sec), &k);
538  if (!sc_isnonzero((const unsigned char*)sig.r.data))
539  goto try_again;
540  }
541 
542  bool crypto_ops::verify_input_signature(const hash &prefix_hash,const uint32_t input_index, const public_key pub_view, const public_key pub_spend, signature sig)
543  {
544  public_key pub = addKeys(pub_view, pub_spend);
545 
546  ge_p2 tmp2;
547  ge_p3 tmp3;
548  ec_scalar c;
549  s_comm_3 buf;
550  assert(check_key(pub));
551  buf.h = prefix_hash;
552  buf.i = input_index;
553  buf.key = pub;
554  if (ge_frombytes_vartime(&tmp3, &pub) != 0) {
555  return false;
556  }
557  if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0 || !sc_isnonzero(&sig.c)) {
558  return false;
559  }
560  ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r);
561  ge_tobytes(&buf.comm, &tmp2);
562  static const ec_point infinity = {{ 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}};
563  if (memcmp(&buf.comm, &infinity, 32) == 0)
564  return false;
565  hash_to_scalar(&buf, sizeof(s_comm_3), c);
566  sc_sub(&c, &c, &sig.c);
567  return sc_isnonzero(&c) == 0;
568  }
569 
570  //for curve points: AB = A + B
571  public_key crypto_ops::addKeys(const public_key &A, const public_key &B) {
572  public_key AB;
573  ge_p3 B2, A2;
574  assert(ge_frombytes_vartime(&B2, &B) == 0 && ge_frombytes_vartime(&A2, &A) == 0);
575  ge_cached tmp2;
576  ge_p3_to_cached(&tmp2, &B2);
577  ge_p1p1 tmp3;
578  ge_add(&tmp3, &A2, &tmp2);
579  ge_p1p1_to_p3(&A2, &tmp3);
580  ge_p3_tobytes(&AB, &A2);
581 
582  return AB;
583  }
584 
585  secret_key crypto_ops::addSecretKeys(const secret_key& a, const secret_key& b){
586  assert(sc_check(&a) == 0);
587  assert(sc_check(&b) == 0);
588  secret_key d;
589  sc_add(&unwrap(d), &unwrap(a), &unwrap(b));
590  sc_reduce32(&d);
591  return d;
592  }
593 
594  void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image,
595  const public_key *const *pubs, size_t pubs_count,
596  const secret_key &sec, size_t sec_index,
597  signature *sig) {
598  size_t i;
599  ge_p3 image_unp;
600  ge_dsmp image_pre;
601  ec_scalar sum, k, h;
602  boost::shared_ptr<rs_comm> buf(reinterpret_cast<rs_comm *>(malloc(rs_comm_size(pubs_count))), free);
603  if (!buf)
604  local_abort("malloc failure");
605  assert(sec_index < pubs_count);
606 #if !defined(NDEBUG)
607  {
608  ge_p3 t;
609  public_key t2;
610  key_image t3;
611  assert(sc_check(&sec) == 0);
612  ge_scalarmult_base(&t, &sec);
613  ge_p3_tobytes(&t2, &t);
614  assert(*pubs[sec_index] == t2);
615  generate_key_image(*pubs[sec_index], sec, t3);
616  assert(image == t3);
617  for (i = 0; i < pubs_count; i++) {
618  assert(check_key(*pubs[i]));
619  }
620  }
621 #endif
622  if (ge_frombytes_vartime(&image_unp, &image) != 0) {
623  local_abort("invalid key image");
624  }
625  ge_dsm_precomp(image_pre, &image_unp);
626  sc_0(&sum);
627  buf->h = prefix_hash;
628  for (i = 0; i < pubs_count; i++) {
629  ge_p2 tmp2;
630  ge_p3 tmp3;
631  // Comments below use the same notation as the Cryptonote whitepaper.
632  if (i == sec_index) {
633  // Generate a random q_s
634  random_scalar(k);
635  // L_s = q_s*G
636  ge_scalarmult_base(&tmp3, &k);
637  // L_s in byte form
638  ge_p3_tobytes(&buf->ab[i].a, &tmp3);
639  // tmp3 now becomes H_p(P_s)
640  hash_to_ec(*pubs[i], tmp3);
641  // R_s = q_s * H_p(P_s)
642  ge_scalarmult(&tmp2, &k, &tmp3);
643  // R_s in byte form
644  ge_tobytes(&buf->ab[i].b, &tmp2);
645  } else {
646  // Generate our random scalars w_i & q_i
647  random_scalar(sig[i].c);
648  random_scalar(sig[i].r);
649  // Takes the byte form of P_i and converts to an ed25519 point.
650  if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
651  local_abort("invalid pubkey");
652  }
653  // Returns L_i = (q_i*G) + (w_i*P_i)
654  ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
655  // L_i in byte form
656  ge_tobytes(&buf->ab[i].a, &tmp2);
657  hash_to_ec(*pubs[i], tmp3);
658  // R_i = (q_i * H_p(P_i)) + w_i*I
659  ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
660  // R_i in byte form
661  ge_tobytes(&buf->ab[i].b, &tmp2);
662  // Add c_i to the running sum of c_i's
663  sc_add(&sum, &sum, &sig[i].c);
664  }
665  }
666  // Keccak1600 Hash (H_s) of the buffer of all L&R, which is then converted to a 32 byte integer modulo l.
667  hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h);
668  // c_s = c-sum(c_i) where i != s
669  sc_sub(&sig[sec_index].c, &h, &sum);
670  // Close the loop: r_s = q_s - c_s*x
671  // where x is the real output private key. This is the same x used to generate the key image
672  sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &unwrap(sec), &k);
673  }
674 
675  bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image,
676  const public_key *const *pubs, size_t pubs_count,
677  const signature *sig) {
678  size_t i;
679  ge_p3 image_unp;
680  ge_dsmp image_pre;
681  ec_scalar sum, h;
682  boost::shared_ptr<rs_comm> buf(reinterpret_cast<rs_comm *>(malloc(rs_comm_size(pubs_count))), free);
683  if (!buf)
684  return false;
685 
686 #if !defined(NDEBUG)
687  for (i = 0; i < pubs_count; i++) {
688  assert(check_key(*pubs[i]));
689  }
690 #endif
691  if (ge_frombytes_vartime(&image_unp, &image) != 0) {
692  return false;
693  }
694  ge_dsm_precomp(image_pre, &image_unp);
695  sc_0(&sum);
696  buf->h = prefix_hash;
697  for (i = 0; i < pubs_count; i++) {
698  ge_p2 tmp2;
699  ge_p3 tmp3;
700  if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) {
701  return false;
702  }
703  if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
704  return false;
705  }
706  ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
707  ge_tobytes(&buf->ab[i].a, &tmp2);
708  hash_to_ec(*pubs[i], tmp3);
709  ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
710  ge_tobytes(&buf->ab[i].b, &tmp2);
711  sc_add(&sum, &sum, &sig[i].c);
712  }
713  hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h);
714  sc_sub(&h, &h, &sum);
715  return sc_isnonzero(&h) == 0;
716  }
717 
718  std::string crypto_ops::sign_message(const std::string &message, const std::string &privateKey) {
719 
720  if(privateKey.size() != 32) {
721  return std::string("");
722  }
723 
724  ed25519_public_key pKey;
725  ed25519_publickey((unsigned char*)privateKey.data(), pKey);
726 
728  ed25519_sign((unsigned char*)message.data(), message.size(), (unsigned char*)privateKey.data(), pKey, signature);
729 
730  return std::string(reinterpret_cast<char const*>(signature), 64);
731  }
732 
733  bool crypto_ops::verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature) {
734 
735  if(publicKey.size() != 32 || signature.size() !=64) {
736  return false;
737  }
738  return ed25519_sign_open((unsigned char*)message.data(), message.size(), (unsigned char*)publicKey.data(), (unsigned char*)signature.data()) == 0;
739  }
740 
741  bool crypto_ops::verify_signature(const std::string &message, const std::vector<std::string> publicKey, const std::string &signature) {
742 
743  if(publicKey.empty() || signature.size() != 64) {
744  return false;
745  }
746 
747  bool result = false;
748  for(auto key : publicKey) {
749  if(ed25519_sign_open((unsigned char*)message.data(), message.size(), (unsigned char*)key.data(), (unsigned char*)signature.data()) == 0) {
750  result = true;
751  break;
752  }
753  }
754 
755  return result;
756  }
757 
758  std::vector<std::string> crypto_ops::create_ed25519_keypair() {
759  ed25519_secret_key sk, pk;
761 
762  ed25519_publickey(sk, pk);
763 
764  std::vector<std::string> result = {
765  boost::algorithm::hex(std::string(reinterpret_cast<char const*>(sk), 32)),
766  boost::algorithm::hex(std::string(reinterpret_cast<char const*>(pk), 32))
767  };
768 
769  return result;
770  }
771 }
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp)
void sc_0(unsigned char *)
ge_cached ge_dsmp[8]
Definition: crypto-ops.h:79
void sc_reduce32(unsigned char *)
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s)
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *)
void ge_mul8(ge_p1p1 *, const ge_p2 *)
int sc_check(const unsigned char *)
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *)
int sc_isnonzero(const unsigned char *)
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *)
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *)
std::string publicKey
std::string privateKey
std::string message("Message requiring signing")
void ED25519_FN() ed25519_randombytes_unsafe(void *p, size_t len)
int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS)
unsigned char ed25519_signature[64]
Definition: ed25519.h:10
unsigned char ed25519_secret_key[32]
Definition: ed25519.h:12
void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS)
unsigned char ed25519_public_key[32]
Definition: ed25519.h:11
void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk)
const char * res
Definition: hmac_keccak.cpp:41
const char * key
Definition: hmac_keccak.cpp:39
crypto namespace.
Definition: crypto.cpp:58
const crypto::public_key null_pkey
Definition: crypto.cpp:72
void cn_fast_hash(const void *data, std::size_t length, hash &hash)
Definition: hash.h:69
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:91
POD_CLASS ec_point
Definition: crypto.h:70
void hash_to_ec(const public_key &key, ge_p3 &res)
Definition: crypto.cpp:479
POD_CLASS signature
Definition: crypto.h:108
const crypto::secret_key null_skey
Definition: crypto.cpp:73
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
size_t rs_comm_size(size_t pubs_count)
Definition: crypto.cpp:505
POD_CLASS key_derivation
Definition: crypto.h:98
POD_CLASS public_key
Definition: crypto.h:76
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:110
POD_CLASS key_image
Definition: crypto.h:102
POD_CLASS ec_scalar
Definition: crypto.h:74
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:126
POD_CLASS hash
Definition: hash.h:50
void random_scalar(ec_scalar &res)
Definition: crypto.cpp:122
T & unwrap(mlocked< T > &src)
Definition: mlocker.h:80
::std::string string
Definition: gtest-port.h:1097
Matcher< T > A()
std::enable_if< std::is_integral< T >::value &&std::is_unsigned< T >::value, void >::type write_varint(OutputIt &&dest, T i)
writes a varint to a stream.
Definition: varint.h:70
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
#define ge_sub
Definition: ge.h:70
#define ge_scalarmult_base
Definition: ge.h:71
#define ge_p1p1_to_p2
Definition: ge.h:62
#define ge_p1p1_to_p3
Definition: ge.h:63
#define ge_p3_tobytes
Definition: ge.h:55
#define ge_p3_to_cached
Definition: ge.h:61
#define ge_add
Definition: ge.h:69
#define ge_tobytes
Definition: ge.h:54
t2
Definition: pow22523.h:103
t3
Definition: pow225521.h:103
const char * buf
Definition: slow_memmem.cpp:74
void generate_random_bytes_not_thread_safe(size_t n, void *result)
signed __int64 int64_t
Definition: stdint.h:135
unsigned int uint32_t
Definition: stdint.h:126
signed int int32_t
Definition: stdint.h:123
unsigned char uint8_t
Definition: stdint.h:124
unsigned __int64 uint64_t
Definition: stdint.h:136
ec_point D
Definition: crypto.cpp:255
ec_point X
Definition: crypto.cpp:256
ec_point Y
Definition: crypto.cpp:257
ec_point comm
Definition: crypto.cpp:264
uint32_t i
Definition: crypto.cpp:262
ec_point key
Definition: crypto.cpp:263
ec_point key
Definition: crypto.cpp:249
ec_point comm
Definition: crypto.cpp:250
provides the implementation of varint's