add mclBn_setETHserialization

pull/2/head
MITSUNARI Shigeo 6 years ago
parent 0234589658
commit f1d0865f1c
  1. 6
      include/mcl/bn.h
  2. 103
      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);
/*
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

@ -20,6 +20,8 @@
namespace mcl {
template<class _Fp> class Fp2T;
namespace ec {
enum Mode {
@ -27,6 +29,25 @@ enum Mode {
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
/*
@ -708,28 +729,44 @@ public:
EcT P(*this);
P.normalize();
if (ioMode & (IoSerialize | IoSerializeHexStr)) {
/*
if (isMSBserialize()) {
// n bytes
x | (y.isOdd ? 0x80 : 0)
} else {
// n + 1 bytes
(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()) {
memset(buf, 0, n + adj);
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 {
cybozu::MemoryOutputStream mos(buf + adj, n);
P.x.save(pb, mos, IoSerialize); if (!*pb) return;
if (adj) {
buf[0] = P.y.isOdd() ? 3 : 2;
/*
if (isMSBserialize()) {
// n bytes
x | (y.isOdd ? 0x80 : 0)
} else {
// n + 1 bytes
(y.isOdd ? 3 : 2), x
}
*/
if (isZero()) {
memset(buf, 0, n + adj);
} else {
if (P.y.isOdd()) {
buf[n - 1] |= 0x80;
cybozu::MemoryOutputStream mos(buf + adj, n);
P.x.save(pb, mos, IoSerialize); if (!*pb) return;
if (adj) {
buf[0] = P.y.isOdd() ? 3 : 2;
} else {
if (P.y.isOdd()) {
buf[n - 1] |= 0x80;
}
}
}
}
@ -789,6 +826,38 @@ public:
*pb = false;
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)) {
clear();
*pb = true;

@ -529,6 +529,7 @@ public:
if (getBitSize() != 381) return;
isETHserialization_ = ETHserialization;
}
static inline bool isETHserialization() { return isETHserialization_; }
static inline int getIoMode() { return ioMode_; }
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))

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

@ -307,7 +307,18 @@ void testTrivial(const G1& P, const G2& Q)
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
const struct FpTbl {
@ -329,6 +340,17 @@ void testSerialize()
CYBOZU_TEST_EQUAL(y.deserialize(buf, n, mcl::IoSerializeHexStr), n);
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);
}
@ -350,7 +372,7 @@ CYBOZU_TEST_AUTO(naive)
clk.put();
return;
#endif
testSerialize();
testSerialize(P, Q);
testParam(ts);
testIo(P, Q);
// testFp12pow(P, Q);

Loading…
Cancel
Save