Exemplo n.º 1
0
static val_ptr v_field_cast(val_ptr v, tree_ptr t) {
	// TODO: Check args, x is an element.
	val_ptr x = tree_eval((tree_ptr)darray_at(t->child, 0));
	element_ptr e = x->elem;
	if (e->field == M) {
		if (v->field == M) return x;
		element_ptr e2 = element_new(v->field);
		if (element_is0(e)) // if 'set0' is not 'set1' in base field of GT, but we hope 'GT(0)' calls 'set1', we may directly call 'element_set0' here
			element_set0(e2);
		else if (element_is1(e)) // reason is same as above
			element_set1(e2);
		else
			element_set_multiz(e2, (multiz)e->data);
		x->elem = e2;
		return x;
	}
	if (v->field == M) {
		// Map to/from integer. TODO: Map to/from multiz instead.
		mpz_t z;
		mpz_init(z);
		element_to_mpz(z, e);
		element_clear(e);
		element_init(e, v->field);
		element_set_mpz(e, z);
		mpz_clear(z);
	}
	return x;
}
Exemplo n.º 2
0
static val_ptr run_nextprime(val_ptr v[]) {
	element_ptr e = v[0]->elem;
	mpz_t z;
	mpz_init(z);
	element_to_mpz(z, e);
	mpz_nextprime(z, z);
	element_set_mpz(e, z);
	return v[0];
}
Exemplo n.º 3
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);
}
Exemplo n.º 4
0
static val_ptr run_item(val_ptr v[]) {
	mpz_t z;
	mpz_init(z);
	element_to_mpz(z, v[1]->elem);
	int i = mpz_get_si(z);
	mpz_clear(z);
	element_ptr a = element_item(v[0]->elem, i);
	element_ptr e = (element_ptr)pbc_malloc(sizeof(*e));
	element_init_same_as(e, a);
	element_set(e, a);
	return val_new_element(e);
}
Exemplo n.º 5
0
Arquivo: d_param.c Projeto: blynn/pbc
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);
}
Exemplo n.º 6
0
Arquivo: pbc.c Projeto: n0htyp/ABBE
static val_ptr v_field_cast(val_ptr v, tree_ptr t) {
  // TODO: Check args, x is an element.
  val_ptr x = tree_eval(darray_at(t->child, 0));
  element_ptr e = x->elem;
  if (e->field == M) {
    if (v->field == M) return x;
    element_ptr e2 = element_new(v->field);
    element_set_multiz(e2, e->data);
    x->elem = e2;
    return x;
  }
  if (v->field == M) {
    // Map to/from integer. TODO: Map to/from multiz instead.
    mpz_t z;
    mpz_init(z);
    element_to_mpz(z, e);
    element_clear(e);
    element_init(e, v->field);
    element_set_mpz(e, z);
    mpz_clear(z);
  }
  return x;
}
Exemplo n.º 7
0
// x in Z_r, g, h in some group of order r
// finds x such that g^x = h
void element_dlog_pollard_rho(element_t x, element_t g, element_t h) {
// see Blake, Seroussi and Smart
// only one snark for this implementation
  int i, s = 20;
  field_ptr Zr = x->field, G = g->field;
  element_t asum;
  element_t bsum;
  element_t a[s];
  element_t b[s];
  element_t m[s];
  element_t g0, snark;
  darray_t hole;
  int interval = 5;
  mpz_t counter;
  int found = 0;

  mpz_init(counter);
  element_init(g0, G);
  element_init(snark, G);
  element_init(asum, Zr);
  element_init(bsum, Zr);
  darray_init(hole);
  //set up multipliers
  for (i = 0; i < s; i++) {
    element_init(a[i], Zr);
    element_init(b[i], Zr);
    element_init(m[i], G);
    element_random(a[i]);
    element_random(b[i]);
    element_pow_zn(g0, g, a[i]);
    element_pow_zn(m[i], h, b[i]);
    element_mul(m[i], m[i], g0);
  }

  element_random(asum);
  element_random(bsum);
  element_pow_zn(g0, g, asum);
  element_pow_zn(snark, h, bsum);
  element_mul(snark, snark, g0);

  record(asum, bsum, snark, hole, counter);
  for (;;) {
    int len = element_length_in_bytes(snark);
    unsigned char *buf = pbc_malloc(len);
    unsigned char hash = 0;

    element_to_bytes(buf, snark);
    for (i = 0; i < len; i++) {
      hash += buf[i];
    }
    i = hash % s;
    pbc_free(buf);

    element_mul(snark, snark, m[i]);
    element_add(asum, asum, a[i]);
    element_add(bsum, bsum, b[i]);

    for (i = 0; i < hole->count; i++) {
      snapshot_ptr ss = hole->item[i];
      if (!element_cmp(snark, ss->snark)) {
        element_sub(bsum, bsum, ss->b);
        element_sub(asum, ss->a, asum);
        //answer is x such that x * bsum = asum
        //complications arise if gcd(bsum, r) > 1
        //which can happen if r is not prime
        if (!mpz_probab_prime_p(Zr->order, 10)) {
          mpz_t za, zb, zd, zm;

          mpz_init(za);
          mpz_init(zb);
          mpz_init(zd);
          mpz_init(zm);

          element_to_mpz(za, asum);
          element_to_mpz(zb, bsum);
          mpz_gcd(zd, zb, Zr->order);
          mpz_divexact(zm, Zr->order, zd);
          mpz_divexact(zb, zb, zd);
          //if zd does not divide za there is no solution
          mpz_divexact(za, za, zd);
          mpz_invert(zb, zb, zm);
          mpz_mul(zb, za, zb);
          mpz_mod(zb, zb, zm);
          do {
            element_pow_mpz(g0, g, zb);
            if (!element_cmp(g0, h)) {
              element_set_mpz(x, zb);
              break;
            }
            mpz_add(zb, zb, zm);
            mpz_sub_ui(zd, zd, 1);
          } while (mpz_sgn(zd));
          mpz_clear(zm);
          mpz_clear(za);
          mpz_clear(zb);
          mpz_clear(zd);
        } else {
          element_div(x, asum, bsum);
        }
        found = 1;
        break;
      }
    }
    if (found) break;

    mpz_add_ui(counter, counter, 1);
    if (mpz_tstbit(counter, interval)) {
      record(asum, bsum, snark, hole, counter);
      interval++;
    }
  }

  for (i = 0; i < s; i++) {
    element_clear(a[i]);
    element_clear(b[i]);
    element_clear(m[i]);
  }
  element_clear(g0);
  element_clear(snark);
  for (i = 0; i < hole->count; i++) {
    snapshot_ptr ss = hole->item[i];
    element_clear(ss->a);
    element_clear(ss->b);
    element_clear(ss->snark);
    pbc_free(ss);
  }
  darray_clear(hole);
  element_clear(asum);
  element_clear(bsum);
  mpz_clear(counter);
}
Exemplo n.º 8
0
// USER JOIN PHASE 1 - user key generation (Join)
void xsgs_user_join_phase1(XSGS_PUBLIC_KEY* gpk, XSGS_USER_KEY* uk,
		XSGS_PAILLIER_PUBKEY* ppk, XSGS_JOIN_PHASE1* jpd1) {
	pairing_ptr pairing = gpk->pairing;
	field_ptr Fp = pairing->Zr;
	gmp_randstate_t rnd_state;
	mpz_t y, r, R1, h;
	element_t R2;

	// 1.choose y e Zp at random and
	element_init(uk->y, Fp);
	element_random(uk->y);
	// compute C <- H^y
	element_init_G1(jpd1->C, pairing);
	element_pow_naf(jpd1->C, gpk->H, uk->y);

	// 2. U = (c=ext-commit(y), NIZKPEqDL(c, C, H))
	// c = ext-commit(y) = g^y mod n^2
	mpz_init(y);
	mpz_init(jpd1->U.c);

	element_to_mpz(y, uk->y);
	mpz_powm(jpd1->U.c, ppk->g, y, ppk->n_squared);

	// zero-knowledge proof of c, C and H
	init_rand(rnd_state, PAILLIER_MODULO_BITS / 8 + 1);
	mpz_init(r);
	mpz_urandomb(r, rnd_state, PAILLIER_MODULO_BITS);
	gmp_randclear(rnd_state);

	// R1 = g^r mod n^2
	mpz_init(R1);
	mpz_powm(R1, ppk->g, r, ppk->n_squared);

	// R2 = H^r
	element_init_G1(R2, pairing);
	element_pow_naf_mpz(R2, gpk->H, r);

	// h = H(g, n, c, C, H, R1, R2)
	DWORD data_len = mpz_length_in_bytes(ppk->g)
			+ mpz_length_in_bytes(ppk->n_squared)
			+
			//mpz_length_in_bytes(ppk->n) +
			mpz_length_in_bytes(jpd1->U.c) + element_length_in_bytes(jpd1->C)
			+ element_length_in_bytes(gpk->H) + mpz_length_in_bytes(R1)
			+ element_length_in_bytes(R2);

	BYTE* data_buf = (BYTE*) malloc(data_len);

	data_buf += mpz_to_bytes(data_buf, ppk->g);
	data_buf += mpz_to_bytes(data_buf, ppk->n_squared);
	//data_buf += mpz_to_bytes(data_buf, ppk->n);
	data_buf += mpz_to_bytes(data_buf, jpd1->U.c);
	data_buf += element_to_bytes(data_buf, jpd1->C);
	data_buf += element_to_bytes(data_buf, gpk->H);
	data_buf += mpz_to_bytes(data_buf, R1);
	data_buf += element_to_bytes(data_buf, R2);
	data_buf -= data_len;

	jpd1->U.hash = (BYTE*) malloc(JOIN_HASH_BITS / 8);
	xsgs_hash(data_buf, data_len * 8, jpd1->U.hash, JOIN_HASH_BITS);

	free(data_buf);
	mpz_clear(R1);
	element_clear(R2);

	// s = r - h * y
	mpz_init(h);
	mpz_init(jpd1->U.s);
	mpz_from_hash(h, jpd1->U.hash, JOIN_HASH_BITS / 8);
	mpz_mul(jpd1->U.s, h, y);
	mpz_sub(jpd1->U.s, r, jpd1->U.s);

	mpz_clear(r);
	mpz_clear(y);
	mpz_clear(h);

	// return ( paillier = (pub, prv), C, U = (c, h, s) )
	return;
}
Exemplo n.º 9
0
// Projection: attempts to convert Re(e) to mpz.
static void fq_to_mpz(mpz_t z, element_ptr e) {
  eptr p = e->data;
  element_to_mpz(z, p->x);
}
Exemplo n.º 10
0
static void mulg_to_mpz(mpz_ptr z, element_ptr e) {
  element_to_mpz(z, e->data);
}
Exemplo n.º 11
0
static val_ptr run_exit(val_ptr v[]) {
	mpz_t z;
	mpz_init(z);
	element_to_mpz(z, v[0]->elem);
	exit(mpz_get_si(z));
}
Exemplo n.º 12
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;
}
Exemplo n.º 13
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);
}
Exemplo n.º 14
0
Arquivo: f_param.c Projeto: blynn/pbc
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);
}
Exemplo n.º 15
0
int main(int argc, char **argv) {
  pairing_t pairing;
  element_t g1, u1, up1, g2, u2, up2, r;
  mpz_t r_mpz;
  element_pp_t g1_pp, g2_pp;
  double t0, t1;
  int i, n;

  printf("reading pairing from stdin...\n");
  pbc_demo_pairing_init(pairing, argc, argv);

  element_init(r, pairing->Zr);
  element_init(g1, pairing->G1);
  element_init(u1, pairing->G1);
  element_init(up1, pairing->G1);
  element_init(g2, pairing->G2);
  element_init(u2, pairing->G2);
  element_init(up2, pairing->G2);

  element_random(r);
  element_random(g1);
  element_random(g2);

  mpz_init(r_mpz);
  element_to_mpz(r_mpz, r);

  element_pp_init(g1_pp, g1);
  element_pp_init(g2_pp, g2);

  n = 100;
  t0 = pbc_get_time();
  for (i=0; i<n; i++) {
    element_pow_mpz(u1, g1, r_mpz);
  }
  t1 = pbc_get_time();
  printf("G1 exp:\t\t%fs\n", t1 - t0);

  n = 100;
  t0 = pbc_get_time();
  for (i=0; i<n; i++) {
    element_pow_mpz(u2, g2, r_mpz);
  }
  t1 = pbc_get_time();
  printf("G2 exp:\t\t%fs\n", t1 - t0);

  n = 100;
  t0 = pbc_get_time();
  for (i=0; i<n; i++) {
    element_pp_pow(up1, r_mpz, g1_pp);
  }
  t1 = pbc_get_time();
  printf("G1 pp exp:\t%fs\n", t1 - t0);

  n = 100;
  t0 = pbc_get_time();
  for (i=0; i<n; i++) {
    element_pp_pow(up2, r_mpz, g2_pp);
  }
  t1 = pbc_get_time();
  printf("G2 pp exp:\t%fs\n", t1 - t0);

  if (element_cmp(u1, up1)) {
    printf("Oops 1!\n");
  }
  if (element_cmp(u2, up2)) {
    printf("Oops 2!\n");
  }

  mpz_clear(r_mpz);
  element_clear(g1);
  element_clear(u1);
  element_clear(up1);
  element_clear(g2);
  element_clear(u2);
  element_clear(up2);
  element_clear(r);
  element_pp_clear(g1_pp);
  element_pp_clear(g2_pp);
  pairing_clear(pairing);

  return 0;
}
Exemplo n.º 16
0
Arquivo: d_param.c Projeto: blynn/pbc
// 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);
}