add mclBn_setETHserialization

pull/2/head
MITSUNARI Shigeo 6 years ago
parent 0234589658
commit f1d0865f1c
  1. 6
      include/mcl/bn.h
  2. 75
      include/mcl/ec.hpp
  3. 1
      include/mcl/fp.hpp
  4. 5
      include/mcl/impl/bn_c_impl.hpp
  5. 26
      test/bls12_test.cpp

@ -177,6 +177,12 @@ MCLBN_DLL_API mclSize mclBn_getCurveOrder(char *buf, mclSize maxBufSize);
*/ */
MCLBN_DLL_API mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize); MCLBN_DLL_API mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize);
/*
set ETH serialization mode for BLS12-381
@param ETHserialization [in] 1:enable, 0:disable
@note ignore the flag if curve is not BLS12-381
*/
MCLBN_DLL_API void mclBn_setETHserialization(int ETHserialization);
//////////////////////////////////////////////// ////////////////////////////////////////////////
/* /*
deserialize deserialize

@ -20,6 +20,8 @@
namespace mcl { namespace mcl {
template<class _Fp> class Fp2T;
namespace ec { namespace ec {
enum Mode { enum Mode {
@ -27,6 +29,25 @@ enum Mode {
Proj = 1 Proj = 1
}; };
namespace local {
// x is negative <=> x < half(:=(p+1)/2) <=> a = 1
template<class Fp>
bool get_a_flag(const Fp& x)
{
return x.isNegative();
}
// Im(x) is negative <=> Im(x) < half(:=(p+1)/2) <=> a = 1
template<class Fp>
bool get_a_flag(const mcl::Fp2T<Fp>& x)
{
return get_a_flag(x.b); // x = a + bi
}
} // mcl::ec::local
} // mcl::ec } // mcl::ec
/* /*
@ -708,6 +729,24 @@ public:
EcT P(*this); EcT P(*this);
P.normalize(); P.normalize();
if (ioMode & (IoSerialize | IoSerializeHexStr)) { if (ioMode & (IoSerialize | IoSerializeHexStr)) {
const size_t n = Fp::getByteSize();
const size_t adj = isMSBserialize() ? 0 : 1;
char buf[sizeof(Fp) + 1];
if (Fp::BaseFp::isETHserialization()) {
const char c_flag = 0x80;
const char b_flag = 0x40;
const char a_flag = 0x20;
if (P.isZero()) {
buf[0] = c_flag | b_flag;
memset(buf + 1, 0, n - 1);
} else {
cybozu::MemoryOutputStream mos(buf, n);
P.x.save(pb, mos, IoSerialize); if (!*pb) return;
char cba = c_flag;
if (ec::local::get_a_flag(P.y)) cba |= a_flag;
buf[0] |= cba;
}
} else {
/* /*
if (isMSBserialize()) { if (isMSBserialize()) {
// n bytes // n bytes
@ -717,9 +756,6 @@ public:
(y.isOdd ? 3 : 2), x (y.isOdd ? 3 : 2), x
} }
*/ */
const size_t n = Fp::getByteSize();
const size_t adj = isMSBserialize() ? 0 : 1;
char buf[sizeof(Fp) + 1];
if (isZero()) { if (isZero()) {
memset(buf, 0, n + adj); memset(buf, 0, n + adj);
} else { } else {
@ -733,6 +769,7 @@ public:
} }
} }
} }
}
if (ioMode & IoSerializeHexStr) { if (ioMode & IoSerializeHexStr) {
mcl::fp::writeHexStr(pb, os, buf, n + adj); mcl::fp::writeHexStr(pb, os, buf, n + adj);
} else { } else {
@ -789,6 +826,38 @@ public:
*pb = false; *pb = false;
return; return;
} }
if (Fp::BaseFp::isETHserialization()) {
const char c_flag = 0x80;
const char b_flag = 0x40;
const char a_flag = 0x20;
*pb = false;
if ((buf[0] & c_flag) == 0) { // assume compressed
return;
}
if (buf[0] & b_flag) { // infinity
if (buf[0] != (c_flag | b_flag)) return;
for (size_t i = 1; i < n - 1; i++) {
if (buf[i]) return;
}
clear();
*pb = true;
return;
}
bool a = (buf[0] & a_flag) != 0;
buf[0] &= ~(c_flag | b_flag | a_flag);
mcl::fp::local::byteSwap(buf, n);
x.setArray(pb, buf, n);
if (!*pb) return;
getWeierstrass(y, x);
if (!Fp::squareRoot(y, y)) {
*pb = false;
return;
}
if (ec::local::get_a_flag(y) ^ a) {
Fp::neg(y, y);
}
return;
}
if (fp::isZeroArray(buf, n1)) { if (fp::isZeroArray(buf, n1)) {
clear(); clear();
*pb = true; *pb = true;

@ -529,6 +529,7 @@ public:
if (getBitSize() != 381) return; if (getBitSize() != 381) return;
isETHserialization_ = ETHserialization; isETHserialization_ = ETHserialization;
} }
static inline bool isETHserialization() { return isETHserialization_; }
static inline int getIoMode() { return ioMode_; } static inline int getIoMode() { return ioMode_; }
static inline size_t getModBitLen() { return getBitSize(); } static inline size_t getModBitLen() { return getBitSize(); }
static inline void setHashFunc(uint32_t hash(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize)) static inline void setHashFunc(uint32_t hash(void *out, uint32_t maxOutSize, const void *msg, uint32_t msgSize))

@ -113,6 +113,11 @@ mclSize mclBn_getFieldOrder(char *buf, mclSize maxBufSize)
return Fp::getModulo(buf, maxBufSize); return Fp::getModulo(buf, maxBufSize);
} }
void mclBn_setETHserialization(int ETHserialization)
{
Fp::setETHserialization(ETHserialization == 1);
}
//////////////////////////////////////////////// ////////////////////////////////////////////////
// set zero // set zero
void mclBnFr_clear(mclBnFr *x) void mclBnFr_clear(mclBnFr *x)

@ -307,7 +307,18 @@ void testTrivial(const G1& P, const G2& Q)
CYBOZU_TEST_EQUAL(e, 1); CYBOZU_TEST_EQUAL(e, 1);
} }
void testSerialize() template<class T>
void deserializeAndSerialize(const T& x)
{
char buf[1024];
size_t n = x.serialize(buf, sizeof(buf));
CYBOZU_TEST_ASSERT(n > 0);
T y;
CYBOZU_TEST_EQUAL(y.deserialize(buf, n), n);
CYBOZU_TEST_EQUAL(x, y);
}
void testSerialize(const G1& P, const G2& Q)
{ {
Fp::setETHserialization(true); // big endian Fp::setETHserialization(true); // big endian
const struct FpTbl { const struct FpTbl {
@ -329,6 +340,17 @@ void testSerialize()
CYBOZU_TEST_EQUAL(y.deserialize(buf, n, mcl::IoSerializeHexStr), n); CYBOZU_TEST_EQUAL(y.deserialize(buf, n, mcl::IoSerializeHexStr), n);
CYBOZU_TEST_EQUAL(x, y); CYBOZU_TEST_EQUAL(x, y);
} }
deserializeAndSerialize(P);
deserializeAndSerialize(-P);
G1 zero1;
zero1.clear();
deserializeAndSerialize(zero1);
deserializeAndSerialize(Q);
deserializeAndSerialize(-Q);
G2 zero2;
zero2.clear();
deserializeAndSerialize(zero2);
Fp::setETHserialization(false); Fp::setETHserialization(false);
} }
@ -350,7 +372,7 @@ CYBOZU_TEST_AUTO(naive)
clk.put(); clk.put();
return; return;
#endif #endif
testSerialize(); testSerialize(P, Q);
testParam(ts); testParam(ts);
testIo(P, Q); testIo(P, Q);
// testFp12pow(P, Q); // testFp12pow(P, Q);

Loading…
Cancel
Save