ecdsa_adaptor: batch affine conversion in dleq_pair and dleq_prove

This commit is contained in:
mllwchrry
2026-02-25 16:14:32 +02:00
parent d380549e38
commit 3f7a9429ad
3 changed files with 45 additions and 31 deletions

View File

@@ -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);

View File

@@ -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);

View File

@@ -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);