Skip to content

Commit 7ecde97

Browse files
committed
borromean: move k-value trickery into borromean_sign
Reduces stack usage of rangeproof_sign by 1056 bytes, is a bit safer as it doesn't require the caller of borromean_sign to know which indices are going to be overwritten, is a net-negative code diff, and reduces the amount of shared data between the borrom ean logic and its callers.
1 parent 75d2ca4 commit 7ecde97

File tree

6 files changed

+15
-41
lines changed

6 files changed

+15
-41
lines changed

src/modules/rangeproof/borromean.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
1818
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);
1919

2020
int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
21-
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
21+
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
2222
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);
2323

2424
#endif

src/modules/rangeproof/borromean_impl.h

+8-4
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
109109
}
110110

111111
int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
112-
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *k, const secp256k1_scalar *sec,
112+
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
113113
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
114114
secp256k1_gej rgej;
115115
secp256k1_ge rge;
@@ -125,7 +125,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
125125
VERIFY_CHECK(e0 != NULL);
126126
VERIFY_CHECK(s != NULL);
127127
VERIFY_CHECK(pubs != NULL);
128-
VERIFY_CHECK(k != NULL);
129128
VERIFY_CHECK(sec != NULL);
130129
VERIFY_CHECK(rsizes != NULL);
131130
VERIFY_CHECK(secidx != NULL);
@@ -135,7 +134,8 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
135134
count = 0;
136135
for (i = 0; i < nrings; i++) {
137136
VERIFY_CHECK(INT_MAX - count > rsizes[i]);
138-
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
137+
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
138+
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &s[count + secidx[i]]);
139139
secp256k1_ge_set_gej(&rge, &rgej);
140140
if (secp256k1_gej_is_infinity(&rgej)) {
141141
return 0;
@@ -165,6 +165,10 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
165165
secp256k1_sha256_finalize(&sha256_e0, e0);
166166
count = 0;
167167
for (i = 0; i < nrings; i++) {
168+
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
169+
secp256k1_scalar k = s[count + secidx[i]];
170+
secp256k1_scalar_clear(&s[count + secidx[i]]);
171+
168172
VERIFY_CHECK(INT_MAX - count > rsizes[i]);
169173
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
170174
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
@@ -186,7 +190,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
186190
}
187191
secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
188192
secp256k1_scalar_negate(&s[count + j], &s[count + j]);
189-
secp256k1_scalar_add(&s[count + j], &s[count + j], &k[i]);
193+
secp256k1_scalar_add(&s[count + j], &s[count + j], &k);
190194
if (secp256k1_scalar_is_zero(&s[count + j])) {
191195
return 0;
192196
}

src/modules/rangeproof/rangeproof_impl.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -398,7 +398,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
398398
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
399399
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
400400
secp256k1_scalar sec[32]; /* Blinding factors for the correct digits. */
401-
secp256k1_scalar k[32]; /* Nonces for our non-forged signatures. */
402401
secp256k1_sha256 sha256_m;
403402
unsigned char tmp[33];
404403
unsigned char *signs; /* Location of sign flags in the proof. */
@@ -453,11 +452,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
453452
if (!secp256k1_rangeproof_genrand_sign(sec, s, blind, message, msg_len, &header, v, &genrand_rng)) {
454453
return 0;
455454
}
456-
for (i = 0; i < header.n_rings; i++) {
457-
/* Sign will overwrite the non-forged signature, move that random value into the nonce. */
458-
k[i] = s[i * 4 + secidx[i]];
459-
secp256k1_scalar_clear(&s[i * 4 + secidx[i]]);
460-
}
461455
signs = &proof[len];
462456
/* We need one sign bit for each blinded value we send. */
463457
for (i = 0; i < (header.n_rings + 6) >> 3; i++) {
@@ -493,7 +487,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
493487
secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len);
494488
}
495489
secp256k1_sha256_finalize(&sha256_m, tmp);
496-
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
490+
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
497491
return 0;
498492
}
499493
len += 32;

src/modules/rangeproof/tests_impl.h

+1-6
Original file line numberDiff line numberDiff line change
@@ -316,7 +316,6 @@ static void test_borromean(void) {
316316
unsigned char e0[32];
317317
secp256k1_scalar s[64];
318318
secp256k1_gej pubs[64];
319-
secp256k1_scalar k[8];
320319
secp256k1_scalar sec[8];
321320
secp256k1_ge ge;
322321
secp256k1_scalar one;
@@ -338,13 +337,9 @@ static void test_borromean(void) {
338337
rsizes[i] = 1 + (secp256k1_testrand32()&7);
339338
secidx[i] = secp256k1_testrand32() % rsizes[i];
340339
random_scalar_order(&sec[i]);
341-
random_scalar_order(&k[i]);
342340
if(secp256k1_testrand32()&7) {
343341
sec[i] = one;
344342
}
345-
if(secp256k1_testrand32()&7) {
346-
k[i] = one;
347-
}
348343
for (j = 0; j < rsizes[i]; j++) {
349344
random_scalar_order(&s[c + j]);
350345
if(secp256k1_testrand32()&7) {
@@ -359,7 +354,7 @@ static void test_borromean(void) {
359354
}
360355
c += rsizes[i];
361356
}
362-
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32));
357+
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, sec, rsizes, secidx, nrings, m, 32));
363358
CHECK(secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
364359
i = secp256k1_testrand32() % c;
365360
secp256k1_scalar_negate(&s[i],&s[i]);

src/modules/surjection/main_impl.h

+1-7
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,6 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1
275275
int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_surjectionproof* proof, const secp256k1_generator* ephemeral_input_tags, size_t n_ephemeral_input_tags, const secp256k1_generator* ephemeral_output_tag, size_t input_index, const unsigned char *input_blinding_key, const unsigned char *output_blinding_key) {
276276
secp256k1_scalar blinding_key;
277277
secp256k1_scalar tmps;
278-
secp256k1_scalar nonce;
279278
int overflow = 0;
280279
size_t rsizes[1]; /* array needed for borromean sig API */
281280
size_t indices[1]; /* array needed for borromean sig API */
@@ -333,12 +332,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
333332
if (secp256k1_surjection_genrand(borromean_s, n_used_pubkeys, &blinding_key) == 0) {
334333
return 0;
335334
}
336-
/* Borromean sign will overwrite one of the s values we just generated, so use
337-
* it as a nonce instead. This avoids extra random generation and also is an
338-
* homage to the rangeproof code which does this very cleverly to encode messages. */
339-
nonce = borromean_s[ring_input_index];
340-
secp256k1_scalar_clear(&borromean_s[ring_input_index]);
341-
if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
335+
if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
342336
return 0;
343337
}
344338
for (i = 0; i < n_used_pubkeys; i++) {

src/modules/whitelist/main_impl.h

+3-16
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_signature *sig, const secp256k1_pubkey *online_pubkeys, const secp256k1_pubkey *offline_pubkeys, const size_t n_keys, const secp256k1_pubkey *sub_pubkey, const unsigned char *online_seckey, const unsigned char *summed_seckey, const size_t index, secp256k1_nonce_function noncefp, const void *noncedata) {
1616
secp256k1_gej pubs[MAX_KEYS];
1717
secp256k1_scalar s[MAX_KEYS];
18-
secp256k1_scalar sec, non;
18+
secp256k1_scalar sec;
1919
unsigned char msg32[32];
2020
int ret;
2121

@@ -51,19 +51,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
5151
secp256k1_scalar_get_b32(seckey32, &sec);
5252
while (1) {
5353
size_t i;
54-
unsigned char nonce32[32];
55-
int done;
56-
ret = noncefp(nonce32, msg32, seckey32, NULL, (void*)noncedata, count);
57-
if (!ret) {
58-
break;
59-
}
60-
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
61-
memset(nonce32, 0, 32);
62-
if (overflow || secp256k1_scalar_is_zero(&non)) {
63-
count++;
64-
continue;
65-
}
66-
done = 1;
54+
int done = 1;
6755
for (i = 0; i < n_keys; i++) {
6856
msg32[0] ^= i + 1;
6957
msg32[1] ^= (i + 1) / 0x100;
@@ -89,12 +77,11 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
8977
/* Actually sign */
9078
if (ret) {
9179
sig->n_keys = n_keys;
92-
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32);
80+
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &sec, &n_keys, &index, 1, msg32, 32);
9381
/* Signing will change s[index], so update in the sig structure */
9482
secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]);
9583
}
9684

97-
secp256k1_scalar_clear(&non);
9885
secp256k1_scalar_clear(&sec);
9986
return ret;
10087
}

0 commit comments

Comments
 (0)