modules: Port bitcoin-core/secp256k1#1774 to zkp-specific code

This commit is contained in:
mllwchrry
2026-03-02 16:40:12 +02:00
parent 07d4de6433
commit 2542b43451
7 changed files with 46 additions and 93 deletions

View File

@@ -47,8 +47,11 @@ static int secp256k1_bppp_parse_one_of_points(secp256k1_ge *pt, const unsigned c
/* Outputs a serialized point in compressed form. Returns 0 at point at infinity.
*/
static int secp256k1_bppp_serialize_pt(unsigned char *output, secp256k1_ge *lpt) {
size_t size;
return secp256k1_eckey_pubkey_serialize(lpt, output, &size, 1 /*compressed*/);
if (secp256k1_ge_is_infinity(lpt)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(lpt, output);
return 1;
}
/* little-endian encodes a uint64 */

View File

@@ -20,16 +20,13 @@ static void secp256k1_nonce_function_dleq_sha256_tagged(secp256k1_sha256 *sha) {
/* algo argument for nonce_function_ecdsa_adaptor to derive the nonce using a tagged hash function. */
static const unsigned char dleq_algo[] = {'D','L','E','Q'};
static int secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) {
static void secp256k1_dleq_hash_point(secp256k1_sha256 *sha, secp256k1_ge *p) {
unsigned char buf[33];
size_t size = 33;
if (!secp256k1_eckey_pubkey_serialize(p, buf, &size, 1)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(p, buf);
secp256k1_sha256_write(sha, buf, size);
return 1;
}
static int secp256k1_dleq_nonce(secp256k1_scalar *k, const unsigned char *sk32, const unsigned char *gen2_33, const unsigned char *p1_33, const unsigned char *p2_33, secp256k1_nonce_function_hardened_ecdsa_adaptor noncefp, void *ndata) {
@@ -95,18 +92,11 @@ static int secp256k1_dleq_prove(const secp256k1_context* ctx, secp256k1_scalar *
unsigned char gen2_33[33];
unsigned char p1_33[33];
unsigned char p2_33[33];
size_t pubkey_size = 33;
int ret;
if (!secp256k1_eckey_pubkey_serialize(gen2, gen2_33, &pubkey_size, 1)) {
return 0;
}
if (!secp256k1_eckey_pubkey_serialize(p1, p1_33, &pubkey_size, 1)) {
return 0;
}
if (!secp256k1_eckey_pubkey_serialize(p2, p2_33, &pubkey_size, 1)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(gen2, gen2_33);
secp256k1_eckey_pubkey_serialize33(p1, p1_33);
secp256k1_eckey_pubkey_serialize33(p2, p2_33);
secp256k1_scalar_get_b32(sk32, sk);

View File

@@ -11,20 +11,12 @@
#include "dleq_impl.h"
/* (R, R', s', dleq_proof) */
static int secp256k1_ecdsa_adaptor_sig_serialize(unsigned char *adaptor_sig162, secp256k1_ge *r, secp256k1_ge *rp, const secp256k1_scalar *sp, const secp256k1_scalar *dleq_proof_e, const secp256k1_scalar *dleq_proof_s) {
size_t size = 33;
if (!secp256k1_eckey_pubkey_serialize(r, adaptor_sig162, &size, 1)) {
return 0;
}
if (!secp256k1_eckey_pubkey_serialize(rp, &adaptor_sig162[33], &size, 1)) {
return 0;
}
static void secp256k1_ecdsa_adaptor_sig_serialize(unsigned char *adaptor_sig162, secp256k1_ge *r, secp256k1_ge *rp, const secp256k1_scalar *sp, const secp256k1_scalar *dleq_proof_e, const secp256k1_scalar *dleq_proof_s) {
secp256k1_eckey_pubkey_serialize33(r, adaptor_sig162);
secp256k1_eckey_pubkey_serialize33(rp, &adaptor_sig162[33]);
secp256k1_scalar_get_b32(&adaptor_sig162[66], sp);
secp256k1_scalar_get_b32(&adaptor_sig162[98], dleq_proof_e);
secp256k1_scalar_get_b32(&adaptor_sig162[130], dleq_proof_s);
return 1;
}
static int secp256k1_ecdsa_adaptor_sig_deserialize(secp256k1_ge *r, secp256k1_scalar *sigr, secp256k1_ge *rp, secp256k1_scalar *sp, secp256k1_scalar *dleq_proof_e, secp256k1_scalar *dleq_proof_s, const unsigned char *adaptor_sig162) {
@@ -162,7 +154,6 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
secp256k1_scalar n;
unsigned char nonce32[32] = { 0 };
unsigned char buf33[33];
size_t size = 33;
int ret = 1;
VERIFY_CHECK(ctx != NULL);
@@ -183,7 +174,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
return 0;
}
secp256k1_eckey_pubkey_serialize(&enckey_ge, buf33, &size, 1);
secp256k1_eckey_pubkey_serialize33(&enckey_ge, buf33);
ret &= !!noncefp(nonce32, msg32, seckey32, buf33, ecdsa_adaptor_algo, sizeof(ecdsa_adaptor_algo), ndata);
secp256k1_scalar_set_b32(&k, nonce32, NULL);
ret &= !secp256k1_scalar_is_zero(&k);
@@ -222,7 +213,7 @@ int secp256k1_ecdsa_adaptor_encrypt(const secp256k1_context* ctx, unsigned char
ret &= !secp256k1_scalar_is_zero(&sp);
/* return (R, R', s', dleq_proof) */
ret &= secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig162, &nonce_pts[1], &nonce_pts[0], &sp, &dleq_proof_e, &dleq_proof_s);
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));
@@ -319,10 +310,10 @@ int secp256k1_ecdsa_adaptor_recover(const secp256k1_context* ctx, unsigned char
secp256k1_scalar s, r;
secp256k1_scalar deckey;
secp256k1_ge enckey_expected_ge;
secp256k1_ge enckey_ge;
secp256k1_gej enckey_expected_gej;
unsigned char enckey33[33];
unsigned char enckey_expected33[33];
size_t size = 33;
int ret = 1;
VERIFY_CHECK(ctx != NULL);
@@ -349,23 +340,21 @@ int secp256k1_ecdsa_adaptor_recover(const secp256k1_context* ctx, unsigned char
/* We declassify non-secret enckey_expected_ge to allow using it as a
* branch point. */
secp256k1_declassify(ctx, &enckey_expected_ge, sizeof(enckey_expected_ge));
if (!secp256k1_eckey_pubkey_serialize(&enckey_expected_ge, enckey_expected33, &size, 1)) {
/* Unreachable from tests (and other VERIFY builds) and therefore this
* branch should be ignored in test coverage analysis.
*
* Proof:
* eckey_pubkey_serialize fails <=> deckey = 0
* deckey = 0 <=> s^-1 = 0 or sp = 0
* case 1: s^-1 = 0 impossible by the definition of multiplicative
* inverse and because the scalar_inverse implementation
* VERIFY_CHECKs that the inputs are valid scalars.
* case 2: sp = 0 impossible because ecdsa_adaptor_sig_deserialize would have already failed
*/
return 0;
}
if (!secp256k1_ec_pubkey_serialize(ctx, enckey33, &size, enckey, SECP256K1_EC_COMPRESSED)) {
/* enckey_expected_ge cannot be infinity:
*
* Proof:
* enckey_expected_ge is infinity <=> deckey = 0
* deckey = 0 <=> s^-1 = 0 or sp = 0
* case 1: s^-1 = 0 impossible by the definition of multiplicative
* inverse and because the scalar_inverse implementation
* VERIFY_CHECKs that the inputs are valid scalars.
* case 2: sp = 0 impossible because ecdsa_adaptor_sig_deserialize would have already failed
*/
secp256k1_eckey_pubkey_serialize33(&enckey_expected_ge, enckey_expected33);
if (!secp256k1_pubkey_load(ctx, &enckey_ge, enckey)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(&enckey_ge, enckey33);
if (secp256k1_memcmp_var(&enckey_expected33[1], &enckey33[1], 32) != 0) {
return 0;
}

View File

@@ -39,7 +39,6 @@ static void dleq_tests_internal(void) {
unsigned char p2_33[33];
unsigned char aux_rand[32];
int i;
size_t pubkey_size = 33;
rand_point(&gen2);
rand_scalar(&sk);
@@ -62,19 +61,12 @@ static void dleq_tests_internal(void) {
CHECK(secp256k1_dleq_verify(&s, &e, &p1, &p_tmp, &p2) == 0);
CHECK(secp256k1_dleq_verify(&s, &e, &p1, &gen2, &p_tmp) == 0);
}
{
secp256k1_ge p_inf;
secp256k1_ge_set_infinity(&p_inf);
CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &p_inf, &p1, &p2, NULL, NULL) == 0);
CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p_inf, &p2, NULL, NULL) == 0);
CHECK(secp256k1_dleq_prove(CTX, &s, &e, &sk, &gen2, &p1, &p_inf, NULL, NULL) == 0);
}
/* Nonce tests */
secp256k1_scalar_get_b32(sk32, &sk);
CHECK(secp256k1_eckey_pubkey_serialize(&gen2, gen2_33, &pubkey_size, 1));
CHECK(secp256k1_eckey_pubkey_serialize(&p1, p1_33, &pubkey_size, 1));
CHECK(secp256k1_eckey_pubkey_serialize(&p2, p2_33, &pubkey_size, 1));
secp256k1_eckey_pubkey_serialize33(&gen2, gen2_33);
secp256k1_eckey_pubkey_serialize33(&p1, p1_33);
secp256k1_eckey_pubkey_serialize33(&p2, p2_33);
CHECK(secp256k1_dleq_nonce(&k, sk32, gen2_33, p1_33, p2_33, NULL, NULL) == 1);
testrand_bytes_test(sk32, sizeof(sk32));
@@ -165,7 +157,7 @@ static void test_ecdsa_adaptor_spec_vectors_check_serialization(const unsigned c
CHECK(expected == secp256k1_ecdsa_adaptor_sig_deserialize(&r, &sigr, &rp, &sp, &dleq_proof_e, &dleq_proof_s, adaptor_sig162));
if (expected == 1) {
CHECK(secp256k1_ecdsa_adaptor_sig_serialize(buf, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 1);
secp256k1_ecdsa_adaptor_sig_serialize(buf, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s);
CHECK(secp256k1_memcmp_var(buf, adaptor_sig162, 162) == 0);
}
}
@@ -896,18 +888,12 @@ static void adaptor_tests_internal(void) {
secp256k1_scalar sigr;
secp256k1_scalar sp;
secp256k1_scalar dleq_proof_s, dleq_proof_e;
secp256k1_ge p_inf;
unsigned char adaptor_sig_tmp[162];
CHECK(secp256k1_ecdsa_adaptor_sig_deserialize(&r, &sigr, &rp, &sp, &dleq_proof_e, &dleq_proof_s, adaptor_sig) == 1);
CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 1);
secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &rp, &sp, &dleq_proof_e, &dleq_proof_s);
CHECK(secp256k1_memcmp_var(adaptor_sig_tmp, adaptor_sig, sizeof(adaptor_sig_tmp)) == 0);
/* Test adaptor_sig_serialize points at infinity */
secp256k1_ge_set_infinity(&p_inf);
CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &p_inf, &rp, &sp, &dleq_proof_e, &dleq_proof_s) == 0);
CHECK(secp256k1_ecdsa_adaptor_sig_serialize(adaptor_sig_tmp, &r, &p_inf, &sp, &dleq_proof_e, &dleq_proof_s) == 0);
}
{
/* Test adaptor_sig_deserialize */

View File

@@ -60,7 +60,6 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
size_t i;
size_t j;
size_t count;
size_t size;
int overflow;
VERIFY_CHECK(e0 != NULL);
VERIFY_CHECK(s != NULL);
@@ -88,12 +87,12 @@ int secp256k1_borromean_verify(secp256k1_scalar *evalues, const unsigned char *e
}
/* OPT: loop can be hoisted and split to use batch inversion across all the rings; this would make it much faster. */
secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
secp256k1_eckey_pubkey_serialize33(&rge, tmp);
if (j != rsizes[i] - 1) {
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
} else {
secp256k1_sha256_write(&sha256_e0, tmp, size);
secp256k1_sha256_write(&sha256_e0, tmp, 33);
}
count++;
}
@@ -115,7 +114,6 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
size_t i;
size_t j;
size_t count;
size_t size;
int overflow;
VERIFY_CHECK(ecmult_gen_ctx != NULL);
VERIFY_CHECK(e0 != NULL);
@@ -136,7 +134,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
if (secp256k1_gej_is_infinity(&rgej)) {
return 0;
}
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
secp256k1_eckey_pubkey_serialize33(&rge, tmp);
for (j = secidx[i] + 1; j < rsizes[i]; j++) {
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
@@ -152,9 +150,9 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
return 0;
}
secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
secp256k1_eckey_pubkey_serialize33(&rge, tmp);
}
secp256k1_sha256_write(&sha256_e0, tmp, size);
secp256k1_sha256_write(&sha256_e0, tmp, 33);
count += rsizes[i];
}
secp256k1_sha256_write(&sha256_e0, m, mlen);
@@ -174,7 +172,7 @@ int secp256k1_borromean_sign(const secp256k1_ecmult_gen_context *ecmult_gen_ctx,
return 0;
}
secp256k1_ge_set_gej_var(&rge, &rgej);
secp256k1_eckey_pubkey_serialize(&rge, tmp, &size, 1);
secp256k1_eckey_pubkey_serialize33(&rge, tmp);
secp256k1_borromean_hash(tmp, m, mlen, tmp, 33, i, j + 1);
secp256k1_scalar_set_b32(&ens, tmp, &overflow);
if (overflow || secp256k1_scalar_is_zero(&ens)) {

View File

@@ -18,9 +18,10 @@ static int secp256k1_whitelist_hash_pubkey(secp256k1_scalar* output, secp256k1_g
secp256k1_ge_set_gej(&ge, pubkey);
secp256k1_sha256_initialize(&sha);
if (!secp256k1_eckey_pubkey_serialize(&ge, c, &size, 1)) {
if (secp256k1_ge_is_infinity(&ge)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(&ge, c);
secp256k1_sha256_write(&sha, c, size);
secp256k1_sha256_finalize(&sha, h);
secp256k1_sha256_clear(&sha);
@@ -95,9 +96,7 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context*
secp256k1_pubkey_load(ctx, &subkey_ge, sub_pubkey);
/* commit to sub-key */
if (!secp256k1_eckey_pubkey_serialize(&subkey_ge, c, &size, 1)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(&subkey_ge, c);
secp256k1_sha256_write(&sha, c, size);
for (i = 0; i < n_keys; i++) {
secp256k1_ge offline_ge;
@@ -106,14 +105,10 @@ static int secp256k1_whitelist_compute_keys_and_message(const secp256k1_context*
/* commit to fixed keys */
secp256k1_pubkey_load(ctx, &offline_ge, &offline_pubkeys[i]);
if (!secp256k1_eckey_pubkey_serialize(&offline_ge, c, &size, 1)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(&offline_ge, c);
secp256k1_sha256_write(&sha, c, size);
secp256k1_pubkey_load(ctx, &online_ge, &online_pubkeys[i]);
if (!secp256k1_eckey_pubkey_serialize(&online_ge, c, &size, 1)) {
return 0;
}
secp256k1_eckey_pubkey_serialize33(&online_ge, c);
secp256k1_sha256_write(&sha, c, size);
/* compute tweaked keys */

View File

@@ -858,15 +858,7 @@ static void secp256k1_ge_serialize_ext(unsigned char *out33, secp256k1_ge* ge) {
if (secp256k1_ge_is_infinity(ge)) {
memset(out33, 0, 33);
} else {
int ret;
size_t size = 33;
ret = secp256k1_eckey_pubkey_serialize(ge, out33, &size, 1);
#ifdef VERIFY
/* Serialize must succeed because the point is not at infinity */
VERIFY_CHECK(ret && size == 33);
#else
(void) ret;
#endif
secp256k1_eckey_pubkey_serialize33(ge, out33);
}
}