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;
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 
497  ge_p2 point;
498  ge_fromfe_frombytes_vartime(&point, reinterpret_cast<const unsigned char *>(&h));
499  ge_tobytes(crypto::operator&(res), &point);
500  }
501 
502  void crypto_ops::generate_key_image(const public_key &pub, const secret_key &sec, key_image &image) {
503  ge_p3 point;
504  ge_p2 point2;
505  assert(sc_check(&sec) == 0);
506  hash_to_ec(pub, point);
507  ge_scalarmult(&point2, &unwrap(sec), &point);
508  ge_tobytes(&image, &point2);
509  }
510 
511  size_t rs_comm_size(size_t pubs_count) {
512  return sizeof(rs_comm) + pubs_count * sizeof(ec_point_pair);
513  }
514 
515  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){
516 
517  // add the two secret keys and reduce modulo l to get a new valid secret key for signing.
518  secret_key sec = addSecretKeys(sec_view, sec_spend);
519 
520  //corresponding public key for the combined secret key
521  public_key pub;
522  ge_p3 t;
523  assert(sc_check(&sec) == 0);
524  ge_scalarmult_base(&t, &sec);
525  ge_p3_tobytes(&pub, &t);
526 
527  //generate signature
528  ge_p3 tmp3;
529  ec_scalar k;
530  s_comm_3 buf;
531  buf.h = prefix_hash;
532  buf.i = input_index;
533  buf.key = pub;
534  try_again:
535  random_scalar(k);
536  if (((const uint32_t*)(&k))[7] == 0) // we don't want tiny numbers here
537  goto try_again;
538  ge_scalarmult_base(&tmp3, &k);
539  ge_p3_tobytes(&buf.comm, &tmp3);
540  hash_to_scalar(&buf, sizeof(s_comm_3), sig.c);
541  if (!sc_isnonzero((const unsigned char*)sig.c.data))
542  goto try_again;
543  sc_mulsub(&sig.r, &sig.c, &unwrap(sec), &k);
544  if (!sc_isnonzero((const unsigned char*)sig.r.data))
545  goto try_again;
546  }
547 
548  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)
549  {
550  public_key pub = addKeys(pub_view, pub_spend);
551 
552  ge_p2 tmp2;
553  ge_p3 tmp3;
554  ec_scalar c;
555  s_comm_3 buf;
556  assert(check_key(pub));
557  buf.h = prefix_hash;
558  buf.i = input_index;
559  buf.key = pub;
560  if (ge_frombytes_vartime(&tmp3, &pub) != 0) {
561  return false;
562  }
563  if (sc_check(&sig.c) != 0 || sc_check(&sig.r) != 0 || !sc_isnonzero(&sig.c)) {
564  return false;
565  }
566  ge_double_scalarmult_base_vartime(&tmp2, &sig.c, &tmp3, &sig.r);
567  ge_tobytes(&buf.comm, &tmp2);
568  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}};
569  if (memcmp(&buf.comm, &infinity, 32) == 0)
570  return false;
571  hash_to_scalar(&buf, sizeof(s_comm_3), c);
572  sc_sub(&c, &c, &sig.c);
573  return sc_isnonzero(&c) == 0;
574  }
575 
576  //for curve points: AB = A + B
577  public_key crypto_ops::addKeys(const public_key &A, const public_key &B) {
578  public_key AB;
579  ge_p3 B2, A2;
580 
581  if (ge_frombytes_vartime(&B2, &B) != 0 || ge_frombytes_vartime(&A2, &A) != 0) {
582  local_abort("addKeys: issue converting a public key to a curve point");
583  }
584 
585  ge_cached tmp2;
586  ge_p3_to_cached(&tmp2, &B2);
587  ge_p1p1 tmp3;
588  ge_add(&tmp3, &A2, &tmp2);
589  ge_p1p1_to_p3(&A2, &tmp3);
590  ge_p3_tobytes(&AB, &A2);
591 
592  return AB;
593  }
594 
595  secret_key crypto_ops::addSecretKeys(const secret_key& a, const secret_key& b){
596  assert(sc_check(&a) == 0);
597  assert(sc_check(&b) == 0);
598  secret_key d;
599  sc_add(&unwrap(d), &unwrap(a), &unwrap(b));
600  sc_reduce32(&d);
601  return d;
602  }
603 
604  void crypto_ops::generate_ring_signature(const hash &prefix_hash, const key_image &image,
605  const public_key *const *pubs, size_t pubs_count,
606  const secret_key &sec, size_t sec_index,
607  signature *sig) {
608  size_t i;
609  ge_p3 image_unp;
610  ge_dsmp image_pre;
611  ec_scalar sum, k, h;
612  boost::shared_ptr<rs_comm> buf(reinterpret_cast<rs_comm *>(malloc(rs_comm_size(pubs_count))), free);
613  if (!buf)
614  local_abort("malloc failure");
615  assert(sec_index < pubs_count);
616 #if !defined(NDEBUG)
617  {
618  ge_p3 t;
619  public_key t2;
620  key_image t3;
621  assert(sc_check(&sec) == 0);
622  ge_scalarmult_base(&t, &sec);
623  ge_p3_tobytes(&t2, &t);
624  assert(*pubs[sec_index] == t2);
625  generate_key_image(*pubs[sec_index], sec, t3);
626  assert(image == t3);
627  for (i = 0; i < pubs_count; i++) {
628  assert(check_key(*pubs[i]));
629  }
630  }
631 #endif
632  if (ge_frombytes_vartime(&image_unp, &image) != 0) {
633  local_abort("invalid key image");
634  }
635  ge_dsm_precomp(image_pre, &image_unp);
636  sc_0(&sum);
637  buf->h = prefix_hash;
638  for (i = 0; i < pubs_count; i++) {
639  ge_p2 tmp2;
640  ge_p3 tmp3;
641  // Comments below use the same notation as the Cryptonote whitepaper.
642  if (i == sec_index) {
643  // Generate a random q_s
644  random_scalar(k);
645  // L_s = q_s*G
646  ge_scalarmult_base(&tmp3, &k);
647  // L_s in byte form
648  ge_p3_tobytes(&buf->ab[i].a, &tmp3);
649  // tmp3 now becomes H_p(P_s)
650  hash_to_ec(*pubs[i], tmp3);
651  // R_s = q_s * H_p(P_s)
652  ge_scalarmult(&tmp2, &k, &tmp3);
653  // R_s in byte form
654  ge_tobytes(&buf->ab[i].b, &tmp2);
655  } else {
656  // Generate our random scalars w_i & q_i
657  random_scalar(sig[i].c);
658  random_scalar(sig[i].r);
659  // Takes the byte form of P_i and converts to an ed25519 point.
660  if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
661  local_abort("invalid pubkey");
662  }
663  // Returns L_i = (q_i*G) + (w_i*P_i)
664  ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
665  // L_i in byte form
666  ge_tobytes(&buf->ab[i].a, &tmp2);
667  hash_to_ec(*pubs[i], tmp3);
668  // R_i = (q_i * H_p(P_i)) + w_i*I
669  ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
670  // R_i in byte form
671  ge_tobytes(&buf->ab[i].b, &tmp2);
672  // Add c_i to the running sum of c_i's
673  sc_add(&sum, &sum, &sig[i].c);
674  }
675  }
676  // Keccak1600 Hash (H_s) of the buffer of all L&R, which is then converted to a 32 byte integer modulo l.
677  hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h);
678  // c_s = c-sum(c_i) where i != s
679  sc_sub(&sig[sec_index].c, &h, &sum);
680  // Close the loop: r_s = q_s - c_s*x
681  // where x is the real output private key. This is the same x used to generate the key image
682  sc_mulsub(&sig[sec_index].r, &sig[sec_index].c, &unwrap(sec), &k);
683  }
684 
685  bool crypto_ops::check_ring_signature(const hash &prefix_hash, const key_image &image,
686  const public_key *const *pubs, size_t pubs_count,
687  const signature *sig) {
688  size_t i;
689  ge_p3 image_unp;
690  ge_dsmp image_pre;
691  ec_scalar sum, h;
692  boost::shared_ptr<rs_comm> buf(reinterpret_cast<rs_comm *>(malloc(rs_comm_size(pubs_count))), free);
693  if (!buf)
694  return false;
695 
696 #if !defined(NDEBUG)
697  for (i = 0; i < pubs_count; i++) {
698  assert(check_key(*pubs[i]));
699  }
700 #endif
701  if (ge_frombytes_vartime(&image_unp, &image) != 0) {
702  return false;
703  }
704  ge_dsm_precomp(image_pre, &image_unp);
705  sc_0(&sum);
706  buf->h = prefix_hash;
707  for (i = 0; i < pubs_count; i++) {
708  ge_p2 tmp2;
709  ge_p3 tmp3;
710  if (sc_check(&sig[i].c) != 0 || sc_check(&sig[i].r) != 0) {
711  return false;
712  }
713  if (ge_frombytes_vartime(&tmp3, &*pubs[i]) != 0) {
714  return false;
715  }
716  ge_double_scalarmult_base_vartime(&tmp2, &sig[i].c, &tmp3, &sig[i].r);
717  ge_tobytes(&buf->ab[i].a, &tmp2);
718  hash_to_ec(*pubs[i], tmp3);
719  ge_double_scalarmult_precomp_vartime(&tmp2, &sig[i].r, &tmp3, &sig[i].c, image_pre);
720  ge_tobytes(&buf->ab[i].b, &tmp2);
721  sc_add(&sum, &sum, &sig[i].c);
722  }
723  hash_to_scalar(buf.get(), rs_comm_size(pubs_count), h);
724  sc_sub(&h, &h, &sum);
725  return sc_isnonzero(&h) == 0;
726  }
727 
728  std::string crypto_ops::sign_message(const std::string &message, const std::string &privateKey) {
729 
730  if(privateKey.size() != 32) {
731  return std::string("");
732  }
733 
734  ed25519_public_key pKey;
735  ed25519_publickey((unsigned char*)privateKey.data(), pKey);
736 
738  ed25519_sign((unsigned char*)message.data(), message.size(), (unsigned char*)privateKey.data(), pKey, signature);
739 
740  return std::string(reinterpret_cast<char const*>(signature), 64);
741  }
742 
743  bool crypto_ops::verify_signature(const std::string &message, const std::string &publicKey, const std::string &signature) {
744 
745  if(publicKey.size() != 32 || signature.size() !=64) {
746  return false;
747  }
748  return ed25519_sign_open((unsigned char*)message.data(), message.size(), (unsigned char*)publicKey.data(), (unsigned char*)signature.data()) == 0;
749  }
750 
751  bool crypto_ops::verify_signature(const std::string &message, const std::vector<std::string> publicKey, const std::string &signature) {
752 
753  if(publicKey.empty() || signature.size() != 64) {
754  return false;
755  }
756 
757  bool result = false;
758  for(auto key : publicKey) {
759  if(ed25519_sign_open((unsigned char*)message.data(), message.size(), (unsigned char*)key.data(), (unsigned char*)signature.data()) == 0) {
760  result = true;
761  break;
762  }
763  }
764 
765  return result;
766  }
767 
768  std::vector<std::string> crypto_ops::create_ed25519_keypair() {
769  ed25519_secret_key sk, pk;
771 
772  ed25519_publickey(sk, pk);
773 
774  std::vector<std::string> result = {
775  boost::algorithm::hex(std::string(reinterpret_cast<char const*>(sk), 32)),
776  boost::algorithm::hex(std::string(reinterpret_cast<char const*>(pk), 32))
777  };
778 
779  return result;
780  }
781 }
const char * res
Definition: hmac_keccak.cpp:41
POD_CLASS ec_point
Definition: crypto.h:70
std::string publicKey
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp)
void ed25519_sign(const unsigned char *m, size_t mlen, const ed25519_secret_key sk, const ed25519_public_key pk, ed25519_signature RS)
uint32_t i
Definition: crypto.cpp:262
::std::string string
Definition: gtest-port.h:1097
POD_CLASS key_derivation
Definition: crypto.h:98
ec_point key
Definition: crypto.cpp:263
void sc_0(unsigned char *)
provides the implementation of varint&#39;s
const char * key
Definition: hmac_keccak.cpp:39
ec_point comm
Definition: crypto.cpp:250
crypto namespace.
Definition: crypto.cpp:58
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition: crypto.h:82
ec_point Y
Definition: crypto.cpp:257
void ge_p3_tobytes(unsigned char *, const ge_p3 *)
unsigned char uint8_t
Definition: stdint.h:124
void hash_to_ec(const public_key &key, ge_p3 &res)
Definition: crypto.cpp:479
void hash_to_point(const crypto::hash &h, crypto::ec_point &res)
Definition: crypto.cpp:496
unsigned char ed25519_public_key[32]
Definition: ed25519.h:11
void generate_random_bytes_not_thread_safe(size_t n, void *result)
void random32_unbiased(unsigned char *bytes)
Definition: crypto.cpp:110
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *)
void ed25519_publickey(const ed25519_secret_key sk, ed25519_public_key pk)
ec_point D
Definition: crypto.cpp:255
Archiver & operator &(Archiver &ar, Student &s)
std::string privateKey
size_t rs_comm_size(size_t pubs_count)
Definition: crypto.cpp:511
const crypto::secret_key null_skey
Definition: crypto.cpp:73
int sc_check(const unsigned char *)
void generate_random_bytes_thread_safe(size_t N, uint8_t *bytes)
Definition: crypto.cpp:91
void ge_p3_to_cached(ge_cached *, const ge_p3 *)
ec_point X
Definition: crypto.cpp:256
unsigned int uint32_t
Definition: stdint.h:126
const crypto::public_key null_pkey
Definition: crypto.cpp:72
POD_CLASS ec_scalar
Definition: crypto.h:74
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *)
t3
Definition: pow225521.h:103
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
unsigned __int64 uint64_t
Definition: stdint.h:136
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s)
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *)
void ge_mul8(ge_p1p1 *, const ge_p2 *)
void ge_tobytes(unsigned char *, const ge_p2 *)
POD_CLASS public_key
Definition: crypto.h:76
const char * buf
Definition: slow_memmem.cpp:74
void cn_fast_hash(const void *data, size_t length, char *hash)
std::string message("Message requiring signing")
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *)
void ED25519_FN() ed25519_randombytes_unsafe(void *p, size_t len)
const GenericPointer< typename T::ValueType > T2 T::AllocatorType & a
Definition: pointer.h:1124
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q)
t2
Definition: pow22523.h:103
void ge_p1p1_to_p3(ge_p3 *, const ge_p1p1 *)
void ge_add(ge_p1p1 *, const ge_p3 *, const ge_cached *)
POD_CLASS signature
Definition: crypto.h:108
void ge_p1p1_to_p2(ge_p2 *, const ge_p1p1 *)
POD_CLASS key_image
Definition: crypto.h:102
Matcher< T > A()
signed __int64 int64_t
Definition: stdint.h:135
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
void hash_to_scalar(const void *data, size_t length, ec_scalar &res)
Definition: crypto.cpp:126
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
T & unwrap(mlocked< T > &src)
Definition: mlocker.h:80
void ge_scalarmult_base(ge_p3 *, const unsigned char *)
ge_cached ge_dsmp[8]
Definition: crypto.cpp:80
POD_CLASS hash
Definition: hash.h:50
signed int int32_t
Definition: stdint.h:123
ec_point key
Definition: crypto.cpp:249
unsigned char ed25519_signature[64]
Definition: ed25519.h:10
unsigned char ed25519_secret_key[32]
Definition: ed25519.h:12
int ed25519_sign_open(const unsigned char *m, size_t mlen, const ed25519_public_key pk, const ed25519_signature RS)
ec_point comm
Definition: crypto.cpp:264
int sc_isnonzero(const unsigned char *)
void sc_reduce32(unsigned char *)
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
void random_scalar(ec_scalar &res)
Definition: crypto.cpp:122