int main(void) { field_t c; field_t Z19; element_t P, Q, R; mpz_t q, z; element_t a; int i; mpz_init(q); mpz_init(z); mpz_set_ui(q, 19); field_init_fp(Z19, q); element_init(a, Z19); field_init_curve_singular_with_node(c, Z19); element_init(P, c); element_init(Q, c); element_init(R, c); //(3,+/-6) is a generator //we have an isomorphism from E_ns to F_19^* // (3,6) --> 3 //(generally (x,y) --> (y+x)/(y-x) curve_set_si(R, 3, 6); for (i=1; i<=18; i++) { mpz_set_si(z, i); element_mul_mpz(Q, R, z); element_printf("%dR = %B\n", i, Q); } mpz_set_ui(z, 6); element_mul_mpz(P, R, z); //P has order 3 element_printf("P = %B\n", P); for (i=1; i<=3; i++) { mpz_set_si(z, i); element_mul_mpz(Q, R, z); tate_3(a, P, Q, R); element_printf("e_3(P,%dP) = %B\n", i, a); } element_double(P, R); //P has order 9 element_printf("P = %B\n", P); for (i=1; i<=9; i++) { mpz_set_si(z, i); element_mul_mpz(Q, P, z); tate_9(a, P, Q, R); element_printf("e_9(P,%dP) = %B\n", i, a); } return 0; }
static val_ptr run_zmod(val_ptr v[]) { element_ptr e = v[0]->elem; mpz_t z; mpz_init(z); element_to_mpz(z, e); field_ptr f = (field_ptr)pbc_malloc(sizeof(*f)); field_init_fp(f, z); mpz_clear(z); return val_new_field(f); }
void pairing_init_singular_with_node(pairing_t pairing, mpz_t q) { sn_pairing_data_ptr p; mpz_init(pairing->r); mpz_sub_ui(pairing->r, q, 1); field_init_fp(pairing->Zr, pairing->r); pairing->map = sn_pairing; p = pairing->data = pbc_malloc(sizeof(sn_pairing_data_t)); field_init_fp(p->Fq, q); field_init_curve_singular_with_node(p->Eq, p->Fq); //mpz_init(p->tateexp); //mpz_sub_ui(p->tateexp, p->Fq->order, 1); //mpz_divexact(p->tateexp, p->tateexp, pairing->r); pairing->G2 = pairing->G1 = p->Eq; pairing_GT_init(pairing, p->Fq); }
static void e_init_pairing(pairing_t pairing, void *data) { e_param_ptr param = data; e_pairing_data_ptr p; element_t a, b; mpz_init(pairing->r); mpz_set(pairing->r, param->r); field_init_fp(pairing->Zr, pairing->r); pairing->map = e_pairing; e_miller_fn = e_miller_proj; p = pairing->data = pbc_malloc(sizeof(e_pairing_data_t)); p->exp2 = param->exp2; p->exp1 = param->exp1; p->sign1 = param->sign1; p->sign0 = param->sign0; field_init_fp(p->Fq, param->q); element_init(a, p->Fq); element_init(b, p->Fq); element_set_mpz(a, param->a); element_set_mpz(b, param->b); field_init_curve_ab(p->Eq, a, b, pairing->r, param->h); //k=1, hence phikonr = (p-1)/r mpz_init(pairing->phikonr); mpz_sub_ui(pairing->phikonr, p->Fq->order, 1); mpz_divexact(pairing->phikonr, pairing->phikonr, pairing->r); pairing->G2 = pairing->G1 = p->Eq; pairing_GT_init(pairing, p->Fq); pairing->finalpow = e_finalpow; pairing->phi = phi_identity; pairing->option_set = e_pairing_option_set; pairing->clear_func = e_pairing_clear; element_init(p->R, p->Eq); curve_set_gen_no_cofac(p->R); element_clear(a); element_clear(b); }
void pbc_param_init_d_gen(pbc_param_ptr p, pbc_cm_ptr cm) { d_param_init(p); d_param_ptr param = p->data; field_t Fq, Fqx, Fqd; element_t irred, nqr; int d = cm->k / 2; int i; compute_cm_curve(param, cm); field_init_fp(Fq, param->q); field_init_poly(Fqx, Fq); element_init(irred, Fqx); do { poly_random_monic(irred, d); } while (!poly_is_irred(irred)); field_init_polymod(Fqd, irred); // Find a quadratic nonresidue of Fqd lying in Fq. element_init(nqr, Fqd); do { element_random(((element_t *) nqr->data)[0]); } while (element_is_sqr(nqr)); param->coeff = pbc_realloc(param->coeff, sizeof(mpz_t) * d); for (i=0; i<d; i++) { mpz_init(param->coeff[i]); element_to_mpz(param->coeff[i], element_item(irred, i)); } element_to_mpz(param->nqr, ((element_t *) nqr->data)[0]); element_clear(nqr); element_clear(irred); field_clear(Fqx); field_clear(Fqd); field_clear(Fq); }
static void eta_T_3_init_pairing(pairing_t pairing, params *p) { mpz_init(pairing->r); mpz_set(pairing->r, p->n); field_init_fp(pairing->Zr, pairing->r); pairing_data_ptr dp = pbc_malloc(sizeof(*dp)); mpz_init(dp->n2); mpz_set(dp->n2, p->n2); field_init_gf3m(dp->gf3m, p->m, p->t); field_init_gf32m(dp->gf32m, dp->gf3m); field_init_gf33m(dp->gf36m, dp->gf32m); pairing_GT_init(pairing, dp->gf36m); pairing->GT->name = "eta_T_3 group of roots of 1"; pairing->GT->random = GT_random; pairing->G2 = pairing->G1 = pbc_malloc(sizeof(field_t)); field_init_eta_T_3(pairing->G1, dp->gf3m); pairing->G1->pairing = pairing; mpz_set(pairing->G1->order, p->n); mpz_set(pairing->GT->order, p->n); pairing->map = eta_T_pairing; pairing->data = dp; pairing->clear_func = eta_T_3_pairing_clear; }
int main(void) { field_t c; field_t Z19; element_t P, Q, R; mpz_t q, z; element_t a, b; int i; field_t Z19_2; field_t c2; element_t P2, Q2, R2; element_t a2; mpz_init(q); mpz_init(z); mpz_set_ui(q, 19); field_init_fp(Z19, q); element_init(a, Z19); element_init(b, Z19); element_set_si(a, 1); element_set_si(b, 6); mpz_set_ui(q, 18); field_init_curve_ab(c, a, b, q, NULL); element_init(P, c); element_init(Q, c); element_init(R, c); printf("Y^2 = X^3 + X + 6 over F_19\n"); //(0,+/-5) is a generator element_set0(a); curve_from_x(R, a); for (i=1; i<19; i++) { mpz_set_si(z, i); element_mul_mpz(Q, R, z); element_printf("%dR = %B\n", i, Q); } mpz_set_ui(z, 6); element_mul_mpz(P, R, z); //P has order 3 element_printf("P = %B\n", P); for (i=1; i<=3; i++) { mpz_set_si(z, i); element_mul_mpz(Q, R, z); tate_3(a, P, Q, R); element_printf("e_3(P,%dR) = %B\n", i, a); } element_double(P, R); //P has order 9 element_printf("P = %B\n", P); for (i=1; i<=9; i++) { mpz_set_si(z, i); //we're supposed to use multiples of R //but 2R works just as well and it allows us //to use R as the offset every time element_mul_mpz(Q, P, z); tate_9(a, P, Q, R); element_printf("e_9(P,%dP) = %B\n", i, a); } //to do the pairing on all of E(F_19) we need to move to F_19^2 //or compute the rational function explicitly printf("moving to F_19^2\n"); field_init_fi(Z19_2, Z19); //don't need to tell it the real order field_init_curve_ab_map(c2, c, element_field_to_fi, Z19_2, q, NULL); element_init(P2, c2); element_init(Q2, c2); element_init(R2, c2); element_init(a2, Z19_2); element_set0(a2); curve_from_x(P2, a2); element_random(R2); element_printf("P = %B\n", P2); for (i=1; i<=18; i++) { mpz_set_si(z, i); element_mul_mpz(Q2, P2, z); tate_18(a2, P2, Q2, R2, P2); element_printf("e_18(P,%dP) = %B\n", i, a2); } element_clear(P2); element_clear(Q2); element_clear(R2); element_clear(a2); field_clear(c2); field_clear(Z19_2); field_clear(c); element_clear(a); element_clear(b); element_clear(P); element_clear(Q); element_clear(R); field_clear(Z19); mpz_clear(q); mpz_clear(z); return 0; }
int main(void) { mpz_t p, q, N, d; mpz_t dmp1, dmq1; mpz_t ipmq, iqmp; mpz_t adq, adp; field_t f; element_t a, b; double t0, t1, tnaive = 0, tcrt=0; int i, n; mpz_init(p); mpz_init(q); mpz_init(N); mpz_init(d); mpz_init(dmp1); mpz_init(dmq1); mpz_init(ipmq); mpz_init(iqmp); mpz_init(adp); mpz_init(adq); pbc_mpz_randomb(p, 512); pbc_mpz_randomb(q, 512); mpz_nextprime(p, p); mpz_nextprime(q, q); mpz_mul(N, p, q); mpz_invert(ipmq, p, q); mpz_invert(iqmp, q, p); field_init_fp(f, N); element_init(a, f); element_init(b, f); n = 10; for (i=0; i<n; i++) { pbc_mpz_random(d, N); element_random(a); t0 = pbc_get_time(); element_pow_mpz(b, a, d); t1 = pbc_get_time(); tnaive += t1 - t0; mpz_sub_ui(p, p, 1); mpz_sub_ui(q, q, 1); mpz_mod(dmp1, d, p); mpz_mod(dmq1, d, q); mpz_add_ui(p, p, 1); mpz_add_ui(q, q, 1); element_to_mpz(adq, a); element_to_mpz(adp, a); t0 = pbc_get_time(); mpz_powm(adp, adp, d, p); mpz_powm(adq, adq, d, q); /* textbook CRT mpz_mul(adp, adp, q); mpz_mul(adp, adp, iqmp); mpz_mul(adq, adq, p); mpz_mul(adq, adq, ipmq); mpz_add(adp, adp, adq); */ // Garner's algorithm mpz_sub(adq, adq, adp); mpz_mul(adq, adq, ipmq); mpz_mod(adq, adq, q); mpz_mul(adq, adq, p); mpz_add(adp, adp, adq); t1 = pbc_get_time(); tcrt += t1 - t0; element_set_mpz(b, adp); } printf("average RSA exp time = %lf\n", tnaive / n); printf("average RSA exp time (CRT) = %lf\n", tcrt / n); return 0; }
void pbc_param_init_e_gen(pbc_param_t par, int rbits, int qbits) { e_init(par); e_param_ptr p = par->data; //3 takes 2 bits to represent int hbits = (qbits - 2) / 2 - rbits; mpz_ptr q = p->q; mpz_ptr r = p->r; mpz_ptr h = p->h; mpz_t n; field_t Fq; field_t cc; element_t j; int found = 0; //won't find any curves is hbits is too low if (hbits < 3) hbits = 3; mpz_init(n); do { int i; mpz_set_ui(r, 0); if (rand() % 2) { p->exp2 = rbits - 1; p->sign1 = 1; } else { p->exp2 = rbits; p->sign1 = -1; } mpz_setbit(r, p->exp2); p->exp1 = (rand() % (p->exp2 - 1)) + 1; //use q as a temp variable mpz_set_ui(q, 0); mpz_setbit(q, p->exp1); if (p->sign1 > 0) { mpz_add(r, r, q); } else { mpz_sub(r, r, q); } if (rand() % 2) { p->sign0 = 1; mpz_add_ui(r, r, 1); } else { p->sign0 = -1; mpz_sub_ui(r, r, 1); } if (!mpz_probab_prime_p(r, 10)) continue; for (i=0; i<10; i++) { //use q as a temp variable mpz_set_ui(q, 0); mpz_setbit(q, hbits + 1); pbc_mpz_random(h, q); mpz_mul(h, h, h); mpz_mul_ui(h, h, 3); //finally q takes the value it should mpz_mul(n, r, r); mpz_mul(n, n, h); mpz_add_ui(q, n, 1); if (mpz_probab_prime_p(q, 10)) { found = 1; break; } } } while (!found); /* do { mpz_set_ui(r, 0); mpz_setbit(r, rbits); pbc_mpz_random(r, r); mpz_nextprime(r, r); mpz_mul(n, r, r); mpz_mul_ui(n, n, 3); mpz_add_ui(q, n, 1); } while (!mpz_probab_prime_p(q, 10)); */ field_init_fp(Fq, q); element_init(j, Fq); element_set_si(j, 1); field_init_curve_b(cc, j, n, NULL); element_clear(j); // We may need to twist it. { // Pick a random point P and twist the curve if P has the wrong order. element_t P; element_init(P, cc); element_random(P); element_mul_mpz(P, P, n); if (!element_is0(P)) field_reinit_curve_twist(cc); element_clear(P); } element_to_mpz(p->a, curve_field_a_coeff(cc)); element_to_mpz(p->b, curve_field_b_coeff(cc)); mpz_clear(n); }
int main(void) { int i; element_t g, h; element_t w0, w1; element_t a, b; mpz_t prime, cofac; mpz_init(prime); mpz_init(order); mpz_init(cofac); mpz_set_ui(prime, 59); field_init_fp(Fq, prime); element_init(a, Fq); element_init(b, Fq); field_init_fi(Fq2, Fq); element_set1(a); element_set0(b); mpz_set_ui(order, 5); mpz_set_ui(cofac, 12); field_init_curve_ab(E, a, b, order, cofac); element_clear(a); element_clear(b); element_init(a, Fq2); element_init(b, Fq2); element_set1(a); element_set0(b); mpz_mul(cofac, cofac, cofac); field_init_curve_ab(E2, a, b, order, NULL); element_init(g, E2); element_init(h, E2); element_init(w0, Fq2); element_init(w1, Fq2); /* do { element_random(g); } while (element_is1(g)); for (i=1; i<5; i++) { element_mul(h, h, g); element_printf("%d: %B\n", i, h); element_printf("tangent = "); do_tangent(h); } */ element_set_str(g, "[[25,0],[30,0]", 0); element_set_str(h, "[[34,0],[0,30]", 0); weil(w0, g, h); element_printf("weil: %B\n", w0); element_set1(w1); for (i=1; i<6; i++) { element_mul(w1, w1, w0); element_printf("%d: %B\n", i, w1); } fasterweil(w0, g, h); element_printf("fasterweil: %B\n", w0); element_set1(w1); for (i=1; i<6; i++) { element_mul(w1, w1, w0); element_printf("%d: %B\n", i, w1); } fasterweil2(w0, g, h); element_printf("fasterweil2: %B\n", w0); tate(w0, g, h); element_printf("tate: %B\n", w0); element_set1(w1); for (i=1; i<6; i++) { element_mul(w1, w1, w0); element_printf("%d: %B\n", i, w1); } shipseystange(w0, g, h); element_printf("ss-tate: %B\n", w0); element_set1(w1); for (i=1; i<6; i++) { element_mul(w1, w1, w0); element_printf("%d: %B\n", i, w1); } return 0; }
int main(void) { field_t fp, fx; mpz_t prime; darray_t list; int p = 7; // Exercise poly_is_irred() with a sieve of Erastosthenes for polynomials. darray_init(list); mpz_init(prime); mpz_set_ui(prime, p); field_init_fp(fp, prime); field_init_poly(fx, fp); element_t e; element_init(e, fp); // Enumerate polynomials in F_p[x] up to degree 2. int a[3], d; a[0] = a[1] = a[2] = 0; for(;;) { element_ptr f = pbc_malloc(sizeof(*f)); element_init(f, fx); int j; for(j = 0; j < 3; j++) { element_set_si(e, a[j]); poly_set_coeff(f, e, j); } // Test poly_degree(). for(j = 2; !a[j] && j >= 0; j--); EXPECT(poly_degree(f) == j); // Add monic polynomials to the list. if (j >= 0 && a[j] == 1) darray_append(list, f); else { element_clear(f); free(f); } // Next! d = 0; for(;;) { a[d]++; if (a[d] >= p) { a[d] = 0; d++; if (d > 2) goto break2; } else break; } } break2: ; // Find all composite monic polynomials of degree 3 or less. darray_t prodlist; darray_init(prodlist); void outer(void *data) { element_ptr f = data; void inner(void *data2) { element_ptr g = data2; if (!poly_degree(f) || !poly_degree(g)) return; if (poly_degree(f) + poly_degree(g) > 3) return; element_ptr h = pbc_malloc(sizeof(*h)); element_init(h, fx); element_mul(h, f, g); darray_append(prodlist, h); EXPECT(!poly_is_irred(h)); }
void pbc_param_init_f_gen(pbc_param_t p, int bits) { f_init(p); f_param_ptr fp = p->data; //36 is a 6-bit number int xbit = (bits - 6) / 4; //TODO: use binary search to find smallest appropriate x mpz_t x, t; mpz_ptr q = fp->q; mpz_ptr r = fp->r; mpz_ptr b = fp->b; field_t Fq, Fq2, Fq2x; element_t e1; element_t f; field_t c; element_t P; mpz_init(x); mpz_init(t); mpz_setbit(x, xbit); for (;;) { mpz_mul(t, x, x); mpz_mul_ui(t, t, 6); mpz_add_ui(t, t, 1); tryminusx(q, x); mpz_sub(r, q, t); mpz_add_ui(r, r, 1); if (mpz_probab_prime_p(q, 10) && mpz_probab_prime_p(r, 10)) break; tryplusx(q, x); mpz_sub(r, q, t); mpz_add_ui(r, r, 1); if (mpz_probab_prime_p(q, 10) && mpz_probab_prime_p(r, 10)) break; mpz_add_ui(x, x, 1); } field_init_fp(Fq, q); element_init(e1, Fq); for (;;) { element_random(e1); field_init_curve_b(c, e1, r, NULL); element_init(P, c); element_random(P); element_mul_mpz(P, P, r); if (element_is0(P)) break; element_clear(P); field_clear(c); } element_to_mpz(b, e1); element_clear(e1); field_init_quadratic(Fq2, Fq); element_to_mpz(fp->beta, field_get_nqr(Fq)); field_init_poly(Fq2x, Fq2); element_init(f, Fq2x); // Find an irreducible polynomial of the form f = x^6 + alpha. // Call poly_set_coeff1() first so we can use element_item() for the other // coefficients. poly_set_coeff1(f, 6); for (;;) { element_random(element_item(f, 0)); if (poly_is_irred(f)) break; } //extend F_q^2 using f = x^6 + alpha //see if sextic twist contains a subgroup of order r //if not, it's the wrong twist: replace alpha with alpha^5 { field_t ctest; element_t Ptest; mpz_t z0, z1; mpz_init(z0); mpz_init(z1); element_init(e1, Fq2); element_set_mpz(e1, fp->b); element_mul(e1, e1, element_item(f, 0)); element_neg(e1, e1); field_init_curve_b(ctest, e1, r, NULL); element_init(Ptest, ctest); element_random(Ptest); //I'm not sure what the #E'(F_q^2) is, but //it definitely divides n_12 = #E(F_q^12). It contains a //subgroup of order r if and only if //(n_12 / r^2)P != O for some (in fact most) P in E'(F_q^6) mpz_pow_ui(z0, q, 12); mpz_add_ui(z0, z0, 1); pbc_mpz_trace_n(z1, q, t, 12); mpz_sub(z1, z0, z1); mpz_mul(z0, r, r); mpz_divexact(z1, z1, z0); element_mul_mpz(Ptest, Ptest, z1); if (element_is0(Ptest)) { mpz_set_ui(z0, 5); element_pow_mpz(element_item(f, 0), element_item(f, 0), z0); } element_clear(e1); element_clear(Ptest); field_clear(ctest); mpz_clear(z0); mpz_clear(z1); } element_to_mpz(fp->alpha0, element_x(element_item(f, 0))); element_to_mpz(fp->alpha1, element_y(element_item(f, 0))); element_clear(f); field_clear(Fq2x); field_clear(Fq2); field_clear(Fq); mpz_clear(t); mpz_clear(x); }
static void f_init_pairing(pairing_t pairing, void *data) { f_param_ptr param = data; f_pairing_data_ptr p; element_t irred; element_t e0, e1, e2; p = pairing->data = pbc_malloc(sizeof(f_pairing_data_t)); mpz_init(pairing->r); mpz_set(pairing->r, param->r); field_init_fp(pairing->Zr, pairing->r); field_init_fp(p->Fq, param->q); p->Fq->nqr = pbc_malloc(sizeof(element_t)); element_init(p->Fq->nqr, p->Fq); element_set_mpz(p->Fq->nqr, param->beta); field_init_quadratic(p->Fq2, p->Fq); field_init_poly(p->Fq2x, p->Fq2); element_init(irred, p->Fq2x); // Call poly_set_coeff1() first so we can use element_item() for the other // coefficients. poly_set_coeff1(irred, 6); element_init(p->negalpha, p->Fq2); element_init(p->negalphainv, p->Fq2); element_set_mpz(element_x(p->negalpha), param->alpha0); element_set_mpz(element_y(p->negalpha), param->alpha1); element_set(element_item(irred, 0), p->negalpha); field_init_polymod(p->Fq12, irred); element_neg(p->negalpha, p->negalpha); element_invert(p->negalphainv, p->negalpha); element_clear(irred); element_init(e0, p->Fq); element_init(e1, p->Fq); element_init(e2, p->Fq2); // Initialize the curve Y^2 = X^3 + b. element_set_mpz(e1, param->b); field_init_curve_ab(p->Eq, e0, e1, pairing->r, NULL); // Initialize the curve Y^2 = X^3 - alpha0 b - alpha1 sqrt(beta) b. element_set_mpz(e0, param->alpha0); element_neg(e0, e0); element_mul(element_x(e2), e0, e1); element_set_mpz(e0, param->alpha1); element_neg(e0, e0); element_mul(element_y(e2), e0, e1); element_clear(e0); element_init(e0, p->Fq2); field_init_curve_ab(p->Etwist, e0, e2, pairing->r, NULL); element_clear(e0); element_clear(e1); element_clear(e2); mpz_t ndonr; mpz_init(ndonr); // ndonr temporarily holds the trace. mpz_sub(ndonr, param->q, param->r); mpz_add_ui(ndonr, ndonr, 1); // TODO: We can use a smaller quotient_cmp, but I have to figure out // BN curves again. pbc_mpz_curve_order_extn(ndonr, param->q, ndonr, 12); mpz_divexact(ndonr, ndonr, param->r); mpz_divexact(ndonr, ndonr, param->r); field_curve_set_quotient_cmp(p->Etwist, ndonr); mpz_clear(ndonr); pairing->G1 = p->Eq; pairing->G2 = p->Etwist; pairing_GT_init(pairing, p->Fq12); pairing->finalpow = f_finalpow; pairing->map = f_pairing; pairing->clear_func = f_pairing_clear; mpz_init(p->tateexp); /* unoptimized tate exponent mpz_pow_ui(p->tateexp, param->q, 12); mpz_sub_ui(p->tateexp, p->tateexp, 1); mpz_divexact(p->tateexp, p->tateexp, param->r); */ mpz_ptr z = p->tateexp; mpz_mul(z, param->q, param->q); mpz_sub_ui(z, z, 1); mpz_mul(z, z, param->q); mpz_mul(z, z, param->q); mpz_add_ui(z, z, 1); mpz_divexact(z, z, param->r); element_init(p->xpowq2, p->Fq2); element_init(p->xpowq6, p->Fq2); element_init(p->xpowq8, p->Fq2); element_t xpowq; element_init(xpowq, p->Fq12); //there are smarter ways since we know q = 1 mod 6 //and that x^6 = -alpha //but this is fast enough element_set1(element_item(xpowq, 1)); element_pow_mpz(xpowq, xpowq, param->q); element_pow_mpz(xpowq, xpowq, param->q); element_set(p->xpowq2, element_item(xpowq, 1)); element_pow_mpz(xpowq, xpowq, param->q); element_pow_mpz(xpowq, xpowq, param->q); element_pow_mpz(xpowq, xpowq, param->q); element_pow_mpz(xpowq, xpowq, param->q); element_set(p->xpowq6, element_item(xpowq, 1)); element_pow_mpz(xpowq, xpowq, param->q); element_pow_mpz(xpowq, xpowq, param->q); element_set(p->xpowq8, element_item(xpowq, 1)); element_clear(xpowq); }
static void d_init_pairing(pairing_ptr pairing, void *data) { d_param_ptr param = data; pptr p; element_t a, b; element_t irred; int d = param->k / 2; int i; if (param->k % 2) pbc_die("k must be even"); mpz_init(pairing->r); mpz_set(pairing->r, param->r); field_init_fp(pairing->Zr, pairing->r); pairing->map = cc_pairing; pairing->prod_pairings = cc_pairings_affine; pairing->is_almost_coddh = cc_is_almost_coddh; p = pairing->data = pbc_malloc(sizeof(*p)); field_init_fp(p->Fq, param->q); element_init(a, p->Fq); element_init(b, p->Fq); element_set_mpz(a, param->a); element_set_mpz(b, param->b); field_init_curve_ab(p->Eq, a, b, pairing->r, param->h); field_init_poly(p->Fqx, p->Fq); element_init(irred, p->Fqx); poly_set_coeff1(irred, d); for (i = 0; i < d; i++) { element_set_mpz(element_item(irred, i), param->coeff[i]); } field_init_polymod(p->Fqd, irred); element_clear(irred); p->Fqd->nqr = pbc_malloc(sizeof(element_t)); element_init(p->Fqd->nqr, p->Fqd); element_set_mpz(((element_t *) p->Fqd->nqr->data)[0], param->nqr); field_init_quadratic(p->Fqk, p->Fqd); // Compute constants involved in the final powering. if (param->k == 6) { mpz_ptr q = param->q; mpz_ptr z = pairing->phikonr; mpz_init(z); mpz_mul(z, q, q); mpz_sub(z, z, q); mpz_add_ui(z, z, 1); mpz_divexact(z, z, pairing->r); element_ptr e = p->xpowq; element_init(e, p->Fqd); element_set1(((element_t *) e->data)[1]); element_pow_mpz(e, e, q); element_init(p->xpowq2, p->Fqd); element_square(p->xpowq2, e); } else { mpz_init(p->tateexp); mpz_sub_ui(p->tateexp, p->Fqk->order, 1); mpz_divexact(p->tateexp, p->tateexp, pairing->r); } field_init_curve_ab_map(p->Etwist, p->Eq, element_field_to_polymod, p->Fqd, pairing->r, NULL); field_reinit_curve_twist(p->Etwist); mpz_t ndonr; mpz_init(ndonr); // ndonr temporarily holds the trace. mpz_sub(ndonr, param->q, param->n); mpz_add_ui(ndonr, ndonr, 1); // Negate it because we want the trace of the twist. mpz_neg(ndonr, ndonr); pbc_mpz_curve_order_extn(ndonr, param->q, ndonr, d); mpz_divexact(ndonr, ndonr, param->r); field_curve_set_quotient_cmp(p->Etwist, ndonr); mpz_clear(ndonr); element_init(p->nqrinv, p->Fqd); element_invert(p->nqrinv, field_get_nqr(p->Fqd)); element_init(p->nqrinv2, p->Fqd); element_square(p->nqrinv2, p->nqrinv); pairing->G1 = p->Eq; pairing->G2 = p->Etwist; p->k = param->k; pairing_GT_init(pairing, p->Fqk); pairing->finalpow = cc_finalpow; // By default use affine coordinates. cc_miller_no_denom_fn = cc_miller_no_denom_affine; pairing->option_set = d_pairing_option_set; pairing->pp_init = d_pairing_pp_init; pairing->pp_clear = d_pairing_pp_clear; pairing->pp_apply = d_pairing_pp_apply; pairing->clear_func = d_pairing_clear; element_clear(a); element_clear(b); }
// Computes a curve and sets fp to the field it is defined over using the // complex multiplication method, where cm holds the appropriate information // (e.g. discriminant, field order). static void compute_cm_curve(d_param_ptr param, pbc_cm_ptr cm) { element_t hp, root; field_t fp, fpx; field_t cc; field_init_fp(fp, cm->q); field_init_poly(fpx, fp); element_init(hp, fpx); mpz_t *coefflist; int n = (int)pbc_hilbert(&coefflist, cm->D); // Temporarily set the coefficient of x^{n-1} to 1 so hp has degree n - 1, // allowing us to use poly_coeff(). poly_set_coeff1(hp, n - 1); int i; for (i = 0; i < n; i++) { element_set_mpz(element_item(hp, i), coefflist[i]); } pbc_hilbert_free(coefflist, n); // TODO: Remove x = 0, 1728 roots. // TODO: What if there are no roots? //printf("hp "); //element_out_str(stdout, 0, hp); //printf("\n"); element_init(root, fp); poly_findroot(root, hp); //printf("root = "); //element_out_str(stdout, 0, root); //printf("\n"); element_clear(hp); field_clear(fpx); // The root is the j-invariant of the desired curve. field_init_curve_j(cc, root, cm->n, NULL); element_clear(root); // We may need to twist it. { // Pick a random point P and twist the curve if it has the wrong order. element_t P; element_init(P, cc); element_random(P); element_mul_mpz(P, P, cm->n); if (!element_is0(P)) field_reinit_curve_twist(cc); element_clear(P); } mpz_set(param->q, cm->q); mpz_set(param->n, cm->n); mpz_set(param->h, cm->h); mpz_set(param->r, cm->r); element_to_mpz(param->a, curve_field_a_coeff(cc)); element_to_mpz(param->b, curve_field_b_coeff(cc)); param->k = cm->k; { mpz_t z; mpz_init(z); // Compute order of curve in F_q^k. // n = q - t + 1 hence t = q - n + 1 mpz_sub(z, param->q, param->n); mpz_add_ui(z, z, 1); pbc_mpz_trace_n(z, param->q, z, param->k); mpz_pow_ui(param->nk, param->q, param->k); mpz_sub_ui(z, z, 1); mpz_sub(param->nk, param->nk, z); mpz_mul(z, param->r, param->r); mpz_divexact(param->hk, param->nk, z); mpz_clear(z); } field_clear(cc); field_clear(fp); }