static void select_point(mpz_t x, mpz_t y, mpz_t a, mpz_t b, mpz_t N, mpz_t t, mpz_t t2) { mpz_t Q, t3, t4; gmp_randstate_t* p_randstate = get_randstate(); mpz_init(Q); mpz_init(t3); mpz_init(t4); mpz_set_ui(y, 0); while (mpz_sgn(y) == 0) { /* select a Q s.t. (Q,N) != -1 */ do { do { /* mpz_urandomm(x, *p_randstate, N); */ mpz_urandomb(x, *p_randstate, 32); /* May as well make x small */ mpz_mod(x, x, N); } while (mpz_sgn(x) == 0); mpz_mul(t, x, x); mpz_add(t, t, a); mpz_mul(t, t, x); mpz_add(t, t, b); mpz_mod(Q, t, N); } while (mpz_jacobi(Q, N) == -1); /* Select Y */ sqrtmod(y, Q, N, t, t2, t3, t4); /* TODO: if y^2 mod Ni != t, return composite */ if (mpz_sgn(y) == 0) croak("y == 0 in point selection\n"); } mpz_clear(Q); mpz_clear(t3); mpz_clear(t4); }
/* See Cohen 1.5.3 */ int modified_cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_cmp_ui(p, 2) == 0) { mpz_add_ui(x, D, 8); if (mpz_perfect_square_p(x)) { mpz_sqrt(x, x); mpz_set_ui(y, 1); result = 1; } return result; } if (mpz_jacobi(D, p) == -1) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); if ( (mpz_even_p(D) && mpz_odd_p(x)) || (mpz_odd_p(D) && mpz_even_p(x)) ) mpz_sub(x, p, x); mpz_mul_ui(a, p, 2); mpz_set(b, x); mpz_sqrt(c, p); mpz_mul_ui(c, c, 2); /* Euclidean algorithm */ while (mpz_cmp(b, c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul_ui(c, p, 4); mpz_mul(a, b, b); mpz_sub(a, c, a); /* a = 4p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
/*=========================================================================== Tonelli-Shanks: Function: Performs Tonelli-Shanks on n mod every prime in the factor base ===========================================================================*/ static void tonelliShanks(unsigned long numPrimes, mpz_t n, mpz_t * sqrts) { unsigned long i; mpz_t fbprime, t1, t2, t3, t4; mpz_init(fbprime); mpz_init(t1); mpz_init(t2); mpz_init(t3); mpz_init(t4); mpz_set_ui(sqrts[0], 0); for (i = 1; i < numPrimes; i++) { mpz_set_ui(fbprime, factorBase[i]); sqrtmod(sqrts[i], n, fbprime, t1, t2, t3, t4); } mpz_clear(t1); mpz_clear(t2); mpz_clear(t3); mpz_clear(t4); mpz_clear(fbprime); }
/* See Cohen 1.5.2 */ int cornacchia(mpz_t x, mpz_t y, mpz_t D, mpz_t p) { int result = 0; mpz_t a, b, c, d; if (mpz_jacobi(D, p) < 0) /* No solution */ return 0; mpz_init(a); mpz_init(b); mpz_init(c); mpz_init(d); sqrtmod(x, D, p, a, b, c, d); mpz_set(a, p); mpz_set(b, x); mpz_sqrt(c, p); while (mpz_cmp(b,c) > 0) { mpz_set(d, a); mpz_set(a, b); mpz_mod(b, d, b); } mpz_mul(a, b, b); mpz_sub(a, p, a); /* a = p - b^2 */ mpz_abs(d, D); /* d = |D| */ if (mpz_divisible_p(a, d)) { mpz_divexact(c, a, d); if (mpz_perfect_square_p(c)) { mpz_set(x, b); mpz_sqrt(y, c); result = 1; } } mpz_clear(a); mpz_clear(b); mpz_clear(c); mpz_clear(d); return result; }
void findPointProj(pointProj pt, giant seed, curveParams *cp) /* Starting with seed, finds a random (projective) point {x,y,1} on curve. */ { giant x = pt->x, y = pt->y, z = pt->z; CKASSERT(cp->curveType == FCT_Weierstrass); feemod(cp, seed); while(1) { gtog(seed, x); gsquare(x); feemod(cp, x); // x := seed^2 addg(cp->a, x); // x := seed^2 + a mulg(seed,x); // x := seed^3 + a*seed addg(cp->b, x); feemod(cp, x); // x := seed^3 + a seed + b. /* test cubic form for having root. */ if(sqrtmod(x, cp)) break; iaddg(1, seed); } gtog(x, y); gtog(seed,x); int_to_giant(1, z); }