Skip to content

Commit f25f555

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 376dfd2 commit f25f555

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
@@ -406,7 +406,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
406406
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
407407
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
408408
secp256k1_scalar sec[32]; /* Blinding factors for the correct digits. */
409-
secp256k1_scalar k[32]; /* Nonces for our non-forged signatures. */
410409
secp256k1_sha256 sha256_m;
411410
unsigned char tmp[33];
412411
unsigned char *signs; /* Location of sign flags in the proof. */
@@ -461,11 +460,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
461460
if (!secp256k1_rangeproof_genrand_sign(sec, s, blind, message, msg_len, &header, v, &genrand_rng)) {
462461
return 0;
463462
}
464-
for (i = 0; i < header.n_rings; i++) {
465-
/* Sign will overwrite the non-forged signature, move that random value into the nonce. */
466-
k[i] = s[i * 4 + secidx[i]];
467-
secp256k1_scalar_clear(&s[i * 4 + secidx[i]]);
468-
}
469463
signs = &proof[len];
470464
/* We need one sign bit for each blinded value we send. */
471465
for (i = 0; i < (header.n_rings + 6) >> 3; i++) {
@@ -501,7 +495,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
501495
secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len);
502496
}
503497
secp256k1_sha256_finalize(&sha256_m, tmp);
504-
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
498+
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
505499
return 0;
506500
}
507501
len += 32;

src/modules/rangeproof/tests_impl.h

+1-6
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@ static void test_borromean(void) {
322322
unsigned char e0[32];
323323
secp256k1_scalar s[64];
324324
secp256k1_gej pubs[64];
325-
secp256k1_scalar k[8];
326325
secp256k1_scalar sec[8];
327326
secp256k1_ge ge;
328327
secp256k1_scalar one;
@@ -344,13 +343,9 @@ static void test_borromean(void) {
344343
rsizes[i] = 1 + (secp256k1_testrand32()&7);
345344
secidx[i] = secp256k1_testrand32() % rsizes[i];
346345
random_scalar_order(&sec[i]);
347-
random_scalar_order(&k[i]);
348346
if(secp256k1_testrand32()&7) {
349347
sec[i] = one;
350348
}
351-
if(secp256k1_testrand32()&7) {
352-
k[i] = one;
353-
}
354349
for (j = 0; j < rsizes[i]; j++) {
355350
random_scalar_order(&s[c + j]);
356351
if(secp256k1_testrand32()&7) {
@@ -365,7 +360,7 @@ static void test_borromean(void) {
365360
}
366361
c += rsizes[i];
367362
}
368-
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32));
363+
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, sec, rsizes, secidx, nrings, m, 32));
369364
CHECK(secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
370365
i = secp256k1_testrand32() % c;
371366
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) {
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

@@ -47,19 +47,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
4747
secp256k1_scalar_get_b32(seckey32, &sec);
4848
while (1) {
4949
size_t i;
50-
unsigned char nonce32[32];
51-
int done;
52-
ret = secp256k1_nonce_function_default(nonce32, msg32, seckey32, NULL, NULL, count);
53-
if (!ret) {
54-
break;
55-
}
56-
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
57-
memset(nonce32, 0, 32);
58-
if (overflow || secp256k1_scalar_is_zero(&non)) {
59-
count++;
60-
continue;
61-
}
62-
done = 1;
50+
int done = 1;
6351
for (i = 0; i < n_keys; i++) {
6452
msg32[0] ^= i + 1;
6553
msg32[1] ^= (i + 1) / 0x100;
@@ -85,12 +73,11 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
8573
/* Actually sign */
8674
if (ret) {
8775
sig->n_keys = n_keys;
88-
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32);
76+
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &sec, &n_keys, &index, 1, msg32, 32);
8977
/* Signing will change s[index], so update in the sig structure */
9078
secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]);
9179
}
9280

93-
secp256k1_scalar_clear(&non);
9481
secp256k1_scalar_clear(&sec);
9582
return ret;
9683
}

0 commit comments

Comments
 (0)