Skip to content

Commit add8e78

Browse files
committed
f use xonly_pubkeys in schnorrsig sign and verify
1 parent 7eeb3aa commit add8e78

File tree

4 files changed

+58
-51
lines changed

4 files changed

+58
-51
lines changed

include/secp256k1_schnorrsig.h

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,13 +88,13 @@ SECP256K1_API int secp256k1_schnorrsig_sign(
8888
* Args: ctx: a secp256k1 context object, initialized for verification.
8989
* In: sig: the signature being verified (cannot be NULL)
9090
* msg32: the 32-byte message being verified (cannot be NULL)
91-
* pubkey: pointer to a public key to verify with (cannot be NULL)
91+
* pubkey: pointer to an x-only public key to verify with (cannot be NULL)
9292
*/
9393
SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify(
9494
const secp256k1_context* ctx,
9595
const secp256k1_schnorrsig *sig,
9696
const unsigned char *msg32,
97-
const secp256k1_pubkey *pubkey
97+
const secp256k1_xonly_pubkey *pubkey
9898
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2) SECP256K1_ARG_NONNULL(3) SECP256K1_ARG_NONNULL(4);
9999

100100
/** Verifies a set of Schnorr signatures.
@@ -105,7 +105,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify(
105105
* scratch: scratch space used for the multiexponentiation
106106
* In: sig: array of signatures, or NULL if there are no signatures
107107
* msg32: array of messages, or NULL if there are no signatures
108-
* pk: array of public keys, or NULL if there are no signatures
108+
* pk: array of x-only public keys, or NULL if there are no signatures
109109
* n_sigs: number of signatures in above arrays. Must be smaller than
110110
* 2^31 and smaller than half the maximum size_t value. Must be 0
111111
* if above arrays are NULL.
@@ -115,7 +115,7 @@ SECP256K1_API SECP256K1_WARN_UNUSED_RESULT int secp256k1_schnorrsig_verify_batch
115115
secp256k1_scratch_space *scratch,
116116
const secp256k1_schnorrsig *const *sig,
117117
const unsigned char *const *msg32,
118-
const secp256k1_pubkey *const *pk,
118+
const secp256k1_xonly_pubkey *const *pk,
119119
size_t n_sigs
120120
) SECP256K1_ARG_NONNULL(1) SECP256K1_ARG_NONNULL(2);
121121

src/bench_schnorrsig.c

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -44,22 +44,22 @@ void bench_schnorrsig_verify(void* arg) {
4444
size_t i;
4545

4646
for (i = 0; i < 1000; i++) {
47-
secp256k1_pubkey pk;
48-
CHECK(secp256k1_ec_pubkey_parse(data->ctx, &pk, data->pk[i], 33) == 1);
47+
secp256k1_xonly_pubkey pk;
48+
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, &pk, data->pk[i]) == 1);
4949
CHECK(secp256k1_schnorrsig_verify(data->ctx, data->sigs[i], data->msgs[i], &pk));
5050
}
5151
}
5252

5353
void bench_schnorrsig_verify_n(void* arg) {
5454
bench_schnorrsig_data *data = (bench_schnorrsig_data *)arg;
5555
size_t i, j;
56-
const secp256k1_pubkey **pk = (const secp256k1_pubkey **)malloc(data->n * sizeof(*pk));
56+
const secp256k1_xonly_pubkey **pk = (const secp256k1_xonly_pubkey **)malloc(data->n * sizeof(*pk));
5757

5858
CHECK(pk != NULL);
5959
for (j = 0; j < MAX_SIGS/data->n; j++) {
6060
for (i = 0; i < data->n; i++) {
61-
secp256k1_pubkey *pk_nonconst = (secp256k1_pubkey *)malloc(sizeof(*pk_nonconst));
62-
CHECK(secp256k1_ec_pubkey_parse(data->ctx, pk_nonconst, data->pk[i], 33) == 1);
61+
secp256k1_xonly_pubkey *pk_nonconst = (secp256k1_xonly_pubkey *)malloc(sizeof(*pk_nonconst));
62+
CHECK(secp256k1_xonly_pubkey_parse(data->ctx, pk_nonconst, data->pk[i]) == 1);
6363
pk[i] = pk_nonconst;
6464
}
6565
CHECK(secp256k1_schnorrsig_verify_batch(data->ctx, data->scratch, data->sigs, data->msgs, pk, data->n));
@@ -84,9 +84,8 @@ int main(void) {
8484
unsigned char sk[32];
8585
unsigned char *msg = (unsigned char *)malloc(32);
8686
secp256k1_schnorrsig *sig = (secp256k1_schnorrsig *)malloc(sizeof(*sig));
87-
unsigned char *pk_char = (unsigned char *)malloc(33);
88-
secp256k1_pubkey pk;
89-
size_t pk_len = 33;
87+
unsigned char *pk_char = (unsigned char *)malloc(32);
88+
secp256k1_xonly_pubkey pk;
9089
msg[0] = sk[0] = i;
9190
msg[1] = sk[1] = i >> 8;
9291
msg[2] = sk[2] = i >> 16;
@@ -98,8 +97,8 @@ int main(void) {
9897
data.msgs[i] = msg;
9998
data.sigs[i] = sig;
10099

101-
CHECK(secp256k1_ec_pubkey_create(data.ctx, &pk, sk));
102-
CHECK(secp256k1_ec_pubkey_serialize(data.ctx, pk_char, &pk_len, &pk, SECP256K1_EC_COMPRESSED) == 1);
100+
CHECK(secp256k1_xonly_pubkey_create(data.ctx, &pk, sk));
101+
CHECK(secp256k1_xonly_pubkey_serialize(data.ctx, pk_char, &pk) == 1);
103102
CHECK(secp256k1_schnorrsig_sign(data.ctx, sig, msg, sk, NULL, NULL));
104103
}
105104

src/modules/schnorrsig/main_impl.h

Lines changed: 30 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -54,8 +54,7 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, secp256k1_schnorrsig
5454
secp256k1_ge r;
5555
secp256k1_sha256 sha;
5656
int overflow;
57-
unsigned char buf[33];
58-
size_t buflen = sizeof(buf);
57+
unsigned char buf[32];
5958

6059
VERIFY_CHECK(ctx != NULL);
6160
ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
@@ -76,6 +75,13 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, secp256k1_schnorrsig
7675
secp256k1_ecmult_gen(&ctx->ecmult_gen_ctx, &pkj, &x);
7776
secp256k1_ge_set_gej(&pk, &pkj);
7877

78+
/* Because we are signing for a x-only pubkey, the secret key is negated
79+
* before signing if the point corresponding to the secret key is not
80+
* positive. */
81+
if (!secp256k1_fe_is_quad_var(&pk.y)) {
82+
secp256k1_scalar_negate(&x, &x);
83+
}
84+
7985
if (!noncefp(buf, msg32, seckey, (unsigned char *) "BIPSchnorrDerive", (void*)ndata, 0)) {
8086
return 0;
8187
}
@@ -93,12 +99,12 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, secp256k1_schnorrsig
9399
secp256k1_fe_normalize(&r.x);
94100
secp256k1_fe_get_b32(&sig->data[0], &r.x);
95101

96-
97-
/* tagged hash(r.x, pk, msg32) */
102+
/* tagged hash(r.x, pk.x, msg32) */
98103
secp256k1_schnorrsig_sha256_tagged(&sha);
99104
secp256k1_sha256_write(&sha, &sig->data[0], 32);
100-
secp256k1_eckey_pubkey_serialize(&pk, buf, &buflen, 1);
101-
secp256k1_sha256_write(&sha, buf, buflen);
105+
secp256k1_fe_normalize(&pk.x);
106+
secp256k1_fe_get_b32(buf, &pk.x);
107+
secp256k1_sha256_write(&sha, buf, sizeof(buf));
102108
secp256k1_sha256_write(&sha, msg32, 32);
103109
secp256k1_sha256_finalize(&sha, buf);
104110

@@ -115,14 +121,14 @@ int secp256k1_schnorrsig_sign(const secp256k1_context* ctx, secp256k1_schnorrsig
115121

116122
/* Helper function for verification and batch verification.
117123
* Computes R = sG - eP. */
118-
static int secp256k1_schnorrsig_real_verify(const secp256k1_context* ctx, secp256k1_gej *rj, const secp256k1_scalar *s, const secp256k1_scalar *e, const secp256k1_pubkey *pk) {
124+
static int secp256k1_schnorrsig_real_verify(const secp256k1_context* ctx, secp256k1_gej *rj, const secp256k1_scalar *s, const secp256k1_scalar *e, const secp256k1_xonly_pubkey *pk) {
119125
secp256k1_scalar nege;
120126
secp256k1_ge pkp;
121127
secp256k1_gej pkj;
122128

123129
secp256k1_scalar_negate(&nege, e);
124130

125-
if (!secp256k1_pubkey_load(ctx, &pkp, pk)) {
131+
if (!secp256k1_pubkey_load(ctx, &pkp, (secp256k1_pubkey *) pk)) {
126132
return 0;
127133
}
128134
secp256k1_gej_set_ge(&pkj, &pkp);
@@ -132,14 +138,13 @@ static int secp256k1_schnorrsig_real_verify(const secp256k1_context* ctx, secp25
132138
return 1;
133139
}
134140

135-
int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *msg32, const secp256k1_pubkey *pk) {
141+
int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_schnorrsig *sig, const unsigned char *msg32, const secp256k1_xonly_pubkey *pk) {
136142
secp256k1_scalar s;
137143
secp256k1_scalar e;
138144
secp256k1_gej rj;
139145
secp256k1_fe rx;
140146
secp256k1_sha256 sha;
141-
unsigned char buf[33];
142-
size_t buflen = sizeof(buf);
147+
unsigned char buf[32];
143148
int overflow;
144149

145150
VERIFY_CHECK(ctx != NULL);
@@ -159,8 +164,8 @@ int secp256k1_schnorrsig_verify(const secp256k1_context* ctx, const secp256k1_sc
159164

160165
secp256k1_schnorrsig_sha256_tagged(&sha);
161166
secp256k1_sha256_write(&sha, &sig->data[0], 32);
162-
secp256k1_ec_pubkey_serialize(ctx, buf, &buflen, pk, SECP256K1_EC_COMPRESSED);
163-
secp256k1_sha256_write(&sha, buf, buflen);
167+
secp256k1_xonly_pubkey_serialize(ctx, buf, pk);
168+
secp256k1_sha256_write(&sha, buf, sizeof(buf));
164169
secp256k1_sha256_write(&sha, msg32, 32);
165170
secp256k1_sha256_finalize(&sha, buf);
166171
secp256k1_scalar_set_b32(&e, buf, NULL);
@@ -186,7 +191,7 @@ typedef struct {
186191
/* Signature, message, public key tuples to verify */
187192
const secp256k1_schnorrsig *const *sig;
188193
const unsigned char *const *msg32;
189-
const secp256k1_pubkey *const *pk;
194+
const secp256k1_xonly_pubkey *const *pk;
190195
size_t n_sigs;
191196
} secp256k1_schnorrsig_verify_ecmult_context;
192197

@@ -217,20 +222,19 @@ static int secp256k1_schnorrsig_verify_batch_ecmult_callback(secp256k1_scalar *s
217222
}
218223
/* eP */
219224
} else {
220-
unsigned char buf[33];
221-
size_t buflen = sizeof(buf);
225+
unsigned char buf[32];
222226
secp256k1_sha256 sha;
223227
secp256k1_schnorrsig_sha256_tagged(&sha);
224228
secp256k1_sha256_write(&sha, &ecmult_context->sig[idx / 2]->data[0], 32);
225-
secp256k1_ec_pubkey_serialize(ecmult_context->ctx, buf, &buflen, ecmult_context->pk[idx / 2], SECP256K1_EC_COMPRESSED);
226-
secp256k1_sha256_write(&sha, buf, buflen);
229+
secp256k1_xonly_pubkey_serialize(ecmult_context->ctx, buf, ecmult_context->pk[idx / 2]);
230+
secp256k1_sha256_write(&sha, buf, sizeof(buf));
227231
secp256k1_sha256_write(&sha, ecmult_context->msg32[idx / 2], 32);
228232
secp256k1_sha256_finalize(&sha, buf);
229233

230234
secp256k1_scalar_set_b32(sc, buf, NULL);
231235
secp256k1_scalar_mul(sc, sc, &ecmult_context->randomizer_cache[(idx / 2) % 2]);
232236

233-
if (!secp256k1_pubkey_load(ecmult_context->ctx, pt, ecmult_context->pk[idx / 2])) {
237+
if (!secp256k1_pubkey_load(ecmult_context->ctx, pt, (secp256k1_pubkey *) ecmult_context->pk[idx / 2])) {
234238
return 0;
235239
}
236240
}
@@ -251,7 +255,7 @@ static int secp256k1_schnorrsig_verify_batch_ecmult_callback(secp256k1_scalar *s
251255
* pk: array of public keys, or NULL if there are no signatures
252256
* n_sigs: number of signatures in above arrays (must be 0 if they are NULL)
253257
*/
254-
static int secp256k1_schnorrsig_verify_batch_init_randomizer(const secp256k1_context *ctx, secp256k1_schnorrsig_verify_ecmult_context *ecmult_context, secp256k1_sha256 *sha, const secp256k1_schnorrsig *const *sig, const unsigned char *const *msg32, const secp256k1_pubkey *const *pk, size_t n_sigs) {
258+
static int secp256k1_schnorrsig_verify_batch_init_randomizer(const secp256k1_context *ctx, secp256k1_schnorrsig_verify_ecmult_context *ecmult_context, secp256k1_sha256 *sha, const secp256k1_schnorrsig *const *sig, const unsigned char *const *msg32, const secp256k1_xonly_pubkey *const *pk, size_t n_sigs) {
255259
size_t i;
256260

257261
if (n_sigs > 0) {
@@ -265,7 +269,11 @@ static int secp256k1_schnorrsig_verify_batch_init_randomizer(const secp256k1_con
265269
size_t buflen = sizeof(buf);
266270
secp256k1_sha256_write(sha, sig[i]->data, 64);
267271
secp256k1_sha256_write(sha, msg32[i], 32);
268-
secp256k1_ec_pubkey_serialize(ctx, buf, &buflen, pk[i], SECP256K1_EC_COMPRESSED);
272+
/* We use compressed serialization here. If we would use
273+
* xonly_pubkey serialization and a user would wrongly memcpy
274+
* normal secp256k1_pubkeys into xonly_pubkeys then the randomizer
275+
* would be the same for two different pubkeys. */
276+
secp256k1_ec_pubkey_serialize(ctx, buf, &buflen, (secp256k1_pubkey *) pk[i], SECP256K1_EC_COMPRESSED);
269277
secp256k1_sha256_write(sha, buf, buflen);
270278
}
271279
ecmult_context->ctx = ctx;
@@ -313,7 +321,7 @@ static int secp256k1_schnorrsig_verify_batch_sum_s(secp256k1_scalar *s, unsigned
313321
* Seeds a random number generator with the inputs and derives a random number ai for every
314322
* signature i. Fails if y-coordinate of any R is not a quadratic residue or if
315323
* 0 != -(s1 + a2*s2 + ... + au*su)G + R1 + a2*R2 + ... + au*Ru + e1*P1 + (a2*e2)P2 + ... + (au*eu)Pu. */
316-
int secp256k1_schnorrsig_verify_batch(const secp256k1_context *ctx, secp256k1_scratch *scratch, const secp256k1_schnorrsig *const *sig, const unsigned char *const *msg32, const secp256k1_pubkey *const *pk, size_t n_sigs) {
324+
int secp256k1_schnorrsig_verify_batch(const secp256k1_context *ctx, secp256k1_scratch *scratch, const secp256k1_schnorrsig *const *sig, const unsigned char *const *msg32, const secp256k1_xonly_pubkey *const *pk, size_t n_sigs) {
317325
secp256k1_schnorrsig_verify_ecmult_context ecmult_context;
318326
secp256k1_sha256 sha;
319327
secp256k1_scalar s;

src/modules/schnorrsig/tests_impl.h

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -26,11 +26,11 @@ void test_schnorrsig_api(secp256k1_scratch_space *scratch) {
2626
unsigned char sk3[32];
2727
unsigned char msg[32];
2828
unsigned char sig64[64];
29-
secp256k1_pubkey pk[3];
29+
secp256k1_xonly_pubkey pk[3];
3030
secp256k1_schnorrsig sig;
3131
const secp256k1_schnorrsig *sigptr = &sig;
3232
const unsigned char *msgptr = msg;
33-
const secp256k1_pubkey *pkptr = &pk[0];
33+
const secp256k1_xonly_pubkey *pkptr = &pk[0];
3434

3535
/** setup **/
3636
secp256k1_context *none = secp256k1_context_create(SECP256K1_CONTEXT_NONE);
@@ -52,9 +52,9 @@ void test_schnorrsig_api(secp256k1_scratch_space *scratch) {
5252
secp256k1_rand256(sk2);
5353
secp256k1_rand256(sk3);
5454
secp256k1_rand256(msg);
55-
CHECK(secp256k1_ec_pubkey_create(ctx, &pk[0], sk1) == 1);
56-
CHECK(secp256k1_ec_pubkey_create(ctx, &pk[1], sk2) == 1);
57-
CHECK(secp256k1_ec_pubkey_create(ctx, &pk[2], sk3) == 1);
55+
CHECK(secp256k1_xonly_pubkey_create(ctx, &pk[0], sk1) == 1);
56+
CHECK(secp256k1_xonly_pubkey_create(ctx, &pk[1], sk2) == 1);
57+
CHECK(secp256k1_xonly_pubkey_create(ctx, &pk[2], sk3) == 1);
5858

5959
/** main test body **/
6060
ecount = 0;
@@ -142,13 +142,13 @@ void test_schnorrsig_sha256_tagged(void) {
142142
void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const unsigned char *pk_serialized, const unsigned char *msg, const unsigned char *expected_sig) {
143143
secp256k1_schnorrsig sig;
144144
unsigned char serialized_sig[64];
145-
secp256k1_pubkey pk;
145+
secp256k1_xonly_pubkey pk;
146146

147147
CHECK(secp256k1_schnorrsig_sign(ctx, &sig, msg, sk, NULL, NULL));
148148
CHECK(secp256k1_schnorrsig_serialize(ctx, serialized_sig, &sig));
149149
CHECK(memcmp(serialized_sig, expected_sig, 64) == 0);
150150

151-
CHECK(secp256k1_ec_pubkey_parse(ctx, &pk, pk_serialized, 33));
151+
CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk, pk_serialized));
152152
CHECK(secp256k1_schnorrsig_verify(ctx, &sig, msg, &pk));
153153
}
154154

@@ -157,11 +157,11 @@ void test_schnorrsig_bip_vectors_check_signing(const unsigned char *sk, const un
157157
void test_schnorrsig_bip_vectors_check_verify(secp256k1_scratch_space *scratch, const unsigned char *pk_serialized, const unsigned char *msg32, const unsigned char *sig_serialized, int expected) {
158158
const unsigned char *msg_arr[1];
159159
const secp256k1_schnorrsig *sig_arr[1];
160-
const secp256k1_pubkey *pk_arr[1];
161-
secp256k1_pubkey pk;
160+
const secp256k1_xonly_pubkey *pk_arr[1];
161+
secp256k1_xonly_pubkey pk;
162162
secp256k1_schnorrsig sig;
163163

164-
CHECK(secp256k1_ec_pubkey_parse(ctx, &pk, pk_serialized, 33));
164+
CHECK(secp256k1_xonly_pubkey_parse(ctx, &pk, pk_serialized));
165165
CHECK(secp256k1_schnorrsig_parse(ctx, &sig, sig_serialized));
166166

167167
sig_arr[0] = &sig;
@@ -368,9 +368,9 @@ void test_schnorrsig_bip_vectors(secp256k1_scratch_space *scratch) {
368368
0x87, 0x66, 0xE4, 0xFA, 0xA0, 0x4A, 0x2D, 0x4A,
369369
0x34
370370
};
371-
secp256k1_pubkey pk7_parsed;
371+
secp256k1_xonly_pubkey pk7_parsed;
372372
/* No need to check the signature of the test vector as parsing the pubkey already fails */
373-
CHECK(!secp256k1_ec_pubkey_parse(ctx, &pk7_parsed, pk7, 33));
373+
CHECK(!secp256k1_xonly_pubkey_parse(ctx, &pk7_parsed, pk7));
374374
}
375375
{
376376
/* Test vector 8 */
@@ -667,10 +667,10 @@ void test_schnorrsig_sign_verify(secp256k1_scratch_space *scratch) {
667667
size_t i;
668668
const secp256k1_schnorrsig *sig_arr[N_SIGS];
669669
const unsigned char *msg_arr[N_SIGS];
670-
const secp256k1_pubkey *pk_arr[N_SIGS];
671-
secp256k1_pubkey pk;
670+
const secp256k1_xonly_pubkey *pk_arr[N_SIGS];
671+
secp256k1_xonly_pubkey pk;
672672

673-
CHECK(secp256k1_ec_pubkey_create(ctx, &pk, sk));
673+
CHECK(secp256k1_xonly_pubkey_create(ctx, &pk, sk));
674674

675675
CHECK(secp256k1_schnorrsig_verify_batch(ctx, scratch, NULL, NULL, NULL, 0));
676676

0 commit comments

Comments
 (0)