Skip to content

Commit ce7eb6f

Browse files
committed
Optimize verification: avoid field inverse
Suggested by Greg Maxwell.
1 parent a098f78 commit ce7eb6f

File tree

3 files changed

+28
-21
lines changed

3 files changed

+28
-21
lines changed

src/ecdsa_impl.h

Lines changed: 19 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -109,25 +109,35 @@ static int secp256k1_ecdsa_sig_serialize(unsigned char *sig, int *size, const se
109109
return 1;
110110
}
111111

112-
static int secp256k1_ecdsa_sig_recompute(secp256k1_scalar_t *r2, const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
112+
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
113113
if (secp256k1_scalar_is_zero(&sig->r) || secp256k1_scalar_is_zero(&sig->s))
114114
return 0;
115115

116-
int ret = 0;
117116
secp256k1_scalar_t sn, u1, u2;
118117
secp256k1_scalar_inverse_var(&sn, &sig->s);
119118
secp256k1_scalar_mul(&u1, &sn, message);
120119
secp256k1_scalar_mul(&u2, &sn, &sig->r);
121120
secp256k1_gej_t pubkeyj; secp256k1_gej_set_ge(&pubkeyj, pubkey);
122121
secp256k1_gej_t pr; secp256k1_ecmult(&pr, &pubkeyj, &u2, &u1);
123-
if (!secp256k1_gej_is_infinity(&pr)) {
124-
secp256k1_fe_t xr; secp256k1_gej_get_x_var(&xr, &pr);
125-
secp256k1_fe_normalize_var(&xr);
126-
unsigned char xrb[32]; secp256k1_fe_get_b32(xrb, &xr);
127-
secp256k1_scalar_set_b32(r2, xrb, NULL);
128-
ret = 1;
122+
if (secp256k1_gej_is_infinity(&pr)) {
123+
return 0;
124+
}
125+
unsigned char c[32];
126+
secp256k1_scalar_get_b32(c, &sig->r);
127+
secp256k1_fe_t xr;
128+
secp256k1_fe_set_b32(&xr, c);
129+
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
130+
return 1;
131+
}
132+
if (secp256k1_fe_cmp_var(&xr, &secp256k1_ecdsa_consts->p_minus_order) >= 0) {
133+
// We can't add the order to r. This will be the case for almost every r.
134+
return 0;
129135
}
130-
return ret;
136+
secp256k1_fe_add(&xr, &secp256k1_ecdsa_consts->order_as_fe);
137+
if (secp256k1_gej_eq_x_var(&xr, &pr)) {
138+
return 1;
139+
}
140+
return 0;
131141
}
132142

133143
static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message, int recid) {
@@ -159,13 +169,6 @@ static int secp256k1_ecdsa_sig_recover(const secp256k1_ecdsa_sig_t *sig, secp256
159169
return !secp256k1_gej_is_infinity(&qj);
160170
}
161171

162-
static int secp256k1_ecdsa_sig_verify(const secp256k1_ecdsa_sig_t *sig, const secp256k1_ge_t *pubkey, const secp256k1_scalar_t *message) {
163-
secp256k1_scalar_t r2;
164-
int ret = 0;
165-
ret = secp256k1_ecdsa_sig_recompute(&r2, sig, pubkey, message) && secp256k1_scalar_eq(&sig->r, &r2);
166-
return ret;
167-
}
168-
169172
static int secp256k1_ecdsa_sig_sign(secp256k1_ecdsa_sig_t *sig, const secp256k1_scalar_t *seckey, const secp256k1_scalar_t *message, const secp256k1_scalar_t *nonce, int *recid) {
170173
secp256k1_gej_t rp;
171174
secp256k1_ecmult_gen(&rp, nonce);

src/group.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,8 +81,8 @@ static void secp256k1_gej_set_xy(secp256k1_gej_t *r, const secp256k1_fe_t *x, co
8181
/** Set a group element (jacobian) equal to another which is given in affine coordinates. */
8282
static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a);
8383

84-
/** Get the X coordinate of a group element (jacobian). */
85-
static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a);
84+
/** Compare the X coordinate of a group element (jacobian). */
85+
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a);
8686

8787
/** Set r equal to the inverse of a (i.e., mirrored around the X axis) */
8888
static void secp256k1_gej_neg_var(secp256k1_gej_t *r, const secp256k1_gej_t *a);

src/group_impl.h

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,13 @@ static void secp256k1_gej_set_ge(secp256k1_gej_t *r, const secp256k1_ge_t *a) {
163163
secp256k1_fe_set_int(&r->z, 1);
164164
}
165165

166-
static void secp256k1_gej_get_x_var(secp256k1_fe_t *r, const secp256k1_gej_t *a) {
167-
secp256k1_fe_t zi2; secp256k1_fe_inv_var(&zi2, &a->z); secp256k1_fe_sqr(&zi2, &zi2);
168-
secp256k1_fe_mul(r, &a->x, &zi2);
166+
static int secp256k1_gej_eq_x_var(const secp256k1_fe_t *x, const secp256k1_gej_t *a) {
167+
VERIFY_CHECK(!a->infinity);
168+
secp256k1_fe_t r; secp256k1_fe_sqr(&r, &a->z); secp256k1_fe_mul(&r, &r, x);
169+
secp256k1_fe_t r2 = a->x;
170+
secp256k1_fe_normalize_var(&r);
171+
secp256k1_fe_normalize_var(&r2);
172+
return secp256k1_fe_equal(&r, &r2);
169173
}
170174

171175
static void secp256k1_gej_neg_var(secp256k1_gej_t *r, const secp256k1_gej_t *a) {

0 commit comments

Comments
 (0)