/* computing of $(-t^2 +u*s -t*p -p^2)^3$ * The algorithm is by J.Beuchat et.al, in the paper of "Algorithms and Arithmetic Operators for Computing * the $eta_T$ Pairing in Characteristic Three", algorithm 4 in the appendix */ static void algorithm4a(element_t S, element_t t, element_t u) { field_ptr f = FIELD(t); element_t e1, c0, c1, m0, v0, v2; element_init(e1, f); element_init(c0, f); element_init(c1, f); element_init(m0, f); element_init(v0, f); element_init(v2, f); element_set1(e1); element_cubic(c0, t); // c0 == t^3 element_cubic(c1, u); element_neg(c1, c1); // c1 == -u^3 element_mul(m0, c0, c0); // m0 == c0^2 element_neg(v0, m0); // v0 == -c0^2 element_sub(v0, v0, c0); // v0 == -c0^2 -c0 element_sub(v0, v0, e1); // v0 == -c0^2 -c0 -1 element_set1(v2); element_sub(v2, v2, c0); // v2 == 1 -c0 // v1 == c1 // S == [[v0, v1], [v2, f3m.zero()], [f3m.two(), f3m.zero()]] element_set(ITEM(S,0,0), v0); element_set(ITEM(S,0,1), c1); element_set(ITEM(S,1,0), v2); element_set0(ITEM(S,1,1)); element_neg(ITEM(S,2,0), e1); element_set0(ITEM(S,2,1)); element_clear(e1); element_clear(c0); element_clear(c1); element_clear(m0); element_clear(v0); element_clear(v2); }
static void point_add(element_t c, element_t a, element_t b) { point_ptr p1 = DATA(a), p2 = DATA(b), p3 = DATA(c); int inf1 = p1->isinf, inf2 = p2->isinf; element_ptr x1 = p1->x, y1 = p1->y, x2 = p2->x, y2 = p2->y; field_ptr f = FIELD(x1); if (inf1) { point_set(c, b); return; } if (inf2) { point_set(c, a); return; } element_t v0, v1, v2, v3, v4, ny2; element_init(v0, f); element_init(v1, f); element_init(v2, f); element_init(v3, f); element_init(v4, f); element_init(ny2, f); if (!element_cmp(x1, x2)) { // x1 == x2 element_neg(ny2, y2); // ny2 == -y2 if (!element_cmp(y1, ny2)) { p3->isinf = 1; goto end; } if (!element_cmp(y1, y2)) { // y1 == y2 element_invert(v0, y1); // v0 == y1^{-1} element_mul(v1, v0, v0); // v1 == [y1^{-1}]^2 element_add(p3->x, v1, x1); // v1 == [y1^{-1}]^2 + x1 element_cubic(v2, v0); // v2 == [y1^{-1}]^3 element_add(v2, v2, y1); // v2 == [y1^{-1}]^3 + y1 element_neg(p3->y, v2); // p3 == -([y1^{-1}]^3 + y1) p3->isinf = 0; goto end; } } // $P1 \ne \pm P2$ element_sub(v0, x2, x1); // v0 == x2-x1 element_invert(v1, v0); // v1 == (x2-x1)^{-1} element_sub(v0, y2, y1); // v0 == y2-y1 element_mul(v2, v0, v1); // v2 == (y2-y1)/(x2-x1) element_mul(v3, v2, v2); // v3 == [(y2-y1)/(x2-x1)]^2 element_cubic(v4, v2); // v4 == [(y2-y1)/(x2-x1)]^3 element_add(v0, x1, x2); // v0 == x1+x2 element_sub(v3, v3, v0); // v3 == [(y2-y1)/(x2-x1)]^2 - (x1+x2) element_add(v0, y1, y2); // v0 == y1+y2 element_sub(v4, v0, v4); // v4 == (y1+y2) - [(y2-y1)/(x2-x1)]^3 p3->isinf = 0; element_set(p3->x, v3); element_set(p3->y, v4); end: element_clear(v0); element_clear(v1); element_clear(v2); element_clear(v3); element_clear(v4); element_clear(ny2); }
/* $e <- a^3$ */ static void gf32m_cubic(element_t e, element_t a) { element_ptr a0 = GF32M(a)->_0, a1 = GF32M(a)->_1, e0 = GF32M(e)->_0, e1 = GF32M(e)->_1; field_ptr base = BASE(a); element_t c0, c1; element_init(c0, base); element_init(c1, base); element_cubic(c0, a0); element_cubic(c1, a1); element_neg(c1, c1); // c1 == -(a1^3) element_set(e0, c0); element_set(e1, c1); element_clear(c0); element_clear(c1); }
static void test_gf3m_cubic(void) { element_random(a); element_mul(b, a, a); element_mul(b, a, b); element_cubic(a, a); EXPECT(!element_cmp(a, b)); }
static void test_gf36m_cubic(void) { element_random(a6); element_mul(b6, a6, a6); element_mul(b6, b6, a6); element_cubic(a6, a6); EXPECT(!element_cmp(a6, b6)); }
static void test_gf33m_cubic(void) { element_random(a3); element_mul(b3, a3, a3); element_mul(b3, b3, a3); element_cubic(a3, a3); EXPECT(!element_cmp(a3, b3)); }
static void test_gf32m_cubic(void) { element_random(a2); element_mul(b2, a2, a2); element_mul(b2, b2, a2); element_cubic(a2, a2); EXPECT(!element_cmp(a2, b2)); }
static void point_random(element_t a) { point_ptr p = DATA(a); element_ptr x = p->x, y = p->y; field_ptr f = x->field; p->isinf = 0; element_t t, t2, e1; element_init(t, f); element_init(e1, f); element_set1(e1); element_init(t2, f); do { element_random(x); if (element_is0(x)) continue; element_cubic(t, x); // t == x^3 element_sub(t, t, x); // t == x^3 - x element_add(t, t, e1); // t == x^3 - x + 1 element_sqrt(y, t); // y == sqrt(x^3 - x + 1) element_mul(t2, y, y); // t2 == x^3 - x + 1 } while (element_cmp(t2, t)); // t2 != t // make sure order of $a$ is order of $G_1$ pairing_ptr pairing = FIELD(a)->pairing; pairing_data_ptr dp = pairing->data; element_pow_mpz(a, a, dp->n2); element_clear(t); element_clear(t2); element_clear(e1); }
/* computing $c <- U^M, M=(3^{3m}-1)*(3^m+1)*(3^m+1-\mu*b*3^{(m+1)//2})$ * This is the algorithm 8 in the paper above. */ static void algorithm8(element_t c, element_t u) { field_ptr f6 = FIELD(u), f = FIELD(ITEM(u,0,0)); params *p = (params *) f->data; element_t v, w; element_init(v, f6); element_init(w, f6); algorithm6(v, u); algorithm7(v, v); element_set(w, v); int i; for (i = 0; i < (p->m + 1) / 2; i++) element_cubic(w, w); algorithm7(v, v); if (p->m % 12 == 1 || p->m % 12 == 11) { // w <= w^{-\mu*b} element_ptr e; e = ITEM(w,0,1); element_neg(e, e); e = ITEM(w,1,1); element_neg(e, e); e = ITEM(w,2,1); element_neg(e, e); } element_mul(c, v, w); element_clear(v); element_clear(w); }
static void test_gf3m_cubic2(void) { if (sizeof(pbc_mpui) < 8) return; // 64-bit test only pbc_mpui x[] = { (pbc_mpui)1153286547535200267ul, (pbc_mpui)6715371622ul, (pbc_mpui)4990694927524257316ul, (pbc_mpui)210763913ul }; pbc_mpui y[] = { (pbc_mpui)8145587063258678275ul, (pbc_mpui)6451025920ul, (pbc_mpui)9976895054123379152ul, (pbc_mpui)1275593166ul }; memcpy(a->data, x, sizeof(x)); memcpy(b->data, y, sizeof(y)); element_cubic(a, a); EXPECT(!element_cmp(a, b)); }
/* $e <- a^3$ */ static void gf33m_cubic(element_t e, element_t a) { field_ptr base = BASE(a); element_ptr a0 = GF33M(a)->_0, a1 = GF33M(a)->_1, a2 = GF33M(a)->_2, e0 = GF33M(e)->_0, e1 = GF33M(e)->_1, e2 = GF33M(e)->_2; element_t a03, a13, a23; element_init(a03, base); element_init(a13, base); element_init(a23, base); element_cubic(a03, a0); element_cubic(a13, a1); element_cubic(a23, a2); element_add(a03, a03, a13); element_add(a03, a03, a23); element_ptr c0 = a03; element_sub(a13, a13, a23); element_ptr c1 = a13; element_ptr c2 = a23; element_set(e0, c0); element_set(e1, c1); element_set(e2, c2); element_clear(a03); element_clear(a13); element_clear(a23); }
/* this is the algorithm 4 in the paper of J.Beuchat et.al, "Algorithms and Arithmetic Operators for Computing * the $eta_T$ Pairing in Characteristic Three" */ static void algorithm4(element_t c, element_ptr xp, element_ptr yp, element_ptr xq, element_ptr yq) { params *p = PARAM(xp); unsigned int re = p->m % 12; field_ptr f = FIELD(xp) /*GF(3^m)*/, f6 = FIELD(c) /*GF(3^{6*m})*/; element_t e1, xpp, ypp, xqq, yqq, t, nt, nt2, v1, v2, a1, a2, R, u, S; element_init(e1, f); element_init(xpp, f); element_init(ypp, f); element_init(xqq, f); element_init(yqq, f); element_init(t, f); element_init(nt, f); element_init(nt2, f); element_init(v1, f); element_init(v2, f); element_init(a1, f6); element_init(a2, f6); element_init(R, f6); element_init(u, f); element_init(S, f6); element_set1(e1); element_set(xpp, xp); xp = xpp; // clone element_add(xp, xp, e1); // xp == xp + b element_set(ypp, yp); yp = ypp; // clone if (re == 1 || re == 11) element_neg(yp, yp); // yp == -\mu*b*yp, \mu == 1 when re==1, or 11 element_set(xqq, xq); xq = xqq; // clone element_cubic(xq, xq); // xq == xq^3 element_set(yqq, yq); yq = yqq; // clone element_cubic(yq, yq); // yq == yq^3 element_add(t, xp, xq); // t == xp+xq element_neg(nt, t); // nt == -t element_mul(nt2, t, nt); // nt2 == -t^2 element_mul(v2, yp, yq); // v2 == yp*yq element_mul(v1, yp, t); // v1 == yp*t if (re == 7 || re == 11) { // \lambda == 1 element_t nyp, nyq; element_init(nyp, f); element_init(nyq, f); element_neg(nyp, yp); // nyp == -yp element_neg(nyq, yq); // nyq == -yq element_set(ITEM(a1,0,0), v1); element_set(ITEM(a1,0,1), nyq); element_set(ITEM(a1,1,0), nyp); element_clear(nyp); element_clear(nyq); } else { // \lambda == -1 element_neg(v1, v1); // v1 == -yp*t element_set(ITEM(a1,0,0), v1); element_set(ITEM(a1,0,1), yq); element_set(ITEM(a1,1,0), yp); } // a2 == -t^2 +yp*yq*s -t*p -p^2 element_set(ITEM(a2,0,0), nt2); element_set(ITEM(a2,0,1), v2); element_set(ITEM(a2,1,0), nt); element_neg(ITEM(a2,2,0), e1); element_mul(R, a1, a2); int i; for (i = 0; i < (p->m - 1) / 2; i++) { element_cubic(R, R); element_cubic(xq, xq); element_cubic(xq, xq); element_sub(xq, xq, e1); // xq <= xq^9-b element_cubic(yq, yq); element_cubic(yq, yq); element_neg(yq, yq); // yq <= -yq^9 element_add(t, xp, xq); // t == xp+xq element_neg(nt, t); // nt == -t element_mul(nt2, t, nt); // nt2 == -t^2 element_mul(u, yp, yq); // u == yp*yq element_set0(S); element_set(ITEM(S,0,0), nt2); element_set(ITEM(S,0,1), u); element_set(ITEM(S,1,0), nt); element_neg(ITEM(S,2,0), e1); element_mul(R, R, S); } element_set(c, R); element_clear(e1); element_clear(xpp); element_clear(ypp); element_clear(xqq); element_clear(yqq); element_clear(t); element_clear(nt); element_clear(nt2); element_clear(v1); element_clear(v2); element_clear(a1); element_clear(a2); element_clear(R); element_clear(u); element_clear(S); }