static void e_miller_proj(element_t res, element_t P, element_ptr QR, element_ptr R, e_pairing_data_ptr p) { //collate divisions int n; element_t v, vd; element_t v1, vd1; element_t Z, Z1; element_t a, b, c; const element_ptr cca = curve_a_coeff(P); element_t e0, e1; const element_ptr e2 = a, e3 = b; element_t z, z2; int i; element_ptr Zx, Zy; const element_ptr Px = curve_x_coord(P); const element_ptr numx = curve_x_coord(QR); const element_ptr numy = curve_y_coord(QR); const element_ptr denomx = curve_x_coord(R); const element_ptr denomy = curve_y_coord(R); //convert Z from weighted projective (Jacobian) to affine //i.e. (X, Y, Z) --> (X/Z^2, Y/Z^3) //also sets z to 1 void to_affine(void) { element_invert(z, z); element_square(e0, z); element_mul(Zx, Zx, e0); element_mul(e0, e0, z); element_mul(Zy, Zy, e0); element_set1(z); element_set1(z2); }
void miller(element_t res, mpz_t q, element_t P, element_ptr Qx, element_ptr Qy) { int m; element_t v; element_t Z; element_t a, b, c; element_t t0; element_t e0; const element_ptr cca = curve_a_coeff(P); const element_ptr Px = curve_x_coord(P); const element_ptr Py = curve_y_coord(P); element_ptr Zx, Zy; void do_tangent(void) { // a = -(3 Zx^2 + cc->a) // b = 2 * Zy // c = -(2 Zy^2 + a Zx); element_square(a, Zx); mult1++; element_mul_si(a, a, 3); add1++; add1++; add1++; element_add(a, a, cca); add1++; element_neg(a, a); element_add(b, Zy, Zy); add1++; element_mul(t0, b, Zy); mult1++; element_mul(c, a, Zx); mult1++; element_add(c, c, t0); add1++; element_neg(c, c); d_miller_evalfn(e0, a, b, c, Qx, Qy); element_mul(v, v, e0); multk++; }
static void miller(element_t res, element_t P, element_ptr QR, element_ptr R, int n) { // Collate divisions. mp_bitcnt_t m; element_t v, vd; element_t Z; element_t a, b, c; const element_ptr cca = curve_a_coeff(P); const element_ptr Px = curve_x_coord(P); const element_ptr Py = curve_y_coord(P); element_t e0, e1; mpz_t q; element_ptr Zx, Zy; const element_ptr numx = curve_x_coord(QR); const element_ptr numy = curve_y_coord(QR); const element_ptr denomx = curve_x_coord(R); const element_ptr denomy = curve_y_coord(R); #define do_vertical(e, edenom) { \ element_sub(e0, numx, Zx); \ element_mul((e), (e), e0); \ \ element_sub(e0, denomx, Zx); \ element_mul((edenom), (edenom), e0); \ } #define do_tangent(e, edenom) { \ /*a = -slope_tangent(A.x, A.y); \ b = 1; \ c = -(A.y + a * A.x); \ but we multiply by 2*A.y to avoid division*/ \ \ /*a = -Ax * (Ax + Ax + Ax + twicea_2) - a_4; \ Common curves: a2 = 0 (and cc->a is a_4), so \ a = -(3 Ax^2 + cc->a) \ b = 2 * Ay \ c = -(2 Ay^2 + a Ax); */ \ \ if (element_is0(Zy)) { \ do_vertical((e), (edenom)); \ } else { \ element_square(a, Zx); \ element_mul_si(a, a, 3); \ element_add(a, a, cca); \ element_neg(a, a); \ \ element_add(b, Zy, Zy); \ \ element_mul(e0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, e0); \ element_neg(c, c); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul((e), (e), e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul((edenom), (edenom), e0); \ } \ } #define do_line(e, edenom) { \ if (!element_cmp(Zx, Px)) { \ if (!element_cmp(Zy, Py)) { \ do_tangent(e, edenom); \ } else { \ do_vertical(e, edenom); \ } \ } else { \ element_sub(b, Px, Zx); \ element_sub(a, Zy, Py); \ element_mul(c, Zx, Py); \ element_mul(e0, Zy, Px); \ element_sub(c, c, e0); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(e, e, e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(edenom, edenom, e0); \ } \ } element_init(a, res->field); element_init(b, res->field); element_init(c, res->field); element_init(e0, res->field); element_init(e1, res->field); element_init(v, res->field); element_init(vd, res->field); element_init(Z, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_y_coord(Z); element_set1(v); element_set1(vd); mpz_init(q); mpz_set_ui(q, n); m = (mp_bitcnt_t)mpz_sizeinbase(q, 2); m = (m > 2 ? m - 2 : 0); for (;;) { element_square(v, v); element_square(vd, vd); do_tangent(v, vd); element_double(Z, Z); do_vertical(vd, v); if (mpz_tstbit(q, m)) { do_line(v, vd); element_add(Z, Z, P); if (m) { do_vertical(vd, v); } } if (!m) break; m--; } mpz_clear(q); element_invert(vd, vd); element_mul(res, v, vd); element_clear(v); element_clear(vd); element_clear(Z); element_clear(a); element_clear(b); element_clear(c); element_clear(e0); element_clear(e1); #undef do_vertical #undef do_tangent #undef do_line }
static void e_miller_proj(element_t res, element_t P, element_ptr QR, element_ptr R, e_pairing_data_ptr p) { //collate divisions int n; element_t v, vd; element_t v1, vd1; element_t Z, Z1; element_t a, b, c; const element_ptr cca = curve_a_coeff(P); element_t e0, e1; const element_ptr e2 = a, e3 = b; element_t z, z2; int i; element_ptr Zx, Zy; const element_ptr Px = curve_x_coord(P); const element_ptr numx = curve_x_coord(QR); const element_ptr numy = curve_y_coord(QR); const element_ptr denomx = curve_x_coord(R); const element_ptr denomy = curve_y_coord(R); //convert Z from weighted projective (Jacobian) to affine //i.e. (X, Y, Z) --> (X/Z^2, Y/Z^3) //also sets z to 1 #define to_affine() { \ element_invert(z, z); \ element_square(e0, z); \ element_mul(Zx, Zx, e0); \ element_mul(e0, e0, z); \ element_mul(Zy, Zy, e0); \ element_set1(z); \ element_set1(z2); \ } #define proj_double() { \ const element_ptr x = Zx; \ const element_ptr y = Zy; \ /* e0 = 3x^2 + (cc->a) z^4 */ \ element_square(e0, x); \ /* element_mul_si(e0, e0, 3); */ \ element_double(e1, e0); \ element_add(e0, e0, e1); \ element_square(e1, z2); \ element_mul(e1, e1, cca); \ element_add(e0, e0, e1); \ \ /* z_out = 2 y z */ \ element_mul(z, y, z); \ /* element_mul_si(z, z, 2); */ \ element_double(z, z); \ element_square(z2, z); \ \ /* e1 = 4 x y^2 */ \ element_square(e2, y); \ element_mul(e1, x, e2); \ /* element_mul_si(e1, e1, 4); */ \ element_double(e1, e1); \ element_double(e1, e1); \ \ /* x_out = e0^2 - 2 e1 */ \ /* element_mul_si(e3, e1, 2); */ \ element_double(e3, e1); \ element_square(x, e0); \ element_sub(x, x, e3); \ \ /* e2 = 8y^4 */ \ element_square(e2, e2); \ /* element_mul_si(e2, e2, 8); */ \ element_double(e2, e2); \ element_double(e2, e2); \ element_double(e2, e2); \ \ /* y_out = e0(e1 - x_out) - e2 */ \ element_sub(e1, e1, x); \ element_mul(e0, e0, e1); \ element_sub(y, e0, e2); \ } #define do_tangent(e, edenom) { \ /* a = -(3x^2 + cca z^4) */ \ /* b = 2 y z^3 */ \ /* c = -(2 y^2 + x a) */ \ /* a = z^2 a */ \ element_square(a, z2); \ element_mul(a, a, cca); \ element_square(b, Zx); \ /* element_mul_si(b, b, 3); */ \ element_double(e0, b); \ element_add(b, b, e0); \ element_add(a, a, b); \ element_neg(a, a); \ \ /* element_mul_si(e0, Zy, 2); */ \ element_double(e0, Zy); \ element_mul(b, e0, z2); \ element_mul(b, b, z); \ \ element_mul(c, Zx, a); \ element_mul(a, a, z2); \ element_mul(e0, e0, Zy); \ element_add(c, c, e0); \ element_neg(c, c); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(e, e, e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(edenom, edenom, e0); \ } #define do_vertical(e, edenom, Ax) { \ element_mul(e0, numx, z2); \ element_sub(e0, e0, Ax); \ element_mul(e, e, e0); \ \ element_mul(e0, denomx, z2); \ element_sub(e0, e0, Ax); \ element_mul(edenom, edenom, e0); \ } #define do_line(e, edenom, A, B) { \ element_ptr Ax = curve_x_coord(A); \ element_ptr Ay = curve_y_coord(A); \ element_ptr Bx = curve_x_coord(B); \ element_ptr By = curve_y_coord(B); \ \ element_sub(b, Bx, Ax); \ element_sub(a, Ay, By); \ element_mul(c, Ax, By); \ element_mul(e0, Ay, Bx); \ element_sub(c, c, e0); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(e, e, e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(edenom, edenom, e0); \ } element_init(a, res->field); element_init(b, res->field); element_init(c, res->field); element_init(e0, res->field); element_init(e1, res->field); element_init(z, res->field); element_init(z2, res->field); element_set1(z); element_set1(z2); element_init(v, res->field); element_init(vd, res->field); element_init(v1, res->field); element_init(vd1, res->field); element_init(Z, P->field); element_init(Z1, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_y_coord(Z); element_set1(v); element_set1(vd); element_set1(v1); element_set1(vd1); n = p->exp1; for (i=0; i<n; i++) { element_square(v, v); element_square(vd, vd); do_tangent(v, vd); proj_double(); do_vertical(vd, v, Zx); } to_affine(); if (p->sign1 < 0) { element_set(v1, vd); element_set(vd1, v); do_vertical(vd1, v1, Zx); element_neg(Z1, Z); } else { element_set(v1, v); element_set(vd1, vd); element_set(Z1, Z); } n = p->exp2; for (; i<n; i++) { element_square(v, v); element_square(vd, vd); do_tangent(v, vd); proj_double(); do_vertical(vd, v, Zx); } to_affine(); element_mul(v, v, v1); element_mul(vd, vd, vd1); do_line(v, vd, Z, Z1); element_add(Z, Z, Z1); do_vertical(vd, v, Zx); if (p->sign0 > 0) { do_vertical(v, vd, Px); } element_invert(vd, vd); element_mul(res, v, vd); element_clear(v); element_clear(vd); element_clear(v1); element_clear(vd1); element_clear(z); element_clear(z2); element_clear(Z); element_clear(Z1); element_clear(a); element_clear(b); element_clear(c); element_clear(e0); element_clear(e1); #undef to_affine #undef proj_double #undef do_tangent #undef do_vertical #undef do_line }
// in1, in2 are from E(F_q), out from F_q^2. // Pairing via elliptic nets (see Stange). static void e_pairing_ellnet(element_ptr out, element_ptr in1, element_ptr in2, pairing_t pairing) { const element_ptr a = curve_a_coeff(in1); const element_ptr b = curve_b_coeff(in1); element_ptr x = curve_x_coord(in1); element_ptr y = curve_y_coord(in1); element_ptr x2 = curve_x_coord(in2); element_ptr y2 = curve_y_coord(in2); //notation: cmi means c_{k-i}, ci means c_{k+i} element_t cm3, cm2, cm1, c0, c1, c2, c3, c4; element_t dm1, d0, d1; element_t A, B, C; element_init_same_as(cm3, x); element_init_same_as(cm2, x); element_init_same_as(cm1, x); element_init_same_as(c0, x); element_init_same_as(c1, x); element_init_same_as(c2, x); element_init_same_as(c3, x); element_init_same_as(c4, x); element_init_same_as(C, x); element_init_same_as(dm1, out); element_init_same_as(d0, out); element_init_same_as(d1, out); element_init_same_as(A, x); element_init_same_as(B, out); // c1 = 2y // cm3 = -2y element_double(c1, y); element_neg(cm3, c1); //use c0, cm1, cm2, C, c4 as temp variables for now //compute c3, c2 element_square(cm2, x); element_square(C, cm2); element_mul(cm1, b, x); element_double(cm1, cm1); element_square(c4, a); element_mul(c2, cm1, cm2); element_double(c2, c2); element_mul(c0, a, C); element_add(c2, c2, c0); element_mul(c0, c4, cm2); element_sub(c2, c2, c0); element_double(c0, c2); element_double(c0, c0); element_add(c2, c2, c0); element_mul(c0, cm1, a); element_square(c3, b); element_double(c3, c3); element_double(c3, c3); element_add(c0, c0, c3); element_double(c0, c0); element_mul(c3, a, c4); element_add(c0, c0, c3); element_sub(c2, c2, c0); element_mul(c0, cm2, C); element_add(c3, c0, c2); element_mul(c3, c3, c1); element_double(c3, c3); element_mul(c0, a, cm2); element_add(c0, c0, cm1); element_double(c0, c0); element_add(c0, c0, C); element_double(c2, c0); element_add(c0, c0, c2); element_sub(c2, c0, c4); // c0 = 1 // cm2 = -1 element_set1(c0); element_neg(cm2, c0); // c4 = c_5 = c_2^3 c_4 - c_3^3 = c1^3 c3 - c2^3 element_square(C, c1); element_mul(c4, C, c1); element_mul(c4, c4, c3); element_square(C, c2); element_mul(C, C, c2); element_sub(c4, c4, C); //compute A, B, d1 (which is d_2 since k = 1) element_sub(A, x, x2); element_double(C, x); element_add(C, C, x2); element_square(cm1, A); element_mul(cm1, C, cm1); element_add(d1, y, y2); element_square(d1, d1); element_sub(B, cm1, d1); element_invert(B, B); element_invert(A, A); element_sub(d1, y, y2); element_mul(d1, d1, A); element_square(d1, d1); element_sub(d1, C, d1); // cm1 = 0 // C = (2y)^-1 element_set0(cm1); element_invert(C, c1); element_set1(dm1); element_set1(d0); element_t sm2, sm1; element_t s0, s1, s2, s3; element_t tm2, tm1; element_t t0, t1, t2, t3; element_t e0, e1; element_t u, v; element_init_same_as(sm2, x); element_init_same_as(sm1, x); element_init_same_as(s0, x); element_init_same_as(s1, x); element_init_same_as(s2, x); element_init_same_as(s3, x); element_init_same_as(tm2, x); element_init_same_as(tm1, x); element_init_same_as(t0, x); element_init_same_as(t1, x); element_init_same_as(t2, x); element_init_same_as(t3, x); element_init_same_as(e0, x); element_init_same_as(e1, x); element_init_same_as(u, d0); element_init_same_as(v, d0); int m = mpz_sizeinbase(pairing->r, 2) - 2; for (;;) { element_square(sm2, cm2); element_square(sm1, cm1); element_square(s0, c0); element_square(s1, c1); element_square(s2, c2); element_square(s3, c3); element_mul(tm2, cm3, cm1); element_mul(tm1, cm2, c0); element_mul(t0, cm1, c1); element_mul(t1, c0, c2); element_mul(t2, c1, c3); element_mul(t3, c2, c4); element_square(u, d0); element_mul(v, dm1, d1); if (mpz_tstbit(pairing->r, m)) { //double-and-add element_mul(e0, t0, sm2); element_mul(e1, tm2, s0); element_sub(cm3, e0, e1); element_mul(cm3, cm3, C); element_mul(e0, t0, sm1); element_mul(e1, tm1, s0); element_sub(cm2, e0, e1); element_mul(e0, t1, sm1); element_mul(e1, tm1, s1); element_sub(cm1, e0, e1); element_mul(cm1, cm1, C); element_mul(e0, t1, s0); element_mul(e1, t0, s1); element_sub(c0, e0, e1); element_mul(e0, t2, s0); element_mul(e1, t0, s2); element_sub(c1, e0, e1); element_mul(c1, c1, C); element_mul(e0, t2, s1); element_mul(e1, t1, s2); element_sub(c2, e0, e1); element_mul(e0, t3, s1); element_mul(e1, t1, s3); element_sub(c3, e0, e1); element_mul(c3, c3, C); element_mul(e0, t3, s2); element_mul(e1, t2, s3); element_sub(c4, e0, e1); element_mul(out, u, t0); element_mul(dm1, v, s0); element_sub(dm1, dm1, out); element_mul(out, u, t1); element_mul(d0, v, s1); element_sub(d0, d0, out); element_mul(d0, d0, A); element_mul(out, u, t2); element_mul(d1, v, s2); element_sub(d1, d1, out); element_mul(d1, d1, B); } else { //double element_mul(e0, tm1, sm2); element_mul(e1, tm2, sm1); element_sub(cm3, e0, e1); element_mul(e0, t0, sm2); element_mul(e1, tm2, s0); element_sub(cm2, e0, e1); element_mul(cm2, cm2, C); element_mul(e0, t0, sm1); element_mul(e1, tm1, s0); element_sub(cm1, e0, e1); element_mul(e0, t1, sm1); element_mul(e1, tm1, s1); element_sub(c0, e0, e1); element_mul(c0, c0, C); element_mul(e0, t1, s0); element_mul(e1, t0, s1); element_sub(c1, e0, e1); element_mul(e0, t2, s0); element_mul(e1, t0, s2); element_sub(c2, e0, e1); element_mul(c2, c2, C); element_mul(e0, t2, s1); element_mul(e1, t1, s2); element_sub(c3, e0, e1); element_mul(e0, t3, s1); element_mul(e1, t1, s3); element_sub(c4, e0, e1); element_mul(c4, c4, C); element_mul(out, u, tm1); element_mul(dm1, v, sm1); element_sub(dm1, dm1, out); element_mul(out, u, t0); element_mul(d0, v, s0); element_sub(d0, d0, out); element_mul(out, u, t1); element_mul(d1, v, s1); element_sub(d1, d1, out); element_mul(d1, d1, A); } if (!m) break; m--; } element_invert(c1, c1); element_mul(d1, d1, c1); element_pow_mpz(out, d1, pairing->phikonr); element_clear(dm1); element_clear(d0); element_clear(d1); element_clear(cm3); element_clear(cm2); element_clear(cm1); element_clear(c0); element_clear(c1); element_clear(c2); element_clear(c3); element_clear(c4); element_clear(sm2); element_clear(sm1); element_clear(s0); element_clear(s1); element_clear(s2); element_clear(s3); element_clear(tm2); element_clear(tm1); element_clear(t0); element_clear(t1); element_clear(t2); element_clear(t3); element_clear(e0); element_clear(e1); element_clear(A); element_clear(B); element_clear(C); element_clear(u); element_clear(v); }
static void e_miller_affine(element_t res, element_t P, element_ptr QR, element_ptr R, e_pairing_data_ptr p) { //collate divisions int n; element_t v, vd; element_t v1, vd1; element_t Z, Z1; element_t a, b, c; element_t e0, e1; const element_ptr Px = curve_x_coord(P); const element_ptr cca = curve_a_coeff(P); element_ptr Zx, Zy; int i; const element_ptr numx = curve_x_coord(QR); const element_ptr numy = curve_y_coord(QR); const element_ptr denomx = curve_x_coord(R); const element_ptr denomy = curve_y_coord(R); #define do_vertical(e, edenom, Ax) { \ element_sub(e0, numx, Ax); \ element_mul(e, e, e0); \ \ element_sub(e0, denomx, Ax); \ element_mul(edenom, edenom, e0); \ } #define do_tangent(e, edenom) { \ /* a = -slope_tangent(A.x, A.y); */ \ /* b = 1; */ \ /* c = -(A.y + a * A.x); */ \ /* but we multiply by 2*A.y to avoid division */ \ \ /* a = -Ax * (Ax + Ax + Ax + twicea_2) - a_4; */ \ /* Common curves: a2 = 0 (and cc->a is a_4), so */ \ /* a = -(3 Ax^2 + cc->a) */ \ /* b = 2 * Ay */ \ /* c = -(2 Ay^2 + a Ax); */ \ \ element_square(a, Zx); \ element_mul_si(a, a, 3); \ element_add(a, a, cca); \ element_neg(a, a); \ \ element_add(b, Zy, Zy); \ \ element_mul(e0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, e0); \ element_neg(c, c); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(e, e, e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(edenom, edenom, e0); \ } #define do_line(e, edenom, A, B) { \ element_ptr Ax = curve_x_coord(A); \ element_ptr Ay = curve_y_coord(A); \ element_ptr Bx = curve_x_coord(B); \ element_ptr By = curve_y_coord(B); \ \ element_sub(b, Bx, Ax); \ element_sub(a, Ay, By); \ element_mul(c, Ax, By); \ element_mul(e0, Ay, Bx); \ element_sub(c, c, e0); \ \ element_mul(e0, a, numx); \ element_mul(e1, b, numy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(e, e, e0); \ \ element_mul(e0, a, denomx); \ element_mul(e1, b, denomy); \ element_add(e0, e0, e1); \ element_add(e0, e0, c); \ element_mul(edenom, edenom, e0); \ } element_init(a, res->field); element_init(b, res->field); element_init(c, res->field); element_init(e0, res->field); element_init(e1, res->field); element_init(v, res->field); element_init(vd, res->field); element_init(v1, res->field); element_init(vd1, res->field); element_init(Z, P->field); element_init(Z1, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_y_coord(Z); element_set1(v); element_set1(vd); element_set1(v1); element_set1(vd1); n = p->exp1; for (i=0; i<n; i++) { element_square(v, v); element_square(vd, vd); do_tangent(v, vd); element_double(Z, Z); do_vertical(vd, v, Zx); } if (p->sign1 < 0) { element_set(v1, vd); element_set(vd1, v); do_vertical(vd1, v1, Zx); element_neg(Z1, Z); } else { element_set(v1, v); element_set(vd1, vd); element_set(Z1, Z); } n = p->exp2; for (; i<n; i++) { element_square(v, v); element_square(vd, vd); do_tangent(v, vd); element_double(Z, Z); do_vertical(vd, v, Zx); } element_mul(v, v, v1); element_mul(vd, vd, vd1); do_line(v, vd, Z, Z1); element_add(Z, Z, Z1); do_vertical(vd, v, Zx); if (p->sign0 > 0) { do_vertical(v, vd, Px); } element_invert(vd, vd); element_mul(res, v, vd); element_clear(v); element_clear(vd); element_clear(v1); element_clear(vd1); element_clear(Z); element_clear(Z1); element_clear(a); element_clear(b); element_clear(c); element_clear(e0); element_clear(e1); #undef do_vertical #undef do_tangent #undef do_line }
static void d_pairing_pp_init(pairing_pp_t p, element_ptr in1, pairing_t pairing) { element_ptr P = in1; const element_ptr Px = curve_x_coord(P); const element_ptr Py = curve_y_coord(P); element_t Z; mp_bitcnt_t m; pptr info = pairing->data; element_t t0; element_t a, b, c; field_ptr Fq = info->Fq; pp_coeff_t *coeff; mpz_ptr q = pairing->r; pp_coeff_ptr pp; const element_ptr cca = curve_a_coeff(P); element_ptr Zx; element_ptr Zy; #define store_abc() { \ element_init(pp->a, Fq); \ element_init(pp->b, Fq); \ element_init(pp->c, Fq); \ element_set(pp->a, a); \ element_set(pp->b, b); \ element_set(pp->c, c); \ pp++; \ } #define do_tangent() { \ /* a = -slope_tangent(Z.x, Z.y); */ \ /* b = 1; */ \ /* c = -(Z.y + a * Z.x); */ \ /* but we multiply by 2*Z.y to avoid division. */ \ \ /* a = -Zx * (3 Zx + twicea_2) - a_4; */ \ /* Common curves: a2 = 0 (and cc->a is a_4), so */ \ /* a = -(3 Zx^2 + cc->a) */ \ /* b = 2 * Zy */ \ /* c = -(2 Zy^2 + a Zx); */ \ \ element_square(a, Zx); \ element_double(t0, a); \ element_add(a, a, t0); \ element_add(a, a, cca); \ element_neg(a, a); \ \ element_add(b, Zy, Zy); \ \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ store_abc(); \ } #define do_line() { \ /* a = -(B.y - A.y) / (B.x - A.x); */ \ /* b = 1; */ \ /* c = -(A.y + a * A.x); */ \ /* but we'll multiply by B.x - A.x to avoid division */ \ \ element_sub(b, Px, Zx); \ element_sub(a, Zy, Py); \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ store_abc(); \ } element_init(Z, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_y_coord(Z); element_init(t0, Fq); element_init(a, Fq); element_init(b, Fq); element_init(c, Fq); m = (mp_bitcnt_t)mpz_sizeinbase(q, 2); m = (m > 2 ? m - 2 : 0); p->data = pbc_malloc(sizeof(pp_coeff_t) * 2 * m); coeff = (pp_coeff_t *) p->data; pp = coeff[0]; for(;;) { do_tangent(); if (!m) break; element_double(Z, Z); if (mpz_tstbit(q, m)) { do_line(); element_add(Z, Z, P); } m--; } element_clear(t0); element_clear(a); element_clear(b); element_clear(c); element_clear(Z); #undef store_abc #undef do_tangent #undef do_line }
//do many millers at one time with affine coordinates. static void cc_millers_no_denom_affine(element_t res, mpz_t q, element_t P[], element_t Qx[], element_t Qy[], int n_prod) { mp_bitcnt_t m; int i; element_t v; element_t a, b, c; element_t t0; element_t e0; const element_ptr cca = curve_a_coeff(P[0]); element_ptr Px, Py; element_t* Z = pbc_malloc(sizeof(element_t)*n_prod); element_ptr Zx, Zy; /* TODO: when exactly is this not needed? void do_vertical() { mapbase(e0, Z->x); element_sub(e0, Qx, e0); element_mul(v, v, e0); } */ #define do_tangents() { \ /* a = -(3 Zx^2 + cc->a) */ \ /* b = 2 * Zy */ \ /* c = -(2 Zy^2 + a Zx); */ \ for(i=0; i<n_prod; i++){ \ Px = curve_x_coord(P[i]); \ Py = curve_y_coord(P[i]); \ Zx = curve_x_coord(Z[i]); \ Zy = curve_y_coord(Z[i]); \ \ element_square(a, Zx); \ element_mul_si(a, a, 3); \ element_add(a, a, cca); \ element_neg(a, a); \ \ element_add(b, Zy, Zy); \ \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]); \ element_mul(v, v, e0); \ } \ } #define do_lines() { \ /* a = -(B.y - A.y) / (B.x - A.x); */ \ /* b = 1; */ \ /* c = -(A.y + a * A.x); */ \ /* but we multiply by B.x - A.x to avoid division. */ \ for(i=0; i<n_prod; i++){ \ Px = curve_x_coord(P[i]); \ Py = curve_y_coord(P[i]); \ Zx = curve_x_coord(Z[i]); \ Zy = curve_y_coord(Z[i]); \ \ element_sub(b, Px, Zx); \ element_sub(a, Zy, Py); \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ d_miller_evalfn(e0, a, b, c, Qx[i], Qy[i]); \ element_mul(v, v, e0); \ } \ } Px= curve_x_coord(P[0]); //temporally used to initial a,b, c and etc. element_init(a, Px->field); element_init(b, a->field); element_init(c, a->field); element_init(t0, a->field); element_init(e0, res->field); element_init(v, res->field); for(i=0; i<n_prod; i++){ element_init(Z[i], P[i]->field); element_set(Z[i], P[i]); } element_set1(v); m = (mp_bitcnt_t)mpz_sizeinbase(q, 2); m = (m > 2 ? m - 2 : 0); for(;;) { do_tangents(); if (!m) break; element_multi_double(Z, Z, n_prod); //Z_i=Z_i+Z_i for all i. if (mpz_tstbit(q, m)) { do_lines(); element_multi_add(Z, Z, P, n_prod); //Z_i=Z_i+P_i for all i. } m--; element_square(v, v); } element_set(res, v); element_clear(v); for(i=0; i<n_prod; i++){ element_clear(Z[i]); } pbc_free(Z); element_clear(a); element_clear(b); element_clear(c); element_clear(t0); element_clear(e0); #undef do_tangents #undef do_lines }
// Same as above, but with affine coordinates. static void cc_miller_no_denom_affine(element_t res, mpz_t q, element_t P, element_ptr Qx, element_ptr Qy) { mp_bitcnt_t m; element_t v; element_t Z; element_t a, b, c; element_t t0; element_t e0; const element_ptr cca = curve_a_coeff(P); const element_ptr Px = curve_x_coord(P); const element_ptr Py = curve_y_coord(P); element_ptr Zx, Zy; /* TODO: when exactly is this not needed? void do_vertical() { mapbase(e0, Z->x); element_sub(e0, Qx, e0); element_mul(v, v, e0); } */ #define do_tangent() { \ /* a = -(3 Zx^2 + cc->a) */ \ /* b = 2 * Zy */ \ /* c = -(2 Zy^2 + a Zx); */ \ \ element_square(a, Zx); \ element_mul_si(a, a, 3); \ element_add(a, a, cca); \ element_neg(a, a); \ \ element_add(b, Zy, Zy); \ \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ d_miller_evalfn(e0, a, b, c, Qx, Qy); \ element_mul(v, v, e0); \ } #define do_line() { \ /* a = -(B.y - A.y) / (B.x - A.x); */ \ /* b = 1; */ \ /* c = -(A.y + a * A.x); */ \ /* but we multiply by B.x - A.x to avoid division. */ \ \ element_sub(b, Px, Zx); \ element_sub(a, Zy, Py); \ element_mul(t0, b, Zy); \ element_mul(c, a, Zx); \ element_add(c, c, t0); \ element_neg(c, c); \ \ d_miller_evalfn(e0, a, b, c, Qx, Qy); \ element_mul(v, v, e0); \ } element_init(a, Px->field); element_init(b, a->field); element_init(c, a->field); element_init(t0, a->field); element_init(e0, res->field); element_init(v, res->field); element_init(Z, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_y_coord(Z); element_set1(v); m = (mp_bitcnt_t)mpz_sizeinbase(q, 2); m = (m > 2 ? m - 2 : 0); for(;;) { do_tangent(); if (!m) break; element_double(Z, Z); if (mpz_tstbit(q, m)) { do_line(); element_add(Z, Z, P); } m--; element_square(v, v); } element_set(res, v); element_clear(v); element_clear(Z); element_clear(a); element_clear(b); element_clear(c); element_clear(t0); element_clear(e0); #undef do_tangent #undef do_line }
// Miller's algorithm, assuming we can ignore the denominator. We can do this // with careful group selection when the embedding degree is even. See thesis. // This version uses projective coordinates, which don't seem much faster. static void cc_miller_no_denom_proj(element_t res, mpz_t q, element_t P, element_ptr Qx, element_ptr Qy) { mp_bitcnt_t m; element_t v; element_t Z; element_t a, b, c; element_t t0, t1; element_ptr t2 = a, t3 = b, t4 = c; element_t e0; element_t z, z2; element_ptr Zx, Zy; const element_ptr curve_a = curve_a_coeff(P); const element_ptr Px = curve_x_coord(P); const element_ptr Py = curve_y_coord(P); #define proj_double() { \ /* t0 = 3x^2 + (curve_a) z^4 */ \ element_square(t0, Zx); \ /* element_mul_si(t0, t0, 3); */ \ element_double(t1, t0); \ element_add(t0, t0, t1); \ element_square(t1, z2); \ element_mul(t1, t1, curve_a); \ element_add(t0, t0, t1); \ \ /* z_out = 2 y z */ \ element_mul(z, Zy, z); \ /* element_mul_si(z, z, 2); */ \ element_double(z, z); \ element_square(z2, z); \ \ /* t1 = 4 x y^2 */ \ element_square(t2, Zy); \ element_mul(t1, Zx, t2); \ /* element_mul_si(t1, t1, 4); */ \ element_double(t1, t1); \ element_double(t1, t1); \ \ /* x_out = t0^2 - 2 t1 */ \ /* element_mul_si(t3, t1, 2); */ \ element_double(t3, t1); \ element_square(Zx, t0); \ element_sub(Zx, Zx, t3); \ \ /* t2 = 8y^4 */ \ element_square(t2, t2); \ /* element_mul_si(t2, t2, 8); */ \ element_double(t2, t2); \ element_double(t2, t2); \ element_double(t2, t2); \ \ /* y_out = t0(t1 - x_out) - t2 */ \ element_sub(t1, t1, Zx); \ element_mul(t0, t0, t1); \ element_sub(Zy, t0, t2); \ } #define proj_mixin() { \ /* t2 = Px z^2 */ \ element_mul(t2, z2, Px); \ \ /* t3 = Zx - t2 */ \ element_sub(t3, Zx, t2); \ \ /* t0 = Py z^3 */ \ element_mul(t0, z2, Py); \ element_mul(t0, t0, z); \ \ /* t1 = Zy - t0 */ \ element_sub(t1, Zy, t0); \ \ /* e7 = Zx + t2, use t2 to double for e7 */ \ element_add(t2, Zx, t2); \ \ /* e8 = Zy + t0, use t0 to double for e8 */ \ element_add(t0, Zy, t0); \ \ /* z = z t3 */ \ element_mul(z, z, t3); \ element_square(z2, z); \ \ /* Zx = t1^2 - e7 t3^2 */ \ /* t3 now holds t3^3, */ \ /* t4 holds e7 t3^2. */ \ element_square(t4, t3); \ element_mul(t3, t4, t3); \ element_square(Zx, t1); \ element_mul(t4, t2, t4); \ element_sub(Zx, Zx, t4); \ \ /* t4 = e7 t3^2 - 2 Zx */ \ element_sub(t4, t4, Zx); \ element_sub(t4, t4, Zx); \ \ /* Zy = (t4 t1 - e8 t3^3)/2 */ \ element_mul(t4, t4, t1); \ element_mul(t0, t0, t3); \ element_sub(t4, t4, t0); \ element_halve(Zy, t4); \ } #define do_tangent() { \ /* a = -(3x^2 + cca z^4) */ \ /* b = 2 y z^3 */ \ /* c = -(2 y^2 + x a) */ \ /* a = z^2 a */ \ element_square(a, z2); \ element_mul(a, a, curve_a); \ element_square(b, Zx); \ /* element_mul_si(b, b, 3); */ \ element_double(t0, b); \ element_add(b, b, t0); \ element_add(a, a, b); \ element_neg(a, a); \ \ element_mul(b, z, z2); \ element_mul(b, b, Zy); \ element_mul_si(b, b, 2); \ \ element_mul(c, Zx, a); \ element_mul(a, a, z2); \ element_square(t0, Zy); \ element_mul_si(t0, t0, 2); \ element_add(c, c, t0); \ element_neg(c, c); \ \ d_miller_evalfn(e0, a, b, c, Qx, Qy); \ element_mul(v, v, e0); \ } #define do_line() { \ /* a = -(Py z^3 - Zy) */ \ /* b = Px z^3 - Zx z */ \ /* c = Zx z Py - Zy Px; */ \ \ element_mul(t0, Zx, z); \ element_mul(t1, z2, z); \ \ element_mul(a, Py, t1); \ element_sub(a, Zy, a); \ \ element_mul(b, Px, t1); \ element_sub(b, b, t0); \ \ element_mul(t0, t0, Py); \ element_mul(c, Zy, Px); \ element_sub(c, t0, c); \ \ d_miller_evalfn(e0, a, b, c, Qx, Qy); \ element_mul(v, v, e0); \ } element_init(a, Px->field); element_init(b, a->field); element_init(c, a->field); element_init(t0, a->field); element_init(t1, a->field); element_init(e0, res->field); element_init(z, a->field); element_init(z2, a->field); element_set1(z); element_set1(z2); element_init(v, res->field); element_init(Z, P->field); element_set(Z, P); Zx = curve_x_coord(Z); Zy = curve_x_coord(Z); element_set1(v); m = (mp_bitcnt_t)mpz_sizeinbase(q, 2); m = (m > 2 ? m - 2 : 0); for(;;) { do_tangent(); if (!m) break; proj_double(); if (mpz_tstbit(q, m)) { do_line(); proj_mixin(); } m--; element_square(v, v); } element_set(res, v); element_clear(v); element_clear(Z); element_clear(a); element_clear(b); element_clear(c); element_clear(t0); element_clear(t1); element_clear(e0); element_clear(z); element_clear(z2); #undef proj_double #undef proj_mixin #undef do_tangent #undef do_line }