unify ec operations

update-fork
MITSUNARI Shigeo 5 years ago
parent 41c11a0f75
commit 2dd76c7b67
  1. 174
      include/mcl/mapto_wb19.hpp
  2. 23
      test/mapto_wb19_test.cpp

@ -39,6 +39,7 @@ inline void hashToFp2(Fp2& out, const void *msg, size_t msgSize, uint8_t ctr, co
namespace local { namespace local {
// y^2 = x^3 + 4(1 + i)
template<class F> template<class F>
struct PointT { struct PointT {
typedef F Fp; typedef F Fp;
@ -56,12 +57,10 @@ struct PointT {
y.clear(); y.clear();
z.clear(); z.clear();
} }
#if 0
bool isEqual(const PointT<F>& rhs) const bool isEqual(const PointT<F>& rhs) const
{ {
return ec::isEqualJacobi(*this, rhs); return ec::isEqualJacobi(*this, rhs);
} }
#endif
}; };
template<class F> F PointT<F>::a_; template<class F> F PointT<F>::a_;
@ -73,9 +72,10 @@ template<class F> int PointT<F>::specialA_;
template<class Fp, class Fp2, class G2> template<class Fp, class Fp2, class G2>
struct MapToG2_WB19 { struct MapToG2_WB19 {
typedef local::PointT<Fp2> Point; typedef local::PointT<Fp2> Point;
Fp2 xi;
Fp half; Fp half;
mpz_class sqrtConst; // (p^2 - 9) / 16 mpz_class sqrtConst; // (p^2 - 9) / 16
Fp2 Ep_a;
Fp2 Ep_b;
Fp2 root4[4]; Fp2 root4[4];
Fp2 etas[4]; Fp2 etas[4];
Fp2 xnum[4]; Fp2 xnum[4];
@ -87,125 +87,17 @@ struct MapToG2_WB19 {
{ {
draftVersion_ = version; draftVersion_ = version;
} }
// should be merged into ec.hpp
template<class G>
void neg(G& Q, const G& P) const
{
Q.x = P.x;
Fp2::neg(Q.y, P.y);
Q.z = P.z;
}
// Jacobi : sqr 4, mul 12, add 11
template<class G>
void add(G& R, const G& P, const G& Q) const
{
if (P.isZero()) {
R = Q;
return;
}
if (Q.isZero()) {
R = Q;
return;
}
Fp2 Z1Z1, Z2Z2, U1, U2, S1, S2;
Fp2::sqr(Z1Z1, P.z);
Fp2::sqr(Z2Z2, Q.z);
Fp2::mul(U1, P.x, Z2Z2);
Fp2::mul(U2, Q.x, Z1Z1);
Fp2::mul(S1, P.y, Q.z);
S1 *= Z2Z2;
Fp2::mul(S2, Q.y, P.z);
S2 *= Z1Z1;
if (U1 == U2 && S1 == S2) {
dbl(R, P);
return;
}
Fp2 H, I, J, rr, V;
Fp2::sub(H, U2, U1);
Fp2::add(I, H, H);
Fp2::sqr(I, I);
Fp2::mul(J, H, I);
Fp2::sub(rr, S2, S1);
rr += rr;
Fp2::mul(V, U1, I);
Fp2::mul(R.z, P.z, Q.z);
R.z *= H;
if (R.z.isZero()) {
R.x.clear();
R.y.clear();
return;
}
R.z += R.z;
Fp2::sqr(R.x, rr);
R.x -= J;
R.x -= V;
R.x -= V;
Fp2::sub(R.y, V, R.x);
R.y *= rr;
S1 *= J;
R.y -= S1;
R.y -= S1;
}
// jacobi : 2M + 5S + 14A
template<class G>
void dblT(G& Q, const G& P) const
{
#if 0
ec::dblJacobi(Q, P, ec::GenericA, Ell2p_a);
#else
Fp2 A, B, C, D, e, f;
Fp2::sqr(A, P.x);
Fp2::sqr(B, P.y);
Fp2::sqr(C, B);
Fp2::add(D, P.x, B);
Fp2::sqr(D, D);
D -= A;
D -= C;
D += D;
Fp2::add(e, A, A);
e += A;
Fp2::sqr(f, e);
Fp2::sub(Q.x, f, D);
Q.x -= D;
Fp2::mul(Q.z, P.y, P.z);
if (Q.z.isZero()) {
Q.x.clear();
Q.y.clear();
return;
}
Q.z += Q.z;
Fp2::sub(Q.y, D, Q.x);
Q.y *= e;
C += C;
C += C;
C += C;
Q.y -= C;
#endif
}
void dbl(Point& Q, const Point& P) const
{
dblT(Q, P);
// ec::dblJacobi(Q, P);
}
// P is on y^2 = x^3 + Ell2p_a x + Ell2p_b
bool isValidPoint(const Point& P) const
{
return ec::isValidJacobi(P);
}
bool isValidPoint(const G2& P) const
{
return P.isValid();
}
void init() void init()
{ {
bool b; bool b;
xi.a = -2; Ep_a.a = 0;
xi.b = -1; Ep_a.b = 240;
Point::a_.a = 0; Ep_b.a = 1012;
Point::a_.b = 240; Ep_b.b = 1012;
Point::b_.a = 1012; Point::a_.clear();
Point::b_.b = 1012; Point::b_.a = 4;
Point::specialA_ = ec::GenericA; Point::b_.b = 4;
Point::specialA_ = ec::Zero;
half = -1; half = -1;
half /= 2; half /= 2;
sqrtConst = Fp::getOp().mp; sqrtConst = Fp::getOp().mp;
@ -310,7 +202,6 @@ struct MapToG2_WB19 {
// refer (xnum, xden, ynum, yden) // refer (xnum, xden, ynum, yden)
void iso3(G2& Q, const Point& P) const void iso3(G2& Q, const Point& P) const
{ {
// assert(isValidPoint(P));
Fp2 zpows[3]; Fp2 zpows[3];
Fp2::sqr(zpows[0], P.z); Fp2::sqr(zpows[0], P.z);
Fp2::sqr(zpows[1], zpows[0]); Fp2::sqr(zpows[1], zpows[0]);
@ -331,9 +222,9 @@ struct MapToG2_WB19 {
Fp2::sqr(t, Q.z); Fp2::sqr(t, Q.z);
Fp2::mul(Q.y, mapvals[2], mapvals[1]); Fp2::mul(Q.y, mapvals[2], mapvals[1]);
Q.y *= t; Q.y *= t;
// assert(Q.isValid());
} }
/* /*
xi = -2-i
(a+bi)*(-2-i) = (b-2a)-(a+2b)i (a+bi)*(-2-i) = (b-2a)-(a+2b)i
*/ */
void mul_xi(Fp2& y, const Fp2& x) const void mul_xi(Fp2& y, const Fp2& x) const
@ -354,22 +245,6 @@ struct MapToG2_WB19 {
if (!x.b.isZero()) return false; if (!x.b.isZero()) return false;
return false; return false;
} }
/*
in : Jacobi [X:Y:Z]
out : Proj [A:B:C]
[X:Y:Z] as Jacobi
= (X/Z^2, Y/Z^3) as Affine
= [X/Z^2:Y/Z^3:1] as Proj
= [XZ:Y:Z^3] as Proj
*/
void toProj(G2& out, const G2& in) const
{
Fp2 z2;
Fp2::sqr(z2, in.z);
Fp2::mul(out.x, in.x, in.z);
out.y = in.y;
Fp2::mul(out.z, in.z, z2);
}
// https://github.com/algorand/bls_sigs_ref // https://github.com/algorand/bls_sigs_ref
void osswu2_help(Point& P, const Fp2& t) const void osswu2_help(Point& P, const Fp2& t) const
{ {
@ -383,20 +258,20 @@ struct MapToG2_WB19 {
den += den2; den += den2;
Fp2 x0_num, x0_den; Fp2 x0_num, x0_den;
Fp2::add(x0_num, den, 1); Fp2::add(x0_num, den, 1);
x0_num *= Point::b_; x0_num *= Ep_b;
if (den.isZero()) { if (den.isZero()) {
Fp2::mul(x0_den, Point::a_, xi); mul_xi(x0_den, Ep_a);
} else { } else {
Fp2::mul(x0_den, -Point::a_, den); Fp2::mul(x0_den, -Ep_a, den);
} }
Fp2 x0_den2, x0_den3, gx0_den, gx0_num; Fp2 x0_den2, x0_den3, gx0_den, gx0_num;
Fp2::sqr(x0_den2, x0_den); Fp2::sqr(x0_den2, x0_den);
Fp2::mul(x0_den3, x0_den2, x0_den); Fp2::mul(x0_den3, x0_den2, x0_den);
gx0_den = x0_den3; gx0_den = x0_den3;
Fp2::mul(gx0_num, Point::b_, gx0_den); Fp2::mul(gx0_num, Ep_b, gx0_den);
Fp2 tmp, tmp1, tmp2; Fp2 tmp, tmp1, tmp2;
Fp2::mul(tmp, Point::a_, x0_num); Fp2::mul(tmp, Ep_a, x0_num);
tmp *= x0_den2; tmp *= x0_den2;
gx0_num += tmp; gx0_num += tmp;
Fp2::sqr(tmp, x0_num); Fp2::sqr(tmp, x0_num);
@ -537,18 +412,6 @@ struct MapToG2_WB19 {
printf("y=%s\n", P.y.getStr(base).c_str()); printf("y=%s\n", P.y.getStr(base).c_str());
printf("z=%s\n", P.z.getStr(base).c_str()); printf("z=%s\n", P.z.getStr(base).c_str());
} }
bool normalizeJacobi(Point& out, const Point& in) const
{
if (in.z.isZero()) return false;
Fp2 t;
Fp2::inv(t, in.z);
Fp2::mul(out.y, in.y, t);
Fp2::sqr(t, t);
Fp2::mul(out.x, in.x, t);
out.y *= t;
out.z = 1;
return true;
}
void opt_swu2_map(G2& P, const Fp2& t, const Fp2 *t2 = 0) const void opt_swu2_map(G2& P, const Fp2& t, const Fp2 *t2 = 0) const
{ {
Point Pp; Point Pp;
@ -556,10 +419,11 @@ struct MapToG2_WB19 {
if (t2) { if (t2) {
Point P2; Point P2;
osswu2_help(P2, *t2); osswu2_help(P2, *t2);
add(Pp, Pp, P2); ec::addJacobi(Pp, Pp, P2);
} }
iso3(P, Pp); iso3(P, Pp);
clear_h2(P, P); clear_h2(P, P);
// if (t2 && !ec::isValidJacobi(P)) { puts("QQQ"); }
} }
// hash-to-curve-06 // hash-to-curve-06
void hashToFp2v6(Fp2 out[2], const void *msg, size_t msgSize, const void *dst, size_t dstSize) const void hashToFp2v6(Fp2 out[2], const void *msg, size_t msgSize, const void *dst, size_t dstSize) const

@ -157,11 +157,11 @@ void py_ecc_optimized_swu_G2(const MapTo& mapto, Point& P, const Fp2& t)
// (t^2 * xi)^2 + (t^2 * xi) // (t^2 * xi)^2 + (t^2 * xi)
Fp2::add(deno, t2xi2, t2xi); Fp2::add(deno, t2xi2, t2xi);
Fp2::add(nume, deno, 1); Fp2::add(nume, deno, 1);
nume *= Point::b_; nume *= mapto.Ep_b;
if (deno.isZero()) { if (deno.isZero()) {
Fp2::mul(deno, Point::a_, mapto.xi); mapto.mul_xi(deno, mapto.Ep_a);
} else { } else {
deno *= -Point::a_; deno *= -mapto.Ep_a;
} }
Fp2 u, v; Fp2 u, v;
{ {
@ -169,8 +169,8 @@ void py_ecc_optimized_swu_G2(const MapTo& mapto, Point& P, const Fp2& t)
Fp2::sqr(deno2, deno); Fp2::sqr(deno2, deno);
Fp2::mul(v, deno2, deno); Fp2::mul(v, deno2, deno);
Fp2::mul(u, Point::b_, v); Fp2::mul(u, mapto.Ep_b, v);
Fp2::mul(tmp, Point::a_, nume); Fp2::mul(tmp, mapto.Ep_a, nume);
tmp *= deno2; tmp *= deno2;
u += tmp; u += tmp;
Fp2::sqr(tmp, nume); Fp2::sqr(tmp, nume);
@ -527,12 +527,11 @@ void osswu2_helpTest(const T& mapto)
CYBOZU_TEST_EQUAL(P.x, x); CYBOZU_TEST_EQUAL(P.x, x);
CYBOZU_TEST_EQUAL(P.y, y); CYBOZU_TEST_EQUAL(P.y, y);
CYBOZU_TEST_EQUAL(P.z, z); CYBOZU_TEST_EQUAL(P.z, z);
CYBOZU_TEST_ASSERT(mapto.isValidPoint(P)); // CYBOZU_TEST_ASSERT(P.isValid());
} }
} }
template<class T> void addTest()
void addTest(const T& mapto)
{ {
const struct Tbl { const struct Tbl {
PointStr P; PointStr P;
@ -590,10 +589,8 @@ void addTest(const T& mapto)
set(Q, tbl[i].Q); set(Q, tbl[i].Q);
set(R, tbl[i].R); set(R, tbl[i].R);
Point E; Point E;
mapto.add(E, P, Q); ec::addJacobi(E, P, Q);
CYBOZU_TEST_EQUAL(R.x, E.x); CYBOZU_TEST_ASSERT(R.isEqual(E));
CYBOZU_TEST_EQUAL(R.y, E.y);
CYBOZU_TEST_EQUAL(R.z, E.z);
} }
} }
@ -878,7 +875,7 @@ CYBOZU_TEST_AUTO(test)
py_eccTest(mapto); py_eccTest(mapto);
py_eccTest2(mapto); py_eccTest2(mapto);
osswu2_helpTest(mapto); osswu2_helpTest(mapto);
addTest(mapto); addTest();
iso3Test(mapto); iso3Test(mapto);
testSign(mapto); testSign(mapto);
ethFp2ToG2test(); ethFp2ToG2test();

Loading…
Cancel
Save