static int fi_is_sqr(element_ptr e) { // x + yi is a square <=> x^2 + y^2 is (in the base field). // Proof: (=>) if x+yi = (a+bi)^2, then a^2 - b^2 = x, 2ab = y, // thus (a^2 + b^2)^2 = (a^2 - b^2)^2 + (2ab)^2 = x^2 + y^2 // (<=) Suppose A^2 = x^2 + y^2. If there exist a, b satisfying: // a^2 = (+-A + x)/2, b^2 = (+-A - x)/2 // then (a + bi)^2 = x + yi. // // We show that exactly one of (A + x)/2, (-A + x)/2 is a quadratic residue // (thus a, b do exist). Suppose not. Then the product (x^2 - A^2) / 4 is // some quadratic residue, a contradiction since this would imply x^2 - A^2 = // -y^2 is also a quadratic residue, but we know -1 is not a quadratic // residue. QED. eptr p = e->data; element_t e0, e1; int result; element_init(e0, p->x->field); element_init(e1, e0->field); element_square(e0, p->x); element_square(e1, p->y); element_add(e0, e0, e1); result = element_is_sqr(e0); element_clear(e0); element_clear(e1); return result; }
static void fi_sqrt(element_ptr n, element_ptr e) { eptr p = e->data; eptr r = n->data; element_t e0, e1, e2; // If (a+bi)^2 = x+yi then 2a^2 = x +- sqrt(x^2 + y^2) // where we choose the sign so that a exists, and 2ab = y. // Thus 2b^2 = - (x -+ sqrt(x^2 + y^2)). element_init(e0, p->x->field); element_init(e1, e0->field); element_init(e2, e0->field); element_square(e0, p->x); element_square(e1, p->y); element_add(e0, e0, e1); element_sqrt(e0, e0); // e0 = sqrt(x^2 + y^2) element_add(e1, p->x, e0); element_set_si(e2, 2); element_invert(e2, e2); element_mul(e1, e1, e2); // e1 = (x + sqrt(x^2 + y^2))/2 if (!element_is_sqr(e1)) { element_sub(e1, e1, e0); // e1 should be a square. } element_sqrt(e0, e1); element_add(e1, e0, e0); element_invert(e1, e1); element_mul(r->y, p->y, e1); element_set(r->x, e0); element_clear(e0); element_clear(e1); element_clear(e2); }
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); }
//-------------------------------------------------- // square root in extended Fp //-------------------------------------------------- int bn254_fp2_sqrt(Element z, const Element x) { mpz_t _v; int m, r, i; field_precomp_sqrt_p ps; Element *t = field(z)->tmp; if (!element_is_sqr(x)) { return FALSE; } ps = ((field_precomp_p)(field(x)->precomp))->ps; element_set(t[0], ps->n_v); // t0 = n^v r = ps->e; // r = e mpz_init_set(_v, ps->v); mpz_sub_ui(_v, _v, 1); mpz_tdiv_q_2exp(_v, _v, 1); element_pow(t[1], x, _v); // t1 = x^{(v-1)/2} element_sqr(t[2], t[1]); element_mul(t[2], t[2], x); // t2 = x*t1^2 element_mul(t[1], x, t[1]); // t1 = x*t1 mpz_clear(_v); while (!element_is_one(t[2])) { m = 0; element_set(t[3], t[2]); do { element_sqr(t[3], t[3]); m++; } while (!element_is_one(t[3]) && m < r); r = r - m - 1; element_set(t[3], t[0]); for (i = 1; i <= r; i++) { element_sqr(t[3], t[3]); } // t3 = t2^{r-m-1} element_sqr(t[0], t[3]); // t0 = t3^2 r = m; element_mul(t[1], t[1], t[3]);// t1 = t1*t3 element_mul(t[2], t[2], t[0]);// t2 = t2*t0 } element_set(z, t[1]); return TRUE; }
//============================================ // 平方根計算のテスト //============================================ void test_sqrt(Field f) { int i; unsigned long long int t1, t2; Element a, b, c, d; element_init(a, f); element_init(b, f); element_init(c, f); element_init(d, f); for (i = 0; i < 50; i++) { element_random(a); element_sqr(b, a); assert(element_is_sqr(b)); element_sqrt(c, b); element_sqr(d, c); assert(element_cmp(d, b) == 0); } t1 = rdtsc(); for (i = 0; i < N; i++) { element_is_sqr(b); } t2 = rdtsc(); printf("element is sqr: %.2lf [clock]\n", (double)(t2 - t1) / N); t1 = rdtsc(); for (i = 0; i < M; i++) { element_sqrt(c, b); } t2 = rdtsc(); printf("element sqrt: %.2lf [clock]\n", (double)(t2 - t1) / M); element_clear(a); element_clear(b); element_clear(c); element_clear(d); }
static int fq_is_sqr(element_ptr e) { //x + y sqrt(nqr) is a square iff x^2 - nqr y^2 is (in the base field) eptr p = e->data; element_t e0, e1; element_ptr nqr = fq_nqr(e->field); int result; element_init(e0, p->x->field); element_init(e1, e0->field); element_square(e0, p->x); element_square(e1, p->y); element_mul(e1, e1, nqr); element_sub(e0, e0, e1); result = element_is_sqr(e0); element_clear(e0); element_clear(e1); return result; }
//singular with node: y^2 = x^3 + x^2 static void sn_random(element_t a) { point_ptr p = a->data; element_t t; element_init(t, p->x->field); p->inf_flag = 0; do { element_random(p->x); if (element_is0(p->x)) continue; element_square(t, p->x); element_add(t, t, p->x); element_mul(t, t, p->x); } while (!element_is_sqr(t)); element_sqrt(p->y, t); element_clear(t); }
static void curve_random_no_cofac_solvefory(element_ptr a) { //TODO: with 0.5 probability negate y-coord curve_data_ptr cdp = (curve_data_ptr)a->field->data; point_ptr p = (point_ptr)a->data; element_t t; element_init(t, cdp->field); p->inf_flag = 0; do { element_random(p->x); element_square(t, p->x); element_add(t, t, cdp->a); element_mul(t, t, p->x); element_add(t, t, cdp->b); } while (!element_is_sqr(t)); element_sqrt(p->y, t); element_clear(t); }
//--------------------------------------------------------- // precomputation for sqrt //--------------------------------------------------------- void bn254_fp2_precomp_sqrt(field_precomp_sqrt_p ps, const Field f) { //----------------------------- // decompose of value // (p^2-1) = 2^e * v //----------------------------- mpz_init_set(ps->v, f->order); mpz_sub_ui(ps->v, ps->v, 1); ps->e = (int)mpz_scan1(ps->v, 0); mpz_fdiv_q_2exp(ps->v, ps->v, ps->e); //---------------------------------- // n_v = n^v : // n is some integer (n/p) = -1 //---------------------------------- element_init(ps->n_v, f); do { element_random(ps->n_v); } while (element_is_sqr(ps->n_v)); element_pow(ps->n_v, ps->n_v, ps->v); }
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 fq_sqrt(element_ptr n, element_ptr e) { eptr p = e->data; eptr r = n->data; element_ptr nqr = fq_nqr(n->field); element_t e0, e1, e2; //if (a+b sqrt(nqr))^2 = x+y sqrt(nqr) then //2a^2 = x +- sqrt(x^2 - nqr y^2) //(take the sign which allows a to exist) //and 2ab = y element_init(e0, p->x->field); element_init(e1, e0->field); element_init(e2, e0->field); element_square(e0, p->x); element_square(e1, p->y); element_mul(e1, e1, nqr); element_sub(e0, e0, e1); element_sqrt(e0, e0); //e0 = sqrt(x^2 - nqr y^2) element_add(e1, p->x, e0); element_set_si(e2, 2); element_invert(e2, e2); element_mul(e1, e1, e2); //e1 = (x + sqrt(x^2 - nqr y^2))/2 if (!element_is_sqr(e1)) { element_sub(e1, e1, e0); //e1 should be a square } element_sqrt(e0, e1); element_add(e1, e0, e0); element_invert(e1, e1); element_mul(r->y, p->y, e1); element_set(r->x, e0); element_clear(e0); element_clear(e1); element_clear(e2); }