From 3f7a9429adccf16e192cd792c1f92b42ad83aaea Mon Sep 17 00:00:00 2001 From: mllwchrry Date: Wed, 25 Feb 2026 16:14:32 +0200 Subject: [PATCH] ecdsa_adaptor: batch affine conversion in dleq_pair and dleq_prove --- src/modules/ecdsa_adaptor/dleq_impl.h | 62 ++++++++++++++------------ src/modules/ecdsa_adaptor/main_impl.h | 9 +++- src/modules/ecdsa_adaptor/tests_impl.h | 5 ++- 3 files changed, 45 insertions(+), 31 deletions(-) diff --git a/src/modules/ecdsa_adaptor/dleq_impl.h b/src/modules/ecdsa_adaptor/dleq_impl.h index 53b3003e..11d2d667 100644 --- a/src/modules/ecdsa_adaptor/dleq_impl.h +++ b/src/modules/ecdsa_adaptor/dleq_impl.h @@ -77,29 +77,27 @@ static void secp256k1_dleq_challenge(secp256k1_scalar *e, secp256k1_ge *gen2, se secp256k1_scalar_set_b32(e, buf, NULL); } -/* P1 = x*G, P2 = x*Y */ -static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *p1, secp256k1_ge *p2, const secp256k1_scalar *sk, const secp256k1_ge *gen2) { - secp256k1_gej p1j, p2j; +/* p[0] = x*G, p[1] = x*Y */ +static void secp256k1_dleq_pair(const secp256k1_ecmult_gen_context *ecmult_gen_ctx, secp256k1_ge *p, const secp256k1_scalar *sk, const secp256k1_ge *gen2) { + secp256k1_gej pj[2]; - secp256k1_ecmult_gen(ecmult_gen_ctx, &p1j, sk); - secp256k1_ge_set_gej(p1, &p1j); - secp256k1_ecmult_const(&p2j, gen2, sk); - secp256k1_ge_set_gej(p2, &p2j); + secp256k1_ecmult_gen(ecmult_gen_ctx, &pj[0], sk); + secp256k1_ecmult_const(&pj[1], gen2, sk); + secp256k1_ge_set_all_gej(p, pj, 2); } /* Generates a proof that the discrete logarithm of P1 to the secp256k1 base G is the * same as the discrete logarithm of P2 to the base Y */ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *s, secp256k1_scalar *e, const secp256k1_scalar *sk, secp256k1_ge *gen2, secp256k1_ge *p1, secp256k1_ge *p2, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) { - secp256k1_ge r1, r2; + secp256k1_ge r[2]; secp256k1_scalar k = { 0 }; unsigned char sk32[32]; unsigned char gen2_33[33]; unsigned char p1_33[33]; unsigned char p2_33[33]; - int ret = 1; size_t pubkey_size = 33; + int ret; - secp256k1_scalar_get_b32(sk32, sk); if (!secp256k1_eckey_pubkey_serialize(gen2, gen2_33, &pubkey_size, 1)) { return 0; } @@ -110,22 +108,30 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar * return 0; } - ret &= secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); - /* R1 = k*G, R2 = k*Y */ - secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, &r1, &r2, &k, gen2); - /* We declassify the non-secret values r1 and r2 to allow using them as - * branch points. */ - secp256k1_declassify(ctx, &r1, sizeof(r1)); - secp256k1_declassify(ctx, &r2, sizeof(r2)); + secp256k1_scalar_get_b32(sk32, sk); - /* e = tagged hash(p1, gen2, p2, r1, r2) */ + ret = secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, noncefp, ndata); + secp256k1_declassify(ctx, &ret, sizeof(ret)); + if (!ret) { + secp256k1_memclear_explicit(sk32, sizeof(sk32)); + return 0; + } + /* R1 = k*G, R2 = k*Y */ + secp256k1_dleq_pair(&ctx->ecmult_gen_ctx, r, &k, gen2); + /* We declassify the non-secret values r[0] and r[1] to allow using them as + * branch points. */ + secp256k1_declassify(ctx, &r[0], sizeof(r[0])); + secp256k1_declassify(ctx, &r[1], sizeof(r[1])); + + /* e = tagged hash(p1, gen2, p2, r[0], r[1]) */ /* s = k + e * sk */ - secp256k1_dleq_challenge(e, gen2, &r1, &r2, p1, p2); + secp256k1_dleq_challenge(e, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_mul(s, e, sk); secp256k1_scalar_add(s, s, &k); secp256k1_scalar_clear(&k); - return ret; + secp256k1_memclear_explicit(sk32, sizeof(sk32)); + return 1; } static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scalar *e, secp256k1_ge *p1, secp256k1_ge *gen2, secp256k1_ge *p2) { @@ -133,8 +139,8 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_scalar e_expected; secp256k1_gej gen2j; secp256k1_gej p1j, p2j; - secp256k1_gej r1j, r2j; - secp256k1_ge r1, r2; + secp256k1_gej rj[2]; + secp256k1_ge r[2]; secp256k1_gej tmpj; secp256k1_gej_set_ge(&p1j, p1); @@ -142,16 +148,16 @@ static int secp256k1_dleq_verify(const secp256k1_scalar *s, const secp256k1_scal secp256k1_scalar_negate(&e_neg, e); /* R1 = s*G - e*P1 */ - secp256k1_ecmult(&r1j, &p1j, &e_neg, s); + secp256k1_ecmult(&rj[0], &p1j, &e_neg, s); /* R2 = s*gen2 - e*P2 */ secp256k1_ecmult(&tmpj, &p2j, &e_neg, &secp256k1_scalar_zero); secp256k1_gej_set_ge(&gen2j, gen2); - secp256k1_ecmult(&r2j, &gen2j, s, &secp256k1_scalar_zero); - secp256k1_gej_add_var(&r2j, &r2j, &tmpj, NULL); + secp256k1_ecmult(&rj[1], &gen2j, s, &secp256k1_scalar_zero); + secp256k1_gej_add_var(&rj[1], &rj[1], &tmpj, NULL); - secp256k1_ge_set_gej(&r1, &r1j); - secp256k1_ge_set_gej(&r2, &r2j); - secp256k1_dleq_challenge(&e_expected, gen2, &r1, &r2, p1, p2); + secp256k1_ge_set_all_gej_var(r, rj, 2); + + secp256k1_dleq_challenge(&e_expected, gen2, &r[0], &r[1], p1, p2); secp256k1_scalar_add(&e_expected, &e_expected, &e_neg); return secp256k1_scalar_is_zero(&e_expected); diff --git a/src/modules/ecdsa_adaptor/main_impl.h b/src/modules/ecdsa_adaptor/main_impl.h index ee0b09a7..e97bb5a0 100644 --- a/src/modules/ecdsa_adaptor/main_impl.h +++ b/src/modules/ecdsa_adaptor/main_impl.h @@ -201,8 +201,12 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char secp256k1_declassify(ctx, &nonce_pts[1], sizeof(nonce_pts[1])); /* dleq_proof = DLEQ_prove(k, (R', Y, R)) */ - ret &= secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata); - + if (!secp256k1_dleq_prove(ctx, &dleq_proof_s, &dleq_proof_e, &k, &enckey_ge, &nonce_pts[0], &nonce_pts[1], noncefp, ndata)) { + memset(adaptor_sig162, 0, 162); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); + secp256k1_scalar_clear(&k); + return 0; + } ret &= secp256k1_scalar_set_b32_seckey(&sk, seckey32); secp256k1_scalar_cmov(&sk, &secp256k1_scalar_one, !ret); secp256k1_scalar_set_b32(&msg, msg32, NULL); @@ -221,6 +225,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s); secp256k1_memczero(adaptor_sig162, 162, !ret); + secp256k1_memclear_explicit(nonce32, sizeof(nonce32)); secp256k1_scalar_clear(&n); secp256k1_scalar_clear(&k); secp256k1_scalar_clear(&sk); diff --git a/src/modules/ecdsa_adaptor/tests_impl.h b/src/modules/ecdsa_adaptor/tests_impl.h index e2293adc..5e41a9c0 100644 --- a/src/modules/ecdsa_adaptor/tests_impl.h +++ b/src/modules/ecdsa_adaptor/tests_impl.h @@ -31,6 +31,7 @@ static void dleq_nonce_bitflip(unsigned char **args, size_t n_flip, size_t n_byt static void dleq_tests_internal(void) { secp256k1_scalar s, e, sk, k; secp256k1_ge gen2, p1, p2; + secp256k1_ge p[2]; unsigned char *args[5]; unsigned char sk32[32]; unsigned char gen2_33[33]; @@ -42,7 +43,9 @@ static void dleq_tests_internal(void) { rand_point(&gen2); rand_scalar(&sk); - secp256k1_dleq_pair(&CTX->ecmult_gen_ctx, &p1, &p2, &sk, &gen2); + secp256k1_dleq_pair(&CTX->ecmult_gen_ctx, p, &sk, &gen2); + p1 = p[0]; + p2 = p[1]; CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p1, &p2, NULL, NULL) == 1); CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p2) == 1);