Electroneum
Loading...
Searching...
No Matches
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>
43#include "crypto.h"
44#include "hash.h"
45
46namespace {
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 }
58namespace 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
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 }
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 }
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)
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);
121 /* generate a random 32-byte (256-bit) integer and copy it to res */
123 random32_unbiased((unsigned char*)res.data);
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));
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
149 sec = rng;
150 sc_reduce32(&unwrap(sec)); // reduce in case second round of keys (sendkeys)
152 ge_scalarmult_base(&point, &unwrap(sec));
153 ge_p3_tobytes(&pub, &point);
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;
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;
195 tools::write_varint(end, output_index);
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
252
259
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;
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
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;
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
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}
friend std::vector< std::string > create_ed25519_keypair()
Definition crypto.h:388
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
const char * key
crypto namespace.
Definition crypto.cpp:58
const crypto::public_key null_pkey
Definition crypto.cpp:72
void ge_scalarmult(ge_p2 *, const unsigned char *, const ge_p3 *)
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
int ge_frombytes_vartime(ge_p3 *, const unsigned char *)
POD_CLASS signature
Definition crypto.h:108
void ge_dsm_precomp(ge_dsmp r, const ge_p3 *s)
const crypto::secret_key null_skey
Definition crypto.cpp:73
void sc_reduce32(unsigned char *)
epee::mlocked< tools::scrubbed< ec_scalar > > secret_key
Definition crypto.h:82
void ge_double_scalarmult_precomp_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *, const ge_dsmp)
void ge_double_scalarmult_base_vartime(ge_p2 *, const unsigned char *, const ge_p3 *, const unsigned char *)
ge_cached ge_dsmp[8]
Definition crypto.cpp:80
unsigned char uint8_t
Definition hash.h:125
void cn_fast_hash(const void *data, size_t length, char *hash)
int sc_check(const unsigned char *)
int sc_isnonzero(const unsigned char *)
void generate_random_bytes_not_thread_safe(size_t n, void *result)
size_t rs_comm_size(size_t pubs_count)
Definition crypto.cpp:511
POD_CLASS key_derivation
Definition crypto.h:101
POD_CLASS public_key
Definition crypto.h:79
void random32_unbiased(unsigned char *bytes)
Definition crypto.cpp:110
void hash_to_point(const crypto::hash &h, crypto::ec_point &res)
Definition crypto.cpp:496
POD_CLASS key_image
Definition crypto.h:105
unsigned int uint32_t
Definition hash.h:127
POD_CLASS ec_scalar
Definition crypto.h:74
void sc_add(unsigned char *, const unsigned char *, const unsigned char *)
void ge_fromfe_frombytes_vartime(ge_p2 *, const unsigned char *)
void ge_mul8(ge_p1p1 *, const ge_p2 *)
void sc_0(unsigned char *)
void sc_mulsub(unsigned char *, const unsigned char *, const unsigned char *, const unsigned char *)
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
void sc_sub(unsigned char *, const unsigned char *, const unsigned char *)
T & unwrap(mlocked< T > &src)
Definition mlocker.h:80
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
unsigned int uint32_t
Definition stdint.h:126
ec_point comm
Definition crypto.cpp:264
ec_point key
Definition crypto.cpp:249
ec_point comm
Definition crypto.cpp:250
provides the implementation of varint's