refactor ec

update-fork
MITSUNARI Shigeo 5 years ago
parent 75b1a8adc7
commit 9c62b3d964
  1. 158
      include/mcl/ec.hpp
  2. 64
      include/mcl/mapto_wb19.hpp
  3. 2
      test/ec_test.cpp

@ -71,9 +71,9 @@ bool get_a_flag(const mcl::Fp2T<F>& x)
template<class F> template<class F>
void normalizeJacobi(F& x, F& y, F& z) void normalizeJacobi(F& x, F& y, F& z)
{ {
assert(!z.isZero()); if (z.isZero()) return;
F rz2;
F::inv(z, z); F::inv(z, z);
F rz2;
F::sqr(rz2, z); F::sqr(rz2, z);
x *= rz2; x *= rz2;
y *= rz2; y *= rz2;
@ -81,6 +81,23 @@ void normalizeJacobi(F& x, F& y, F& z)
z = 1; z = 1;
} }
// (x/z^2, y/z^3)
template<class F>
bool isEqualJacobi(const F& x1, const F& y1, const F& z1, const F& x2, const F& y2, const F& z2)
{
F s1, s2, t1, t2;
F::sqr(s1, z1);
F::sqr(s2, z2);
F::mul(t1, x1, s2);
F::mul(t2, x2, s1);
if (t1 != t2) return false;
F::mul(t1, y1, s2);
F::mul(t2, y2, s1);
t1 *= z2;
t2 *= z1;
return t1 == t2;
}
// Y^2 == X(X^2 + aZ^4) + bZ^6 // Y^2 == X(X^2 + aZ^4) + bZ^6
template<class F> template<class F>
bool isValidJacobi(const F& x, const F& y, const F& z, const F& a, const F& b) bool isValidJacobi(const F& x, const F& y, const F& z, const F& a, const F& b)
@ -100,10 +117,9 @@ bool isValidJacobi(const F& x, const F& y, const F& z, const F& a, const F& b)
} }
/* /*
|a=0|-3| generic a = 0 3M + 4S + 12A
sqr| 4| 6| 6 a = -3 3M + 6S + 13A
mul| 3| 3| 4 generic 4M + 6S + 13A
add| 12|13|13
*/ */
template<class E> template<class E>
void dblJacobi(E& R, const E& P, int specialA, const typename E::Fp& a) void dblJacobi(E& R, const E& P, int specialA, const typename E::Fp& a)
@ -113,6 +129,65 @@ void dblJacobi(E& R, const E& P, int specialA, const typename E::Fp& a)
R.clear(); R.clear();
return; return;
} }
#if 0
// a = 0 M + 7S + 15A
// a = -3 M + 8S + 18A
// generic 2M + 8S + 16A
F x2, y2, y4, z2, s, m, t;
F::sqr(x2, P.x);
F::sqr(y2, P.y);
F::sqr(y4, y2);
const bool isPzOne = P.z.isOne();
if (isPzOne) {
z2 = P.z;
} else {
F::sqr(z2, P.z);
}
F::add(s, P.x, y2);
F::sqr(s, s);
s -= x2;
s -= y4;
s += s;
F::add(m, x2, x2);
m += x2;
switch (specialA) {
case Zero:
break;
case Minus3:
if (isPzOne) {
t = z2;
} else {
F::sqr(t, z2);
}
m -= t;
m -= t;
m -= t;
break;
case GenericA:
default:
if (isPzOne) {
m += a;
} else {
F::sqr(t, z2);
t *= a;
m += t;
}
break;
}
F::sqr(t, m);
t -= s;
F::sub(R.x, t, s); // m^2 - 2s
F::add(R.z, P.y, P.z);
F::sqr(R.z, R.z);
R.z -= y2;
R.z -= z2;
F::sub(R.y, s, R.x);
R.y *= m;
F::add(t, y4, y4);
t += t;
t += t;
R.y -= t;
#else
F S, M, t, y2; F S, M, t, y2;
F::sqr(y2, P.y); F::sqr(y2, P.y);
F::mul(S, P.x, y2); F::mul(S, P.x, y2);
@ -166,13 +241,10 @@ void dblJacobi(E& R, const E& P, int specialA, const typename E::Fp& a)
F::sub(R.y, S, R.x); F::sub(R.y, S, R.x);
R.y *= M; R.y *= M;
R.y -= y2; R.y -= y2;
#endif
} }
/* // 7M + 4S + 7A
sqr| 4
mul| 12
add| 7
*/
template<class E, class F> template<class E, class F>
void addJacobi(E& R, const E& P, const E& Q, int specialA, const F& a) void addJacobi(E& R, const E& P, const E& Q, int specialA, const F& a)
{ {
@ -252,7 +324,7 @@ void addJacobi(E& R, const E& P, const E& Q, int specialA, const F& a)
template<class F> template<class F>
void normalizeProj(F& x, F& y, F& z) void normalizeProj(F& x, F& y, F& z)
{ {
assert(!z.isZero()); if (z.isZero()) return;
F::inv(z, z); F::inv(z, z);
x *= z; x *= z;
y *= z; y *= z;
@ -276,10 +348,23 @@ bool isValidProj(const F& x, const F& y, const F& z, const F& a, const F& b)
return y2 == t; return y2 == t;
} }
// (x/z, y/z)
template<class F>
bool isEqualProj(const F& x1, const F& y1, const F& z1, const F& x2, const F& y2, const F& z2)
{
F t1, t2;
F::mul(t1, x1, z2);
F::mul(t2, x2, z1);
if (t1 != t2) return false;
F::mul(t1, y1, z2);
F::mul(t2, y2, z1);
return t1 == t2;
}
/* /*
|a=0|-3| generic |a=0|-3| generic
sqr| 4| 5| 5
mul| 8| 8| 9 mul| 8| 8| 9
sqr| 4| 5| 5
add| 11|12|12 add| 11|12|12
*/ */
template<class E, class F> template<class E, class F>
@ -348,8 +433,8 @@ void dblProj(E& R, const E& P, int specialA, const F& a)
} }
/* /*
sqr| 2
mul| 12 mul| 12
sqr| 2
add| 7 add| 7
*/ */
template<class E, class F> template<class E, class F>
@ -523,22 +608,6 @@ public:
return isZero() || z.isOne(); return isZero() || z.isOne();
} }
private: private:
void normalizeJacobi()
{
ec::normalizeJacobi(x, y, z);
}
void normalizeProj()
{
ec::normalizeProj(x, y, z);
}
bool isValidJacobi() const
{
return ec::isValidJacobi(x, y, z, a_, b_);
}
bool isValidProj() const
{
return ec::isValidProj(x, y, z, a_, b_);
}
bool isValidAffine() const bool isValidAffine() const
{ {
return ec::isValidAffine(x, y, a_, b_); return ec::isValidAffine(x, y, a_, b_);
@ -546,13 +615,12 @@ private:
public: public:
void normalize() void normalize()
{ {
if (isNormalized()) return;
switch (mode_) { switch (mode_) {
case ec::Jacobi: case ec::Jacobi:
normalizeJacobi(); ec::normalizeJacobi(x, y, z);
break; break;
case ec::Proj: case ec::Proj:
normalizeProj(); ec::normalizeProj(x, y, z);
break; break;
} }
} }
@ -617,15 +685,15 @@ public:
} }
bool isValid() const bool isValid() const
{ {
if (isZero()) return true;
switch (mode_) { switch (mode_) {
case ec::Jacobi: case ec::Jacobi:
if (!isValidJacobi()) return false; if (!ec::isValidJacobi(x, y, z, a_, b_)) return false;
break; break;
case ec::Proj: case ec::Proj:
if (!isValidProj()) return false; if (!ec::isValidProj(x, y, z, a_, b_)) return false;
break; break;
case ec::Affine: case ec::Affine:
if (z.isZero()) return true;
if (!isValidAffine()) return false; if (!isValidAffine()) return false;
break; break;
} }
@ -898,7 +966,7 @@ public:
z.clear(); z.clear();
return; return;
} }
goto verifyValidness; goto verifyValidAffine;
} }
if (ioMode & (IoSerialize | IoSerializeHexStr)) { if (ioMode & (IoSerialize | IoSerializeHexStr)) {
const size_t n = Fp::getByteSize(); const size_t n = Fp::getByteSize();
@ -982,7 +1050,7 @@ public:
x.load(pb, is, ioMode); if (!*pb) return; x.load(pb, is, ioMode); if (!*pb) return;
if (c == '1') { if (c == '1') {
y.load(pb, is, ioMode); if (!*pb) return; y.load(pb, is, ioMode); if (!*pb) return;
goto verifyValidness; goto verifyValidAffine;
} else if (c == '2' || c == '3') { } else if (c == '2' || c == '3') {
bool isYodd = c == '3'; bool isYodd = c == '3';
*pb = getYfromX(y, x, isYodd); *pb = getYfromX(y, x, isYodd);
@ -1008,7 +1076,7 @@ public:
*pb = true; *pb = true;
} }
return; return;
verifyValidness: verifyValidAffine:
if (!isValidAffine()) { if (!isValidAffine()) {
*pb = false; *pb = false;
return; return;
@ -1063,9 +1131,15 @@ public:
EcT operator-() const { EcT x; neg(x, *this); return x; } EcT operator-() const { EcT x; neg(x, *this); return x; }
bool operator==(const EcT& rhs) const bool operator==(const EcT& rhs) const
{ {
EcT R; switch (mode_) {
sub(R, *this, rhs); // QQQ : optimized later case ec::Jacobi:
return R.isZero(); return ec::isEqualJacobi(x, y, z, rhs.x, rhs.y, rhs.z);
case ec::Proj:
return ec::isEqualProj(x, y, z, rhs.x, rhs.y, rhs.z);
case ec::Affine:
default:
return x == rhs.x && y == rhs.y && z == rhs.z;
}
} }
bool operator!=(const EcT& rhs) const { return !operator==(rhs); } bool operator!=(const EcT& rhs) const { return !operator==(rhs); }
bool operator<(const EcT& rhs) const bool operator<(const EcT& rhs) const

@ -37,6 +37,26 @@ inline void hashToFp2(Fp2& out, const void *msg, size_t msgSize, uint8_t ctr, co
} }
} }
namespace local {
template<class F>
struct PointT {
typedef F Fp;
F x, y, z;
bool isZero() const
{
return z.isZero();
}
void clear()
{
x.clear();
y.clear();
z.clear();
}
};
} // mcl::local
template<class Fp, class Fp2, class G2> template<class Fp, class Fp2, class G2>
struct MapToG2_WB19 { struct MapToG2_WB19 {
Fp2 xi; Fp2 xi;
@ -51,17 +71,11 @@ struct MapToG2_WB19 {
Fp2 ynum[4]; Fp2 ynum[4];
Fp2 yden[4]; Fp2 yden[4];
int draftVersion_; int draftVersion_;
typedef local::PointT<Fp2> Point;
void setDraftVersion(int version) void setDraftVersion(int version)
{ {
draftVersion_ = version; draftVersion_ = version;
} }
struct Point {
Fp2 x, y, z;
bool isZero() const
{
return z.isZero();
}
};
// should be merged into ec.hpp // should be merged into ec.hpp
template<class G> template<class G>
void neg(G& Q, const G& P) const void neg(G& Q, const G& P) const
@ -70,7 +84,7 @@ struct MapToG2_WB19 {
Fp2::neg(Q.y, P.y); Fp2::neg(Q.y, P.y);
Q.z = P.z; Q.z = P.z;
} }
// Jacobi // Jacobi : sqr 4, mul 12, add 11
template<class G> template<class G>
void add(G& R, const G& P, const G& Q) const void add(G& R, const G& P, const G& Q) const
{ {
@ -121,9 +135,13 @@ struct MapToG2_WB19 {
R.y -= S1; R.y -= S1;
R.y -= S1; R.y -= S1;
} }
// jacobi : sqr 5, mul 2, add 14
template<class G> template<class G>
void dbl(G& Q, const G& P) const 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 A, B, C, D, E, F;
Fp2::sqr(A, P.x); Fp2::sqr(A, P.x);
Fp2::sqr(B, P.y); Fp2::sqr(B, P.y);
@ -151,22 +169,24 @@ struct MapToG2_WB19 {
C += C; C += C;
C += C; C += C;
Q.y -= C; Q.y -= C;
#endif
}
void dbl(Point& Q, const Point& P) const
{
dblT(Q, P);
}
void dbl(G2& Q, const G2& P) const
{
dblT(Q, P);
} }
// P is on y^2 = x^3 + Ell2p_a x + Ell2p_b // P is on y^2 = x^3 + Ell2p_a x + Ell2p_b
bool isValidPoint(const Point& P) const bool isValidPoint(const Point& P) const
{ {
Fp2 y2, x2, z2, z4, t; return ec::isValidJacobi(P.x, P.y, P.z, Ell2p_a, Ell2p_b);
Fp2::sqr(x2, P.x); }
Fp2::sqr(y2, P.y); bool isValidPoint(const G2& P) const
Fp2::sqr(z2, P.z); {
Fp2::sqr(z4, z2); return P.isValid();
Fp2::mul(t, z4, Ell2p_a);
t += x2;
t *= P.x;
z4 *= z2;
z4 *= Ell2p_b;
t += z4;
return y2 == t;
} }
void init() void init()
{ {
@ -617,7 +637,7 @@ struct MapToG2_WB19 {
void clear_h2(G2& Q, const G2& P) const void clear_h2(G2& Q, const G2& P) const
{ {
#if 0 #if 0
mcl::bn::BN::param.mapTo.mulByCofactorBLS12fast(Q, P); bn::param.mapTo.mulByCofactorBLS12fast(Q, P);
#else #else
G2 work, work2; G2 work, work2;
h2_chain(work, P); h2_chain(work, P);

@ -612,7 +612,7 @@ CYBOZU_TEST_AUTO(all)
{ {
if (g_partial & (1 << 3)) { if (g_partial & (1 << 3)) {
const struct mcl::EcParam para3[] = { const struct mcl::EcParam para3[] = {
// mcl::ecparam::p160_1, mcl::ecparam::p160_1,
mcl::ecparam::secp160k1, mcl::ecparam::secp160k1,
mcl::ecparam::secp192k1, mcl::ecparam::secp192k1,
mcl::ecparam::NIST_P192, mcl::ecparam::NIST_P192,

Loading…
Cancel
Save