// Existing points are invalidated as this mangles c. void field_reinit_curve_twist(field_ptr c) { curve_data_ptr cdp = (curve_data_ptr)c->data; element_ptr nqr = field_get_nqr(cdp->field); element_mul(cdp->a, cdp->a, nqr); element_mul(cdp->a, cdp->a, nqr); element_mul(cdp->b, cdp->b, nqr); element_mul(cdp->b, cdp->b, nqr); element_mul(cdp->b, cdp->b, nqr); // Recompute generators. curve_random_no_cofac_solvefory(cdp->gen_no_cofac); if (cdp->cofac) { element_mul_mpz(cdp->gen, cdp->gen_no_cofac, cdp->cofac); } else{ element_set(cdp->gen, cdp->gen_no_cofac); } }
// Return the quadratic nonresidue used to build this field. // Should only be called from routines used exclusively by the generic quadratic // extension code. static inline element_ptr fq_nqr(field_ptr f) { return field_get_nqr((field_ptr) f->data); }
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 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); }