Skip to content

Commit

Permalink
borromean: move k-value trickery into borromean_sign
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
apoelstra committed Mar 6, 2022
1 parent 376dfd2 commit f25f555
Show file tree
Hide file tree
Showing 6 changed files with 15 additions and 41 deletions.
2 changes: 1 addition & 1 deletion src/modules/rangeproof/borromean.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
const secp256k1_gej *pubs, const size_t *rsizes, size_t nrings, const unsigned char *m, size_t mlen);

int secp256k1_borromean_sign(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,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen);

#endif
12 changes: 8 additions & 4 deletions src/modules/rangeproof/borromean_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
}

int secp256k1_borromean_sign(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,
unsigned char *e0, secp256k1_scalar *s, const secp256k1_gej *pubs, const secp256k1_scalar *sec,
const size_t *rsizes, const size_t *secidx, size_t nrings, const unsigned char *m, size_t mlen) {
secp256k1_gej rgej;
secp256k1_ge rge;
Expand All @@ -125,7 +125,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL);
VERIFY_CHECK(pubs != NULL);
VERIFY_CHECK(k != NULL);
VERIFY_CHECK(sec != NULL);
VERIFY_CHECK(rsizes != NULL);
VERIFY_CHECK(secidx != NULL);
Expand All @@ -135,7 +134,8 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
count = 0;
for (i = 0; i < nrings; i++) {
VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &k[i]);
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_ecmult_gen(ecmult_gen_ctx, &rgej, &s[count + secidx[i]]);
secp256k1_ge_set_gej(&rge, &rgej);
if (secp256k1_gej_is_infinity(&rgej)) {
return 0;
Expand Down Expand Up @@ -165,6 +165,10 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
secp256k1_sha256_finalize(&sha256_e0, e0);
count = 0;
for (i = 0; i < nrings; i++) {
/* We have been provided an s value that we will just overwrite, so use it as a nonce */
secp256k1_scalar k = s[count + secidx[i]];
secp256k1_scalar_clear(&s[count + secidx[i]]);

VERIFY_CHECK(INT_MAX - count > rsizes[i]);
secp256k1_borromean_hash(tmp, m, mlen, e0, 32, i, 0);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
Expand All @@ -186,7 +190,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
}
secp256k1_scalar_mul(&s[count + j], &ens, &sec[i]);
secp256k1_scalar_negate(&s[count + j], &s[count + j]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k[i]);
secp256k1_scalar_add(&s[count + j], &s[count + j], &k);
if (secp256k1_scalar_is_zero(&s[count + j])) {
return 0;
}
Expand Down
8 changes: 1 addition & 7 deletions src/modules/rangeproof/rangeproof_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -406,7 +406,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
secp256k1_gej pubs[128]; /* Candidate digits for our proof, most inferred. */
secp256k1_scalar s[128]; /* Signatures in our proof, most forged. */
secp256k1_scalar sec[32]; /* Blinding factors for the correct digits. */
secp256k1_scalar k[32]; /* Nonces for our non-forged signatures. */
secp256k1_sha256 sha256_m;
unsigned char tmp[33];
unsigned char *signs; /* Location of sign flags in the proof. */
Expand Down Expand Up @@ -461,11 +460,6 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
if (!secp256k1_rangeproof_genrand_sign(sec, s, blind, message, msg_len, &header, v, &genrand_rng)) {
return 0;
}
for (i = 0; i < header.n_rings; i++) {
/* Sign will overwrite the non-forged signature, move that random value into the nonce. */
k[i] = s[i * 4 + secidx[i]];
secp256k1_scalar_clear(&s[i * 4 + secidx[i]]);
}
signs = &proof[len];
/* We need one sign bit for each blinded value we send. */
for (i = 0; i < (header.n_rings + 6) >> 3; i++) {
Expand Down Expand Up @@ -501,7 +495,7 @@ SECP256K1_INLINE static int secp256k1_rangeproof_sign_impl(const secp256k1_ecmul
secp256k1_sha256_write(&sha256_m, extra_commit, extra_commit_len);
}
secp256k1_sha256_finalize(&sha256_m, tmp);
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, k, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
if (!secp256k1_borromean_sign(ecmult_gen_ctx, &proof[len], s, pubs, sec, header.rsizes, secidx, header.n_rings, tmp, 32)) {
return 0;
}
len += 32;
Expand Down
7 changes: 1 addition & 6 deletions src/modules/rangeproof/tests_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,6 @@ static void test_borromean(void) {
unsigned char e0[32];
secp256k1_scalar s[64];
secp256k1_gej pubs[64];
secp256k1_scalar k[8];
secp256k1_scalar sec[8];
secp256k1_ge ge;
secp256k1_scalar one;
Expand All @@ -344,13 +343,9 @@ static void test_borromean(void) {
rsizes[i] = 1 + (secp256k1_testrand32()&7);
secidx[i] = secp256k1_testrand32() % rsizes[i];
random_scalar_order(&sec[i]);
random_scalar_order(&k[i]);
if(secp256k1_testrand32()&7) {
sec[i] = one;
}
if(secp256k1_testrand32()&7) {
k[i] = one;
}
for (j = 0; j < rsizes[i]; j++) {
random_scalar_order(&s[c + j]);
if(secp256k1_testrand32()&7) {
Expand All @@ -365,7 +360,7 @@ static void test_borromean(void) {
}
c += rsizes[i];
}
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, k, sec, rsizes, secidx, nrings, m, 32));
CHECK(secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, e0, s, pubs, sec, rsizes, secidx, nrings, m, 32));
CHECK(secp256k1_borromean_verify(NULL, e0, s, pubs, rsizes, nrings, m, 32));
i = secp256k1_testrand32() % c;
secp256k1_scalar_negate(&s[i],&s[i]);
Expand Down
8 changes: 1 addition & 7 deletions src/modules/surjection/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,6 @@ int secp256k1_surjectionproof_initialize(const secp256k1_context* ctx, secp256k1
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) {
secp256k1_scalar blinding_key;
secp256k1_scalar tmps;
secp256k1_scalar nonce;
int overflow = 0;
size_t rsizes[1]; /* array needed for borromean sig API */
size_t indices[1]; /* array needed for borromean sig API */
Expand Down Expand Up @@ -333,12 +332,7 @@ int secp256k1_surjectionproof_generate(const secp256k1_context* ctx, secp256k1_s
if (secp256k1_surjection_genrand(borromean_s, n_used_pubkeys, &blinding_key) == 0) {
return 0;
}
/* Borromean sign will overwrite one of the s values we just generated, so use
* it as a nonce instead. This avoids extra random generation and also is an
* homage to the rangeproof code which does this very cleverly to encode messages. */
nonce = borromean_s[ring_input_index];
secp256k1_scalar_clear(&borromean_s[ring_input_index]);
if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &nonce, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
if (secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &proof->data[0], borromean_s, ring_pubkeys, &blinding_key, rsizes, indices, 1, msg32, 32) == 0) {
return 0;
}
for (i = 0; i < n_used_pubkeys; i++) {
Expand Down
19 changes: 3 additions & 16 deletions src/modules/whitelist/main_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
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_gej pubs[MAX_KEYS];
secp256k1_scalar s[MAX_KEYS];
secp256k1_scalar sec, non;
secp256k1_scalar sec;
unsigned char msg32[32];
int ret;

Expand Down Expand Up @@ -47,19 +47,7 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
secp256k1_scalar_get_b32(seckey32, &sec);
while (1) {
size_t i;
unsigned char nonce32[32];
int done;
ret = secp256k1_nonce_function_default(nonce32, msg32, seckey32, NULL, NULL, count);
if (!ret) {
break;
}
secp256k1_scalar_set_b32(&non, nonce32, &overflow);
memset(nonce32, 0, 32);
if (overflow || secp256k1_scalar_is_zero(&non)) {
count++;
continue;
}
done = 1;
int done = 1;
for (i = 0; i < n_keys; i++) {
msg32[0] ^= i + 1;
msg32[1] ^= (i + 1) / 0x100;
Expand All @@ -85,12 +73,11 @@ int secp256k1_whitelist_sign(const secp256k1_context* ctx, secp256k1_whitelist_s
/* Actually sign */
if (ret) {
sig->n_keys = n_keys;
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &non, &sec, &n_keys, &index, 1, msg32, 32);
ret = secp256k1_borromean_sign(&ctx->ecmult_gen_ctx, &sig->data[0], s, pubs, &sec, &n_keys, &index, 1, msg32, 32);
/* Signing will change s[index], so update in the sig structure */
secp256k1_scalar_get_b32(&sig->data[32 * (index + 1)], &s[index]);
}

secp256k1_scalar_clear(&non);
secp256k1_scalar_clear(&sec);
return ret;
}
Expand Down

0 comments on commit f25f555

Please sign in to comment.