Revert "Remove unused Jacobi symbol support"
This reverts commit 20448b8d09a492afcfcae7721033c13a44a776fd. The removed functions secp256k1_ge_set_xquad and secp256k1_fe_is_quad_var are required for some modules in secp256k1-zkp.
This commit is contained in:
parent
edcacc2b2e
commit
d27e459861
@ -245,6 +245,26 @@ 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;
|
||||
@ -252,10 +272,8 @@ void bench_group_to_affine_var(void* arg, int iters) {
|
||||
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.
|
||||
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). */
|
||||
Similar to bench_group_jacobi_var, this approach does not result in
|
||||
coordinates of points 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);
|
||||
@ -364,6 +382,7 @@ 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);
|
||||
|
@ -103,6 +103,9 @@ 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);
|
||||
|
@ -135,6 +135,11 @@ 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) {
|
||||
secp256k1_fe r;
|
||||
return secp256k1_fe_sqrt(&r, a);
|
||||
}
|
||||
|
||||
static const secp256k1_fe secp256k1_fe_one = SECP256K1_FE_CONST(0, 0, 0, 0, 0, 0, 0, 1);
|
||||
|
||||
#endif /* SECP256K1_FIELD_IMPL_H */
|
||||
|
@ -42,6 +42,12 @@ 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);
|
||||
@ -89,6 +95,9 @@ 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);
|
||||
|
||||
|
@ -206,14 +206,18 @@ static void secp256k1_ge_clear(secp256k1_ge *r) {
|
||||
secp256k1_fe_clear(&r->y);
|
||||
}
|
||||
|
||||
static int secp256k1_ge_set_xo_var(secp256k1_ge *r, const secp256k1_fe *x, int odd) {
|
||||
static int secp256k1_ge_set_xquad(secp256k1_ge *r, const secp256k1_fe *x) {
|
||||
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);
|
||||
if (!secp256k1_fe_sqrt(&r->y, &x3)) {
|
||||
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)) {
|
||||
return 0;
|
||||
}
|
||||
secp256k1_fe_normalize_var(&r->y);
|
||||
@ -650,6 +654,20 @@ 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;
|
||||
|
39
src/tests.c
39
src/tests.c
@ -3510,35 +3510,64 @@ void run_ec_commit(void) {
|
||||
void test_group_decompress(const secp256k1_fe* x) {
|
||||
/* The input itself, normalized. */
|
||||
secp256k1_fe fex = *x;
|
||||
/* Results of set_xo_var(..., 0), set_xo_var(..., 1). */
|
||||
secp256k1_ge ge_even, ge_odd;
|
||||
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;
|
||||
/* Return values of the above calls. */
|
||||
int res_even, res_odd;
|
||||
int res_quad, 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_even == res_odd);
|
||||
CHECK(res_quad == res_even);
|
||||
CHECK(res_quad == res_odd);
|
||||
|
||||
if (res_even) {
|
||||
if (res_quad) {
|
||||
secp256k1_fe_normalize_var(&ge_quad.x);
|
||||
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));
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user