mirror of
https://github.com/bitcoin/bitcoin.git
synced 2025-02-02 09:46:52 -05:00
Add function for testing quadratic residue field/group elements.
This commit is contained in:
parent
efd953a7a7
commit
e6e9805fc4
6 changed files with 76 additions and 4 deletions
|
@ -227,6 +227,15 @@ void bench_group_add_affine_var(void* arg) {
|
|||
}
|
||||
}
|
||||
|
||||
void bench_group_jacobi_var(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
||||
for (i = 0; i < 20000; i++) {
|
||||
secp256k1_gej_has_quad_y_var(&data->gej_x);
|
||||
}
|
||||
}
|
||||
|
||||
void bench_ecmult_wnaf(void* arg) {
|
||||
int i;
|
||||
bench_inv_t *data = (bench_inv_t*)arg;
|
||||
|
@ -354,6 +363,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, 200000);
|
||||
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, 200000);
|
||||
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, 200000);
|
||||
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, 20000);
|
||||
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("wnaf_const", bench_wnaf_const, bench_setup, NULL, &data, 10, 20000);
|
||||
if (have_flag(argc, argv, "ecmult") || have_flag(argc, argv, "wnaf")) run_benchmark("ecmult_wnaf", bench_ecmult_wnaf, bench_setup, NULL, &data, 10, 20000);
|
||||
|
|
|
@ -94,6 +94,9 @@ static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a);
|
|||
* itself. */
|
||||
static int secp256k1_fe_sqrt_var(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);
|
||||
|
|
|
@ -280,4 +280,29 @@ static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe *r, const secp256k
|
|||
r[0] = u;
|
||||
}
|
||||
|
||||
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_var(&r, a) == 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -94,6 +94,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. If rzr is not-NULL, r->z = a->z * *rzr (where infinity means an implicit z = 0).
|
||||
* a may not be zero. Constant time. */
|
||||
static void secp256k1_gej_double_nonzero(secp256k1_gej *r, const secp256k1_gej *a, secp256k1_fe *rzr);
|
||||
|
|
|
@ -629,4 +629,18 @@ static void secp256k1_ge_mul_lambda(secp256k1_ge *r, const secp256k1_ge *a) {
|
|||
}
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
25
src/tests.c
25
src/tests.c
|
@ -2179,9 +2179,10 @@ void run_ec_combine(void) {
|
|||
void test_group_decompress(const secp256k1_fe* x) {
|
||||
/* The input itself, normalized. */
|
||||
secp256k1_fe fex = *x;
|
||||
secp256k1_fe tmp;
|
||||
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_quad, res_even, res_odd;
|
||||
|
||||
|
@ -2213,13 +2214,29 @@ void test_group_decompress(const secp256k1_fe* 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_sqrt_var(&tmp, &ge_quad.y));
|
||||
secp256k1_fe_sqr(&tmp, &tmp);
|
||||
CHECK(secp256k1_fe_equal_var(&tmp, &ge_quad.y));
|
||||
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…
Add table
Reference in a new issue