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();
#endif
}
static inline bool isIoTightSupported()
{
return !b_.isZero() && (Fp::getBitSize() & 7) != 0;
}
/*
"0" ; infinity
"1 <x> <y>" ; not compressed
"2 <x>" ; compressed for even 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
{
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()) {
str = '0';
return;
}
normalize();
const char *sep = Fp::BaseFp::getIoSeparator();
if (compressedExpression_) {
str = y.isOdd() ? '3' : '2';
@ -711,8 +735,34 @@ public:
}
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);
if (!(is >> *this)) {
throw cybozu::Exception("EcT:setStr:bad str") << str;

@ -43,14 +43,15 @@ enum IoMode {
IoBinPrefix = IoBin | IoPrefix,
IoHexPrefix = IoHex | IoPrefix,
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 {
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)
@ -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);
// 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
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);
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> > {
typedef fp::Unit Unit;
typedef fp::Operator<FpT<tag, maxBitSize> > Operator;
public:
static const size_t maxSize = (maxBitSize + fp::UnitBitSize - 1) / fp::UnitBitSize;
private:
template<class tag2, size_t maxBitSize2> friend class FpT;
Unit v_[maxSize];
static fp::Op op_;
@ -235,11 +238,11 @@ public:
}
void setStr(const std::string& str, int ioMode = 0)
{
if (ioMode & (IoArray | IoArrayRaw)) {
if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
const size_t n = getByteSize();
if (str.size() != n) throw cybozu::Exception("FpT:setStr:bad size") << str.size() << n << ioMode;
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;
} else {
setArray(&str[0], n);
@ -302,17 +305,16 @@ public:
}
void getStr(std::string& str, int ioMode = 10) const
{
fp::Block b;
const size_t n = getByteSize();
if (ioMode & IoArrayRaw) {
str.resize(n);
fp::copyUnitToByteAsLE(&str[0], v_, str.size());
return;
const Unit *p = v_;
if (!(ioMode & IoArrayRaw)) {
getBlock(b);
p = b.p;
}
fp::Block b;
getBlock(b);
if (ioMode & IoArray) {
if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
str.resize(n);
fp::copyUnitToByteAsLE(&str[0], b.p, str.size());
fp::copyUnitToByteAsLE(reinterpret_cast<uint8_t*>(&str[0]), p, str.size());
return;
}
fp::arrayToStr(str, b.p, b.n, ioMode & ~IoPrefix, (ioMode & IoPrefix) != 0);
@ -410,7 +412,7 @@ public:
{
int ioMode = fp::detectIoMode(getIoMode(), is);
std::string str;
if (ioMode & (IoArray | IoArrayRaw)) {
if (ioMode & (IoArray | IoArrayRaw | IoTight)) {
str.resize(getByteSize());
is.read(&str[0], str.size());
} 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)) {
setUnitAsLE(p, *src++);
p += sizeof(Unit);
setUnitAsLE(dst, *src++);
dst += sizeof(Unit);
byteSize -= sizeof(Unit);
}
if (byteSize == 0) return;
Unit x = *src;
while (byteSize) {
*p++ = static_cast<uint8_t>(x);
*dst++ = static_cast<uint8_t>(x);
x >>= 8;
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)) {
*dst++ = getUnitAsLE(p);
p += sizeof(Unit);
*dst++ = getUnitAsLE(src);
src += sizeof(Unit);
byteSize -= sizeof(Unit);
}
if (byteSize == 0) return;
Unit x = 0;
for (size_t i = 0; i < byteSize; i++) {
x |= Unit(p[i]) << (i * 8);
x |= Unit(src[i]) << (i * 8);
}
*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;
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++) {
y[i] = 0;
}

@ -280,6 +280,30 @@ struct Test {
ss >> 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
{

Loading…
Cancel
Save