Skip to content

Commit

Permalink
Remove unused Jacobi symbol support
Browse files Browse the repository at this point in the history
No exposed functions rely on Jacobi symbol computation anymore. Remove it; it can always
be brough back later if needed.
  • Loading branch information
sipa committed Mar 12, 2021
1 parent 5437e7b commit 20448b8
Show file tree
Hide file tree
Showing 6 changed files with 11 additions and 197 deletions.
48 changes: 4 additions & 44 deletions src/bench_internal.c
Original file line number Diff line number Diff line change
Expand Up @@ -246,35 +246,17 @@ void bench_group_add_affine_var(void* arg, int iters) {
}
}

void bench_group_jacobi_var(void* arg, int iters) {
int i, j = 0;
bench_inv *data = (bench_inv*)arg;

for (i = 0; i < iters; i++) {
j += secp256k1_gej_has_quad_y_var(&data->gej[0]);
/* Vary the Y and Z coordinates of the input (the X coordinate doesn't matter to
secp256k1_gej_has_quad_y_var). Note that the resulting coordinates will
generally not correspond to a point on the curve, but this is not a problem
for the code being benchmarked here. Adding and normalizing have less
overhead than EC operations (which could guarantee the point remains on the
curve). */
secp256k1_fe_add(&data->gej[0].y, &data->fe[1]);
secp256k1_fe_add(&data->gej[0].z, &data->fe[2]);
secp256k1_fe_normalize_var(&data->gej[0].y);
secp256k1_fe_normalize_var(&data->gej[0].z);
}
CHECK(j <= iters);
}

void bench_group_to_affine_var(void* arg, int iters) {
int i;
bench_inv *data = (bench_inv*)arg;

for (i = 0; i < iters; ++i) {
secp256k1_ge_set_gej_var(&data->ge[1], &data->gej[0]);
/* Use the output affine X/Y coordinates to vary the input X/Y/Z coordinates.
Similar to bench_group_jacobi_var, this approach does not result in
coordinates of points on the curve. */
Note that the resulting coordinates will generally not correspond to a point
on the curve, but this is not a problem for the code being benchmarked here.
Adding and normalizing have less overhead than EC operations (which could
guarantee the point remains on the curve). */
secp256k1_fe_add(&data->gej[0].x, &data->ge[1].y);
secp256k1_fe_add(&data->gej[0].y, &data->fe[2]);
secp256k1_fe_add(&data->gej[0].z, &data->ge[1].x);
Expand Down Expand Up @@ -360,24 +342,6 @@ void bench_context_sign(void* arg, int iters) {
}
}

#ifndef USE_NUM_NONE
void bench_num_jacobi(void* arg, int iters) {
int i, j = 0;
bench_inv *data = (bench_inv*)arg;
secp256k1_num nx, na, norder;

secp256k1_scalar_get_num(&nx, &data->scalar[0]);
secp256k1_scalar_order_get_num(&norder);
secp256k1_scalar_get_num(&na, &data->scalar[1]);

for (i = 0; i < iters; i++) {
j += secp256k1_num_jacobi(&nx, &norder);
secp256k1_num_add(&nx, &nx, &na);
}
CHECK(j <= iters);
}
#endif

int main(int argc, char **argv) {
bench_inv data;
int iters = get_iters(20000);
Expand All @@ -401,7 +365,6 @@ int main(int argc, char **argv) {
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_var", bench_group_add_var, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine", bench_group_add_affine, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "add")) run_benchmark("group_add_affine_var", bench_group_add_affine_var, bench_setup, NULL, &data, 10, iters*10);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "jacobi")) run_benchmark("group_jacobi_var", bench_group_jacobi_var, bench_setup, NULL, &data, 10, iters);
if (have_flag(argc, argv, "group") || have_flag(argc, argv, "to_affine")) run_benchmark("group_to_affine_var", bench_group_to_affine_var, bench_setup, NULL, &data, 10, iters);

if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, iters);
Expand All @@ -414,8 +377,5 @@ int main(int argc, char **argv) {
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "verify")) run_benchmark("context_verify", bench_context_verify, bench_setup, NULL, &data, 10, 1 + iters/1000);
if (have_flag(argc, argv, "context") || have_flag(argc, argv, "sign")) run_benchmark("context_sign", bench_context_sign, bench_setup, NULL, &data, 10, 1 + iters/100);

#ifndef USE_NUM_NONE
if (have_flag(argc, argv, "num") || have_flag(argc, argv, "jacobi")) run_benchmark("num_jacobi", bench_num_jacobi, bench_setup, NULL, &data, 10, iters*10);
#endif
return 0;
}
3 changes: 0 additions & 3 deletions src/field.h
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
* itself. */
static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a);

/** Checks whether a field element is a quadratic residue. */
static int secp256k1_fe_is_quad_var(const secp256k1_fe *a);

/** Sets a field element to be the (modular) inverse of another. Requires the input's magnitude to be
* at most 8. The output magnitude is 1 (but not guaranteed to be normalized). */
static void secp256k1_fe_inv(secp256k1_fe *r, const secp256k1_fe *a);
Expand Down
25 changes: 0 additions & 25 deletions src/field_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -136,31 +136,6 @@ static int secp256k1_fe_sqrt(secp256k1_fe *r, const secp256k1_fe *a) {
return secp256k1_fe_equal(&t1, a);
}

static int secp256k1_fe_is_quad_var(const secp256k1_fe *a) {
#ifndef USE_NUM_NONE
unsigned char b[32];
secp256k1_num n;
secp256k1_num m;
/* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
static const unsigned char prime[32] = {
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
};

secp256k1_fe c = *a;
secp256k1_fe_normalize_var(&c);
secp256k1_fe_get_b32(b, &c);
secp256k1_num_set_bin(&n, b, 32);
secp256k1_num_set_bin(&m, prime, 32);
return secp256k1_num_jacobi(&n, &m) >= 0;
#else
secp256k1_fe r;
return secp256k1_fe_sqrt(&r, a);
#endif
}

static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);

#endif /* SECP256K1_FIELD_IMPL_H */
9 changes: 0 additions & 9 deletions src/group.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,12 +43,6 @@ typedef struct {
/** Set a group element equal to the point with given X and Y coordinates */
static void secp256k1_ge_set_xy(secp256k1_ge *r, const secp256k1_fe *x, const secp256k1_fe *y);

/** Set a group element (affine) equal to the point with the given X coordinate
* and a Y coordinate that is a quadratic residue modulo p. The return value
* is true iff a coordinate with the given X coordinate exists.
*/
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x);

/** Set a group element (affine) equal to the point with the given X coordinate, and given oddness
* 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);
Expand Down Expand Up @@ -96,9 +90,6 @@ static void secp256k1_gej_neg(secp256k1_gej *r, const secp256k1_gej *a);
/** Check whether a group element is the point at infinity. */
static int secp256k1_gej_is_infinity(const secp256k1_gej *a);

/** Check whether a group element's y coordinate is a quadratic residue. */
static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a);

/** Set r equal to the double of a. Constant time. */
static void secp256k1_gej_double(secp256k1_gej *r, const secp256k1_gej *a);

Expand Down
22 changes: 2 additions & 20 deletions src/group_impl.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,18 +207,14 @@ static void secp256k1_ge_clear(secp256k1_ge *r) {
secp256k1_fe_clear(&r->y);
}

static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
secp256k1_fe x2, x3;
r->x = *x;
secp256k1_fe_sqr(&x2, x);
secp256k1_fe_mul(&x3, x, &x2);
r->infinity = 0;
secp256k1_fe_add(&x3, &secp256k1_fe_const_b);
return secp256k1_fe_sqrt(&r->y, &x3);
}

static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
if (!secp256k1_ge_set_xquad(r, x)) {
if (!secp256k1_fe_sqrt(&r->y, &x3)) {
return 0;
}
secp256k1_fe_normalize_var(&r->y);
Expand Down Expand Up @@ -655,20 +651,6 @@ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
secp256k1_fe_mul(&r->x, &r->x, &beta);
}

static int secp256k1_gej_has_quad_y_var(const secp256k1_gej *a) {
secp256k1_fe yz;

if (a->infinity) {
return 0;
}

/* We rely on the fact that the Jacobi symbol of 1 / a->z^3 is the same as
* that of a->z. Thus a->y / a->z^3 is a quadratic residue iff a->y * a->z
is */
secp256k1_fe_mul(&yz, &a->y, &a->z);
return secp256k1_fe_is_quad_var(&yz);
}

static int secp256k1_ge_is_in_correct_subgroup(const secp256k1_ge* ge) {
#ifdef EXHAUSTIVE_TEST_ORDER
secp256k1_gej out;
Expand Down
101 changes: 5 additions & 96 deletions src/tests.c
Original file line number Diff line number Diff line change
Expand Up @@ -750,74 +750,12 @@ void test_num_mod(void) {
CHECK(secp256k1_num_is_zero(&n));
}

void test_num_jacobi(void) {
secp256k1_scalar sqr;
secp256k1_scalar small;
secp256k1_scalar five; /* five is not a quadratic residue */
secp256k1_num order, n;
int i;
/* squares mod 5 are 1, 4 */
const int jacobi5[10] = { 0, 1, -1, -1, 1, 0, 1, -1, -1, 1 };

/* check some small values with 5 as the order */
secp256k1_scalar_set_int(&five, 5);
secp256k1_scalar_get_num(&order, &five);
for (i = 0; i < 10; ++i) {
secp256k1_scalar_set_int(&small, i);
secp256k1_scalar_get_num(&n, &small);
CHECK(secp256k1_num_jacobi(&n, &order) == jacobi5[i]);
}

/** test large values with 5 as group order */
secp256k1_scalar_get_num(&order, &five);
/* we first need a scalar which is not a multiple of 5 */
do {
secp256k1_num fiven;
random_scalar_order_test(&sqr);
secp256k1_scalar_get_num(&fiven, &five);
secp256k1_scalar_get_num(&n, &sqr);
secp256k1_num_mod(&n, &fiven);
} while (secp256k1_num_is_zero(&n));
/* next force it to be a residue. 2 is a nonresidue mod 5 so we can
* just multiply by two, i.e. add the number to itself */
if (secp256k1_num_jacobi(&n, &order) == -1) {
secp256k1_num_add(&n, &n, &n);
}

/* test residue */
CHECK(secp256k1_num_jacobi(&n, &order) == 1);
/* test nonresidue */
secp256k1_num_add(&n, &n, &n);
CHECK(secp256k1_num_jacobi(&n, &order) == -1);

/** test with secp group order as order */
secp256k1_scalar_order_get_num(&order);
random_scalar_order_test(&sqr);
secp256k1_scalar_mul(&sqr, &sqr, &sqr);
/* test residue */
secp256k1_scalar_get_num(&n, &sqr);
CHECK(secp256k1_num_jacobi(&n, &order) == 1);
/* test nonresidue */
secp256k1_scalar_mul(&sqr, &sqr, &five);
secp256k1_scalar_get_num(&n, &sqr);
CHECK(secp256k1_num_jacobi(&n, &order) == -1);
/* test multiple of the order*/
CHECK(secp256k1_num_jacobi(&order, &order) == 0);

/* check one less than the order */
secp256k1_scalar_set_int(&small, 1);
secp256k1_scalar_get_num(&n, &small);
secp256k1_num_sub(&n, &order, &n);
CHECK(secp256k1_num_jacobi(&n, &order) == 1); /* sage confirms this is 1 */
}

void run_num_smalltests(void) {
int i;
for (i = 0; i < 100*count; i++) {
test_num_negate();
test_num_add_sub();
test_num_mod();
test_num_jacobi();
}
}
#endif
Expand Down Expand Up @@ -2959,64 +2897,35 @@ void run_ec_combine(void) {
void test_group_decompress(const secp256k1_fe* x) {
/* The input itself, normalized. */
secp256k1_fe fex = *x;
secp256k1_fe fez;
/* Results of set_xquad_var, set_xo_var(..., 0), set_xo_var(..., 1). */
secp256k1_ge ge_quad, ge_even, ge_odd;
secp256k1_gej gej_quad;
/* Results of set_xo_var(..., 0), set_xo_var(..., 1). */
secp256k1_ge ge_even, ge_odd;
/* Return values of the above calls. */
int res_quad, res_even, res_odd;
int res_even, res_odd;

secp256k1_fe_normalize_var(&fex);

res_quad = secp256k1_ge_set_xquad(&ge_quad, &fex);
res_even = secp256k1_ge_set_xo_var(&ge_even, &fex, 0);
res_odd = secp256k1_ge_set_xo_var(&ge_odd, &fex, 1);

CHECK(res_quad == res_even);
CHECK(res_quad == res_odd);
CHECK(res_even == res_odd);

if (res_quad) {
secp256k1_fe_normalize_var(&ge_quad.x);
if (res_even) {
secp256k1_fe_normalize_var(&ge_odd.x);
secp256k1_fe_normalize_var(&ge_even.x);
secp256k1_fe_normalize_var(&ge_quad.y);
secp256k1_fe_normalize_var(&ge_odd.y);
secp256k1_fe_normalize_var(&ge_even.y);

/* No infinity allowed. */
CHECK(!ge_quad.infinity);
CHECK(!ge_even.infinity);
CHECK(!ge_odd.infinity);

/* Check that the x coordinates check out. */
CHECK(secp256k1_fe_equal_var(&ge_quad.x, x));
CHECK(secp256k1_fe_equal_var(&ge_even.x, x));
CHECK(secp256k1_fe_equal_var(&ge_odd.x, x));

/* Check that the Y coordinate result in ge_quad is a square. */
CHECK(secp256k1_fe_is_quad_var(&ge_quad.y));

/* Check odd/even Y in ge_odd, ge_even. */
CHECK(secp256k1_fe_is_odd(&ge_odd.y));
CHECK(!secp256k1_fe_is_odd(&ge_even.y));

/* Check secp256k1_gej_has_quad_y_var. */
secp256k1_gej_set_ge(&gej_quad, &ge_quad);
CHECK(secp256k1_gej_has_quad_y_var(&gej_quad));
do {
random_fe_test(&fez);
} while (secp256k1_fe_is_zero(&fez));
secp256k1_gej_rescale(&gej_quad, &fez);
CHECK(secp256k1_gej_has_quad_y_var(&gej_quad));
secp256k1_gej_neg(&gej_quad, &gej_quad);
CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad));
do {
random_fe_test(&fez);
} while (secp256k1_fe_is_zero(&fez));
secp256k1_gej_rescale(&gej_quad, &fez);
CHECK(!secp256k1_gej_has_quad_y_var(&gej_quad));
secp256k1_gej_neg(&gej_quad, &gej_quad);
CHECK(secp256k1_gej_has_quad_y_var(&gej_quad));
}
}

Expand Down

0 comments on commit 20448b8

Please sign in to comment.