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 void curve_from_hash(element_t a, void *data, int len) { element_t t, t1; point_ptr p = (point_ptr)a->data; curve_data_ptr cdp = (curve_data_ptr)a->field->data; element_init(t, cdp->field); element_init(t1, cdp->field); p->inf_flag = 0; element_from_hash(p->x, data, len); for(;;) { element_square(t, p->x); element_add(t, t, cdp->a); element_mul(t, t, p->x); element_add(t, t, cdp->b); if (element_is_sqr(t)) break; // Compute x <- x^2 + 1 and try again. element_square(p->x, p->x); element_set1(t); element_add(p->x, p->x, t); } element_sqrt(p->y, t); if (element_sgn(p->y) < 0) element_neg(p->y, p->y); if (cdp->cofac) element_mul_mpz(a, a, cdp->cofac); element_clear(t); element_clear(t1); }
static void curve_random_pointmul(element_ptr a) { curve_data_ptr cdp = (curve_data_ptr)a->field->data; mpz_t x; mpz_init(x); pbc_mpz_random(x, a->field->order); element_mul_mpz(a, cdp->gen, x); mpz_clear(x); }
// 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); } }
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; }
static void fq_mul_mpz(element_ptr n, element_ptr a, mpz_ptr z) { eptr p = a->data; eptr r = n->data; element_mul_mpz(r->x, p->x, z); element_mul_mpz(r->y, p->y, z); }
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); }
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); }
void field_init_curve_ab(field_ptr f, element_ptr a, element_ptr b, mpz_t order, mpz_t cofac) { /* if (element_is0(a)) { c->double_nocheck = cc_double_no_check_ais0; } else { c->double_nocheck = cc_double_no_check; } */ curve_data_ptr cdp; field_init(f); mpz_set(f->order, order); f->data = pbc_malloc(sizeof(*cdp)); cdp = (curve_data_ptr)f->data; cdp->field = a->field; element_init(cdp->a, cdp->field); element_init(cdp->b, cdp->field); element_set(cdp->a, a); element_set(cdp->b, b); f->init = curve_init; f->clear = curve_clear; f->neg = f->invert = curve_invert; f->square = f->doub = curve_double; f->multi_doub = multi_double; f->add = f->mul = curve_mul; f->multi_add = multi_add; f->mul_mpz = element_pow_mpz; f->cmp = curve_cmp; f->set0 = f->set1 = curve_set1; f->is0 = f->is1 = curve_is1; f->sign = curve_sign; f->set = curve_set; f->random = curve_random_pointmul; //f->random = curve_random_solvefory; f->from_hash = curve_from_hash; f->out_str = curve_out_str; f->snprint = curve_snprint; f->set_multiz = curve_set_multiz; f->set_str = curve_set_str; f->field_clear = field_clear_curve; if (cdp->field->fixed_length_in_bytes < 0) { f->length_in_bytes = curve_length_in_bytes; } else { f->fixed_length_in_bytes = 2 * cdp->field->fixed_length_in_bytes; } f->to_bytes = curve_to_bytes; f->from_bytes = curve_from_bytes; f->out_info = curve_out_info; f->item_count = curve_item_count; f->item = curve_item; f->get_x = curve_get_x; f->get_y = curve_get_y; if (mpz_odd_p(order)) { f->is_sqr = odd_curve_is_sqr; } else { f->is_sqr = even_curve_is_sqr; } element_init(cdp->gen_no_cofac, f); element_init(cdp->gen, f); curve_random_no_cofac_solvefory(cdp->gen_no_cofac); if (cofac) { cdp->cofac = (mpz_ptr)pbc_malloc(sizeof(mpz_t)); mpz_init(cdp->cofac); mpz_set(cdp->cofac, cofac); element_mul_mpz(cdp->gen, cdp->gen_no_cofac, cofac); } else{ cdp->cofac = NULL; element_set(cdp->gen, cdp->gen_no_cofac); } cdp->quotient_cmp = NULL; }
static void curve_random_solvefory(element_ptr a) { curve_data_ptr cdp = (curve_data_ptr)a->field->data; curve_random_no_cofac_solvefory(a); if (cdp->cofac) element_mul_mpz(a, a, cdp->cofac); }
// 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); }