add IoTight repl for elliptic curve

dev
MITSUNARI Shigeo 8 years ago
parent c048593b44
commit 9aca9c9b01
  1. 54
      include/mcl/ec.hpp
  2. 32
      include/mcl/fp.hpp
  3. 21
      src/fp.cpp
  4. 24
      test/ec_test.cpp

@ -636,19 +636,43 @@ public:
return z.isZero(); return z.isZero();
#endif #endif
} }
static inline bool isIoTightSupported()
{
return !b_.isZero() && (Fp::getBitSize() & 7) != 0;
}
/* /*
"0" ; infinity "0" ; infinity
"1 <x> <y>" ; not compressed "1 <x> <y>" ; not compressed
"2 <x>" ; compressed for even y "2 <x>" ; compressed for even y
"3 <x>" ; compressed for odd y "3 <x>" ; compressed for odd y
tight repl of EC over a prime
the size of str must be equal to Fp::getByteSize()
[0] ; infinity
<x> ; for even y
<x>|1 ; for odd y ; |1 means set MSB of x
*/ */
void getStr(std::string& str, int ioMode = 10) const void getStr(std::string& str, int ioMode = 10) const
{ {
normalize();
if (ioMode & IoTight) {
if (!isIoTightSupported()) throw cybozu::Exception("EcT:getStr:not supported ioMode") << ioMode;
const size_t n = Fp::getByteSize();
if (isZero()) {
str.resize(n, 0);
return;
}
x.getStr(str, ioMode);
assert(str.size() == n && (str[n - 1] & 0x80) != 0);
if (y.isOdd()) {
str[n - 1] |= 0x80;
}
return;
}
if (isZero()) { if (isZero()) {
str = '0'; str = '0';
return; return;
} }
normalize();
const char *sep = Fp::BaseFp::getIoSeparator(); const char *sep = Fp::BaseFp::getIoSeparator();
if (compressedExpression_) { if (compressedExpression_) {
str = y.isOdd() ? '3' : '2'; str = y.isOdd() ? '3' : '2';
@ -711,8 +735,34 @@ public:
} }
return is; return is;
} }
void setStr(const std::string& str) void setStr(const std::string& str, int ioMode = 0)
{ {
if (ioMode & IoTight) {
if (!isIoTightSupported()) throw cybozu::Exception("EcT:operator>>:not supported ioMode") << ioMode;
uint8_t buf[Fp::maxSize * sizeof(fp::Unit)];
const size_t n = Fp::getByteSize();
if (str.size() != n) {
throw cybozu::Exception("EcT:setStr:bad size") << str.size() << n;
}
memcpy(buf, str.c_str(), n);
if (fp::isZeroArray(buf, n)) {
clear();
return;
}
#ifdef MCL_EC_USE_AFFINE
inf_ = false;
#else
z = 1;
#endif
bool isYodd = (buf[n - 1] >> 7) != 0;
buf[n - 1] &= 0x7f;
x.setArray(buf, n);
getYfromX(y, x, isYodd);
if (verifyOrder_ && !isValidOrder()) {
throw cybozu::Exception("EcT:setStr:bad order") << *this;
}
return;
}
std::istringstream is(str); std::istringstream is(str);
if (!(is >> *this)) { if (!(is >> *this)) {
throw cybozu::Exception("EcT:setStr:bad str") << str; throw cybozu::Exception("EcT:setStr:bad str") << str;

@ -43,14 +43,15 @@ enum IoMode {
IoBinPrefix = IoBin | IoPrefix, IoBinPrefix = IoBin | IoPrefix,
IoHexPrefix = IoHex | IoPrefix, IoHexPrefix = IoHex | IoPrefix,
IoArray = 32, // array of Unit(fixed size) IoArray = 32, // array of Unit(fixed size)
IoArrayRaw = 64 // raw array of Unit without Montgomery conversion IoArrayRaw = 64, // raw array of Unit without Montgomery conversion
IoTight = 128 // tight repr of Ec
}; };
namespace fp { namespace fp {
static inline const char* getIoSeparator(int ioMode) static inline const char* getIoSeparator(int ioMode)
{ {
return (ioMode & (IoArray | IoArrayRaw)) ? "" : " "; return (ioMode & (IoArray | IoArrayRaw | IoTight)) ? "" : " ";
} }
static inline int detectIoMode(int ioMode, const std::ios_base& ios) static inline int detectIoMode(int ioMode, const std::ios_base& ios)
@ -76,9 +77,9 @@ void arrayToStr(std::string& str, const Unit *x, size_t n, int base, bool withPr
bool strToMpzArray(size_t *pBitSize, Unit *y, size_t maxBitSize, mpz_class& x, const std::string& str, int base); bool strToMpzArray(size_t *pBitSize, Unit *y, size_t maxBitSize, mpz_class& x, const std::string& str, int base);
// copy src to dst as little endian // copy src to dst as little endian
void copyUnitToByteAsLE(void *dst, const Unit *src, size_t byteSize); void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize);
// copy src to dst as little endian // copy src to dst as little endian
void copyByteToUnitAsLE(Unit *dst, const void *src, size_t byteSize); void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize);
void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask); void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool doMask);
uint64_t getUint64(bool *pb, const fp::Block& b); uint64_t getUint64(bool *pb, const fp::Block& b);
@ -102,7 +103,9 @@ template<class tag = FpTag, size_t maxBitSize = MCL_MAX_BIT_SIZE>
class FpT : public fp::Operator<FpT<tag, maxBitSize> > { class FpT : public fp::Operator<FpT<tag, maxBitSize> > {
typedef fp::Unit Unit; typedef fp::Unit Unit;
typedef fp::Operator<FpT<tag, maxBitSize> > Operator; typedef fp::Operator<FpT<tag, maxBitSize> > Operator;
public:
static const size_t maxSize = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize; static const size_t maxSize = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize;
private:
template<class tag2, size_t maxBitSize2> friend class FpT; template<class tag2, size_t maxBitSize2> friend class FpT;
Unit v_[maxSize]; Unit v_[maxSize];
static fp::Op op_; static fp::Op op_;
@ -235,11 +238,11 @@ public:
} }
void setStr(const std::string& str, int ioMode = 0) void setStr(const std::string& str, int ioMode = 0)
{ {
if (ioMode & (IoArray | IoArrayRaw)) { if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
const size_t n = getByteSize(); const size_t n = getByteSize();
if (str.size() != n) throw cybozu::Exception("FpT:setStr:bad size") << str.size() << n << ioMode; if (str.size() != n) throw cybozu::Exception("FpT:setStr:bad size") << str.size() << n << ioMode;
if (ioMode & IoArrayRaw) { if (ioMode & IoArrayRaw) {
fp::copyByteToUnitAsLE(v_, str.c_str(), n); fp::copyByteToUnitAsLE(v_, reinterpret_cast<const uint8_t*>(str.c_str()), n);
if (!isValid()) throw cybozu::Exception("FpT:setStr:bad value") << str; if (!isValid()) throw cybozu::Exception("FpT:setStr:bad value") << str;
} else { } else {
setArray(&str[0], n); setArray(&str[0], n);
@ -302,17 +305,16 @@ public:
} }
void getStr(std::string& str, int ioMode = 10) const void getStr(std::string& str, int ioMode = 10) const
{ {
const size_t n = getByteSize();
if (ioMode & IoArrayRaw) {
str.resize(n);
fp::copyUnitToByteAsLE(&str[0], v_, str.size());
return;
}
fp::Block b; fp::Block b;
const size_t n = getByteSize();
const Unit *p = v_;
if (!(ioMode & IoArrayRaw)) {
getBlock(b); getBlock(b);
if (ioMode & IoArray) { p = b.p;
}
if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
str.resize(n); str.resize(n);
fp::copyUnitToByteAsLE(&str[0], b.p, str.size()); fp::copyUnitToByteAsLE(reinterpret_cast<uint8_t*>(&str[0]), p, str.size());
return; return;
} }
fp::arrayToStr(str, b.p, b.n, ioMode & ~IoPrefix, (ioMode & IoPrefix) != 0); fp::arrayToStr(str, b.p, b.n, ioMode & ~IoPrefix, (ioMode & IoPrefix) != 0);
@ -410,7 +412,7 @@ public:
{ {
int ioMode = fp::detectIoMode(getIoMode(), is); int ioMode = fp::detectIoMode(getIoMode(), is);
std::string str; std::string str;
if (ioMode & (IoArray | IoArrayRaw)) { if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
str.resize(getByteSize()); str.resize(getByteSize());
is.read(&str[0], str.size()); is.read(&str[0], str.size());
} else { } else {

@ -485,35 +485,33 @@ void arrayToStr(std::string& str, const Unit *x, size_t n, int base, bool withPr
} }
} }
void copyUnitToByteAsLE(void *dst, const Unit *src, size_t byteSize) void copyUnitToByteAsLE(uint8_t *dst, const Unit *src, size_t byteSize)
{ {
uint8_t *p = reinterpret_cast<uint8_t*>(dst);
while (byteSize >= sizeof(Unit)) { while (byteSize >= sizeof(Unit)) {
setUnitAsLE(p, *src++); setUnitAsLE(dst, *src++);
p += sizeof(Unit); dst += sizeof(Unit);
byteSize -= sizeof(Unit); byteSize -= sizeof(Unit);
} }
if (byteSize == 0) return; if (byteSize == 0) return;
Unit x = *src; Unit x = *src;
while (byteSize) { while (byteSize) {
*p++ = static_cast<uint8_t>(x); *dst++ = static_cast<uint8_t>(x);
x >>= 8; x >>= 8;
byteSize--; byteSize--;
} }
} }
void copyByteToUnitAsLE(Unit *dst, const void *src, size_t byteSize) void copyByteToUnitAsLE(Unit *dst, const uint8_t *src, size_t byteSize)
{ {
const uint8_t *p = reinterpret_cast<const uint8_t*>(src);
while (byteSize >= sizeof(Unit)) { while (byteSize >= sizeof(Unit)) {
*dst++ = getUnitAsLE(p); *dst++ = getUnitAsLE(src);
p += sizeof(Unit); src += sizeof(Unit);
byteSize -= sizeof(Unit); byteSize -= sizeof(Unit);
} }
if (byteSize == 0) return; if (byteSize == 0) return;
Unit x = 0; Unit x = 0;
for (size_t i = 0; i < byteSize; i++) { for (size_t i = 0; i < byteSize; i++) {
x |= Unit(p[i]) << (i * 8); x |= Unit(src[i]) << (i * 8);
} }
*dst = x; *dst = x;
} }
@ -524,7 +522,8 @@ void copyAndMask(Unit *y, const void *x, size_t xByteSize, const Op& op, bool do
if (!doMask) throw cybozu::Exception("fp:copyAndMask:bad size") << xByteSize << fpByteSize; if (!doMask) throw cybozu::Exception("fp:copyAndMask:bad size") << xByteSize << fpByteSize;
xByteSize = fpByteSize; xByteSize = fpByteSize;
} }
copyByteToUnitAsLE(y, x, xByteSize); // QQQ : fixed later for big endian
copyByteToUnitAsLE(y, (const uint8_t*)x, xByteSize);
for (size_t i = (xByteSize + sizeof(Unit) - 1) / sizeof(Unit); i < op.N; i++) { for (size_t i = (xByteSize + sizeof(Unit) - 1) / sizeof(Unit); i < op.N; i++) {
y[i] = 0; y[i] = 0;
} }

@ -280,6 +280,30 @@ struct Test {
ss >> Q; ss >> Q;
CYBOZU_TEST_EQUAL(P, Q); CYBOZU_TEST_EQUAL(P, Q);
} }
// tight
if (!Ec::isIoTightSupported()) return;
P.set(x, y);
{
std::string s = P.getStr(mcl::IoTight);
CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize());
Q.setStr(s, mcl::IoTight);
CYBOZU_TEST_EQUAL(P, Q);
}
{
P = -P;
std::string s = P.getStr(mcl::IoTight);
CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize());
Q.setStr(s, mcl::IoTight);
CYBOZU_TEST_EQUAL(P, Q);
}
P.clear();
{
std::string s = P.getStr(mcl::IoTight);
CYBOZU_TEST_EQUAL(s.size(), Fp::getByteSize());
CYBOZU_TEST_ASSERT(mcl::fp::isZeroArray(s.c_str(), s.size()));
Q.setStr(s, mcl::IoTight);
CYBOZU_TEST_EQUAL(P, Q);
}
} }
void ioMode() const void ioMode() const
{ {

Loading…
Cancel
Save