PRCYCoin  2.0.0.7rc1
P2P Digital Currency
borromean_impl.h
Go to the documentation of this file.
1 /**********************************************************************
2  * Copyright (c) 2014, 2015 Gregory Maxwell *
3  * Distributed under the MIT software license, see the accompanying *
4  * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
5  **********************************************************************/
6 
7 
8 #ifndef _SECP256K1_BORROMEAN_IMPL_H_
9 #define _SECP256K1_BORROMEAN_IMPL_H_
10 
11 #include "scalar.h"
12 #include "field.h"
13 #include "group.h"
14 #include "hash.h"
15 #include "eckey.h"
16 #include "ecmult.h"
17 #include "ecmult_gen.h"
18 #include "borromean.h"
19 
20 #include <limits.h>
21 #include <string.h>
22 
23 #ifdef WORDS_BIGENDIAN
24 #define BE32(x) (x)
25 #else
26 #define BE32(p) ((((p) & 0xFF) << 24) | (((p) & 0xFF00) << 8) | (((p) & 0xFF0000) >> 8) | (((p) & 0xFF000000) >> 24))
27 #endif
28 
29 SECP256K1_INLINE static void secp256k1_borromean_hash(unsigned char *hash, const unsigned char *m, size_t mlen, const unsigned char *e, size_t elen,
30  size_t ridx, size_t eidx) {
31  uint32_t ring;
32  uint32_t epos;
33  secp256k1_sha256 sha256_en;
34  secp256k1_sha256_initialize(&sha256_en);
35  ring = BE32((uint32_t)ridx);
36  epos = BE32((uint32_t)eidx);
37  secp256k1_sha256_write(&sha256_en, e, elen);
38  secp256k1_sha256_write(&sha256_en, m, mlen);
39  secp256k1_sha256_write(&sha256_en, (unsigned char*)&ring, 4);
40  secp256k1_sha256_write(&sha256_en, (unsigned char*)&epos, 4);
41  secp256k1_sha256_finalize(&sha256_en, hash);
42 }
43 
58 int secp256k1_borromean_verify(const secp256k1_ecmult_context* ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0,
59  const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen) {
60  secp256k1_gej rgej;
61  secp256k1_ge rge;
62  secp256k1_scalar ens;
63  secp256k1_sha256 sha256_e0;
64  unsigned char tmp[33];
65  size_t i;
66  size_t j;
67  size_t count;
68  size_t size;
69  int overflow;
70  VERIFY_CHECK(ecmult_ctx != NULL);
71  VERIFY_CHECK(e0 != NULL);
72  VERIFY_CHECK(s != NULL);
73  VERIFY_CHECK(pubs != NULL);
74  VERIFY_CHECK(rsizes != NULL);
75  VERIFY_CHECK(nrings > 0);
76  VERIFY_CHECK(m != NULL);
77  count = 0;
78  secp256k1_sha256_initialize(&sha256_e0);
79  for (i = 0; i < nrings; i++) {
80  VERIFY_CHECK(INT_MAX - count > rsizes[i]);
81  secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
82  secp256k1_scalar_set_b32(&ens, tmp, &overflow);
83  for (j = 0; j < rsizes[i]; j++) {
84  if (overflow || secp256k1_scalar_is_zero(&s[count]) || secp256k1_scalar_is_zero(&ens) || secp256k1_gej_is_infinity(&pubs[count])) {
85  return 0;
86  }
87  if (evalues) {
88  /*If requested, save the challenges for proof rewind.*/
89  evalues[count] = ens;
90  }
91  secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count], &ens, &s[count]);
92  if (secp256k1_gej_is_infinity(&rgej)) {
93  return 0;
94  }
95  /* OPT: loop can be hoisted and split to use batch inversion across all the rings; this would make it much faster. */
96  secp256k1_ge_set_gej_var(&rge, &rgej);
97  secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
98  if (j != rsizes[i] - 1) {
99  secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
100  secp256k1_scalar_set_b32(&ens, tmp, &overflow);
101  } else {
102  secp256k1_sha256_write(&sha256_e0, tmp, size);
103  }
104  count++;
105  }
106  }
107  secp256k1_sha256_write(&sha256_e0, m, mlen);
108  secp256k1_sha256_finalize(&sha256_e0, tmp);
109  return memcmp(e0, tmp, 32) == 0;
110 }
111 
113  unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
114  const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
115  secp256k1_gej rgej;
116  secp256k1_ge rge;
117  secp256k1_scalar ens;
118  secp256k1_sha256 sha256_e0;
119  unsigned char tmp[33];
120  size_t i;
121  size_t j;
122  size_t count;
123  size_t size;
124  int overflow;
125  VERIFY_CHECK(ecmult_ctx != NULL);
126  VERIFY_CHECK(ecmult_gen_ctx != NULL);
127  VERIFY_CHECK(e0 != NULL);
128  VERIFY_CHECK(s != NULL);
129  VERIFY_CHECK(pubs != NULL);
130  VERIFY_CHECK(k != NULL);
131  VERIFY_CHECK(sec != NULL);
132  VERIFY_CHECK(rsizes != NULL);
133  VERIFY_CHECK(secidx != NULL);
134  VERIFY_CHECK(nrings > 0);
135  VERIFY_CHECK(m != NULL);
136  secp256k1_sha256_initialize(&sha256_e0);
137  count = 0;
138  for (i = 0; i < nrings; i++) {
139  VERIFY_CHECK(INT_MAX - count > rsizes[i]);
140  secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
141  secp256k1_ge_set_gej(&rge, &rgej);
142  if (secp256k1_gej_is_infinity(&rgej)) {
143  return 0;
144  }
145  secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
146  for (j = secidx[i] + 1; j < rsizes[i]; j++) {
147  secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j);
148  secp256k1_scalar_set_b32(&ens, tmp, &overflow);
149  if (overflow || secp256k1_scalar_is_zero(&ens)) {
150  return 0;
151  }
156  secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]);
157  if (secp256k1_gej_is_infinity(&rgej)) {
158  return 0;
159  }
160  secp256k1_ge_set_gej_var(&rge, &rgej);
161  secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
162  }
163  secp256k1_sha256_write(&sha256_e0, tmp, size);
164  count += rsizes[i];
165  }
166  secp256k1_sha256_write(&sha256_e0, m, mlen);
167  secp256k1_sha256_finalize(&sha256_e0, e0);
168  count = 0;
169  for (i = 0; i < nrings; i++) {
170  VERIFY_CHECK(INT_MAX - count > rsizes[i]);
171  secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
172  secp256k1_scalar_set_b32(&ens, tmp, &overflow);
173  if (overflow || secp256k1_scalar_is_zero(&ens)) {
174  return 0;
175  }
176  for (j = 0; j < secidx[i]; j++) {
177  secp256k1_ecmult(ecmult_ctx, &rgej, &pubs[count + j], &ens, &s[count + j]);
178  if (secp256k1_gej_is_infinity(&rgej)) {
179  return 0;
180  }
181  secp256k1_ge_set_gej_var(&rge, &rgej);
182  secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
183  secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
184  secp256k1_scalar_set_b32(&ens, tmp, &overflow);
185  if (overflow || secp256k1_scalar_is_zero(&ens)) {
186  return 0;
187  }
188  }
189  secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
190  secp256k1_scalar_negate(&s[count + j], &s[count + j]);
191  secp256k1_scalar_add(&s[count + j], &s[count + j], &k[i]);
192  if (secp256k1_scalar_is_zero(&s[count + j])) {
193  return 0;
194  }
195  count += rsizes[i];
196  }
197  secp256k1_scalar_clear(&ens);
198  secp256k1_ge_clear(&rge);
199  secp256k1_gej_clear(&rgej);
200  memset(tmp, 0, 33);
201  return 1;
202 }
203 
204 #endif
VERIFY_CHECK
#define VERIFY_CHECK(cond)
Definition: util.h:61
BE32
#define BE32(p)
Definition: borromean_impl.h:26
secp256k1_sha256
Definition: hash.h:13
secp256k1_borromean_sign
int secp256k1_borromean_sign(const secp256k1_ecmult_context *ecmult_ctx, const secp256k1_ecmult_gen_context *ecmult_gen_ctx, unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec, const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen)
Definition: borromean_impl.h:112
secp256k1_scalar
A scalar modulo the group order of the secp256k1 curve.
Definition: scalar_4x64.h:13
secp256k1_gej
A group element of the secp256k1 curve, in jacobian coordinates.
Definition: group.h:24
secp256k1_ecmult_gen_context
Definition: ecmult_gen.h:13
borromean.h
secp256k1_borromean_verify
int secp256k1_borromean_verify(const secp256k1_ecmult_context *ecmult_ctx, secp256k1_scalar *evalues, const unsigned char *e0, const secp256k1_scalar *s, const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen)
"Borromean" ring signature.
Definition: borromean_impl.h:58
SECP256K1_INLINE
#define SECP256K1_INLINE
Definition: secp256k1.h:23
secp256k1_ecmult_context
Definition: ecmult.h:15
secp256k1_ge
A group element of the secp256k1 curve, in affine coordinates.
Definition: group.h:14