Skip to content

Commit

Permalink
Add functions to test if X coordinate is valid
Browse files Browse the repository at this point in the history
  • Loading branch information
sipa committed Jun 20, 2023
1 parent a597a5a commit 79e5b2a
Show file tree
Hide file tree
Showing 3 changed files with 63 additions and 1 deletion.
6 changes: 6 additions & 0 deletions src/group.h
Expand Up @@ -51,6 +51,12 @@ static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const se
* for Y. Return value indicates whether the result is valid. */
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd);

/** Determine whether x is a valid X coordinate on the curve. */
static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x);

/** Determine whether fraction xn/xd is a valid X coordinate on the curve (xd != 0). */
static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd);

/** Check whether a group element is the point at infinity. */
static int secp256k1_ge_is_infinity(const secp256k1_ge *a);

Expand Down
28 changes: 28 additions & 0 deletions src/group_impl.h
Expand Up @@ -823,4 +823,32 @@ static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
#endif
}

static int secp256k1_ge_x_on_curve_var(const secp256k1_fe *x) {
secp256k1_fe c;
secp256k1_fe_sqr(&c, x);
secp256k1_fe_mul(&c, &c, x);
secp256k1_fe_add_int(&c, SECP256K1_B);
return secp256k1_fe_is_square_var(&c);
}

static int secp256k1_ge_x_frac_on_curve_var(const secp256k1_fe *xn, const secp256k1_fe *xd) {
/* We want to determine whether (xn/xd) is on the curve.
*
* (xn/xd)^3 + 7 is square <=> xd*xn^3 + 7*xd^4 is square (multiplying by xd^4, a square).
*/
secp256k1_fe r, t;
#ifdef VERIFY
VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(xd));
#endif
secp256k1_fe_mul(&r, xd, xn); /* r = xd*xn */
secp256k1_fe_sqr(&t, xn); /* t = xn^2 */
secp256k1_fe_mul(&r, &r, &t); /* r = xd*xn^3 */
secp256k1_fe_sqr(&t, xd); /* t = xd^2 */
secp256k1_fe_sqr(&t, &t); /* t = xd^4 */
VERIFY_CHECK(SECP256K1_B <= 31);
secp256k1_fe_mul_int(&t, SECP256K1_B); /* t = 7*xd^4 */
secp256k1_fe_add(&r, &t); /* r = xd*xn^3 + 7*xd^4 */
return secp256k1_fe_is_square_var(&r);
}

#endif /* SECP256K1_GROUP_IMPL_H */
30 changes: 29 additions & 1 deletion src/tests.c
Expand Up @@ -3775,7 +3775,7 @@ static void test_ge(void) {
*/
secp256k1_ge *ge = (secp256k1_ge *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_ge) * (1 + 4 * runs));
secp256k1_gej *gej = (secp256k1_gej *)checked_malloc(&CTX->error_callback, sizeof(secp256k1_gej) * (1 + 4 * runs));
secp256k1_fe zf;
secp256k1_fe zf, r;
secp256k1_fe zfi2, zfi3;

secp256k1_gej_set_infinity(&gej[0]);
Expand Down Expand Up @@ -3817,6 +3817,11 @@ static void test_ge(void) {
secp256k1_fe_sqr(&zfi2, &zfi3);
secp256k1_fe_mul(&zfi3, &zfi3, &zfi2);

/* Generate random r */
do {
random_field_element_test(&r);
} while(secp256k1_fe_is_zero(&r));

for (i1 = 0; i1 < 1 + 4 * runs; i1++) {
int i2;
for (i2 = 0; i2 < 1 + 4 * runs; i2++) {
Expand Down Expand Up @@ -3929,6 +3934,29 @@ static void test_ge(void) {
free(ge_set_all);
}

/* Test that all elements have X coordinates on the curve. */
for (i = 1; i < 4 * runs + 1; i++) {
secp256k1_fe n;
CHECK(secp256k1_ge_x_on_curve_var(&ge[i].x));
/* And the same holds after random rescaling. */
secp256k1_fe_mul(&n, &zf, &ge[i].x);
CHECK(secp256k1_ge_x_frac_on_curve_var(&n, &zf));
}

/* Test correspondence of secp256k1_ge_x{,_frac}_on_curve_var with ge_set_xo. */
{
secp256k1_fe n;
secp256k1_ge q;
int ret_on_curve, ret_frac_on_curve, ret_set_xo;
secp256k1_fe_mul(&n, &zf, &r);
ret_on_curve = secp256k1_ge_x_on_curve_var(&r);
ret_frac_on_curve = secp256k1_ge_x_frac_on_curve_var(&n, &zf);
ret_set_xo = secp256k1_ge_set_xo_var(&q, &r, 0);
CHECK(ret_on_curve == ret_frac_on_curve);
CHECK(ret_on_curve == ret_set_xo);
if (ret_set_xo) CHECK(secp256k1_fe_equal_var(&r, &q.x));
}

/* Test batch gej -> ge conversion with many infinities. */
for (i = 0; i < 4 * runs + 1; i++) {
int odd;
Expand Down

0 comments on commit 79e5b2a

Please sign in to comment.