aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2018-06-02 16:47:26 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2018-06-02 16:47:26 +0800
commitc0bdae8ea7d47f5456b8000f3621d3c8f2d0f21a (patch)
tree62a2113cce622d3b4bfcd2634413f2e5ec7bc96a
parent9e0f60181ca9ab5e7f1b5effc6fcfcf714babb2e (diff)
downloadtangerine-mcl-c0bdae8ea7d47f5456b8000f3621d3c8f2d0f21a.tar.gz
tangerine-mcl-c0bdae8ea7d47f5456b8000f3621d3c8f2d0f21a.tar.zst
tangerine-mcl-c0bdae8ea7d47f5456b8000f3621d3c8f2d0f21a.zip
add initG1only mode for she
-rw-r--r--include/mcl/ec.hpp2
-rw-r--r--include/mcl/she.hpp99
-rw-r--r--sample/she_make_dlp_table.cpp6
-rw-r--r--src/she_c_impl.hpp6
-rw-r--r--test/she_test.cpp69
5 files changed, 150 insertions, 32 deletions
diff --git a/include/mcl/ec.hpp b/include/mcl/ec.hpp
index d41ac48..7635eb0 100644
--- a/include/mcl/ec.hpp
+++ b/include/mcl/ec.hpp
@@ -171,8 +171,10 @@ public:
} else {
specialA_ = generic;
}
+ ioMode_ = 0;
verifyOrder_ = false;
order_ = 0;
+ mulArrayGLV = 0;
#ifdef MCL_EC_USE_AFFINE
cybozu::disable_warning_unused_variable(mode);
#else
diff --git a/include/mcl/she.hpp b/include/mcl/she.hpp
index 0eee669..6c3b0ed 100644
--- a/include/mcl/she.hpp
+++ b/include/mcl/she.hpp
@@ -340,6 +340,7 @@ struct SHET {
static local::HashTable<GT, false> ePQhashTbl_;
static bool useDecG1ViaGT_;
static bool useDecG2ViaGT_;
+ static bool isG1only_;
private:
template<class G>
class CipherTextAT : public fp::Serializable<CipherTextAT<G> > {
@@ -554,6 +555,9 @@ public:
pairing(ePQ_, P_, Q_);
precomputeG2(Qcoeff_, Q_);
setRangeForDLP(hashSize);
+ useDecG1ViaGT_ = false;
+ useDecG2ViaGT_ = false;
+ isG1only_ = false;
setTryNum(tryNum);
}
static void init(size_t hashSize, size_t tryNum = local::defaultTryNum)
@@ -561,6 +565,24 @@ public:
init(mcl::BN254, hashSize, tryNum);
}
/*
+ standard lifted ElGamal encryption
+ */
+ static void initG1only(const mcl::EcParam& para, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
+ {
+ Fp::init(para.p);
+ Fr::init(para.n);
+ G1::init(para.a, para.b);
+ const Fp x0(para.gx);
+ const Fp y0(para.gy);
+ P_.set(x0, y0);
+
+ setRangeForG1DLP(hashSize);
+ useDecG1ViaGT_ = false;
+ useDecG2ViaGT_ = false;
+ isG1only_ = true;
+ setTryNum(tryNum);
+ }
+ /*
set range for G1-DLP
*/
static void setRangeForG1DLP(size_t hashSize)
@@ -633,7 +655,7 @@ public:
void setByCSPRNG()
{
x_.setRand();
- y_.setRand();
+ if (!isG1only_) y_.setRand();
}
/*
set xP and yQ
@@ -749,13 +771,14 @@ public:
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
x_.load(pb, is, ioMode); if (!*pb) return;
- y_.load(pb, is, ioMode);
+ if (!isG1only_) y_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
const char sep = *fp::getIoSeparator(ioMode);
x_.save(pb, os, ioMode); if (!*pb) return;
+ if (isG1only_) return;
if (sep) {
cybozu::writeChar(pb, os, sep);
if (!*pb) return;
@@ -788,7 +811,7 @@ public:
}
bool operator==(const SecretKey& rhs) const
{
- return x_ == rhs.x_ && y_ == rhs.y_;
+ return x_ == rhs.x_ && (isG1only_ || y_ == rhs.y_);
}
bool operator!=(const SecretKey& rhs) const { return !operator==(rhs); }
};
@@ -1219,7 +1242,7 @@ public:
void set(const Fr& x, const Fr& y)
{
G1::mul(xP_, P_, x);
- G2::mul(yQ_, Q_, y);
+ if (!isG1only_) G2::mul(yQ_, Q_, y);
}
template<class INT>
void encG1(CipherTextG1& c, const INT& m) const
@@ -1329,13 +1352,14 @@ public:
void load(bool *pb, InputStream& is, int ioMode = IoSerialize)
{
xP_.load(pb, is, ioMode); if (!*pb) return;
- yQ_.load(pb, is, ioMode);
+ if (!isG1only_) yQ_.load(pb, is, ioMode);
}
template<class OutputStream>
void save(bool *pb, OutputStream& os, int ioMode = IoSerialize) const
{
const char sep = *fp::getIoSeparator(ioMode);
xP_.save(pb, os, ioMode); if (!*pb) return;
+ if (isG1only_) return;
if (sep) {
cybozu::writeChar(pb, os, sep);
if (!*pb) return;
@@ -1368,7 +1392,7 @@ public:
}
bool operator==(const PublicKey& rhs) const
{
- return xP_ == rhs.xP_ && yQ_ == rhs.yQ_;
+ return xP_ == rhs.xP_ && (isG1only_ || yQ_ == rhs.yQ_);
}
bool operator!=(const PublicKey& rhs) const { return !operator==(rhs); }
};
@@ -1425,15 +1449,16 @@ public:
public:
void init(const PublicKey& pub)
{
+ const size_t bitSize = Fr::getBitSize();
+ xPwm_.init(pub.xP_, bitSize, local::winSize);
+ if (isG1only_) return;
+ yQwm_.init(pub.yQ_, bitSize, local::winSize);
pairing(exPQ_, pub.xP_, Q_);
pairing(eyPQ_, P_, pub.yQ_);
pairing(exyPQ_, pub.xP_, pub.yQ_);
- const size_t bitSize = Fr::getBitSize();
exPQwm_.init(static_cast<const GTasEC&>(exPQ_), bitSize, local::winSize);
eyPQwm_.init(static_cast<const GTasEC&>(eyPQ_), bitSize, local::winSize);
exyPQwm_.init(static_cast<const GTasEC&>(exyPQ_), bitSize, local::winSize);
- xPwm_.init(pub.xP_, bitSize, local::winSize);
- yQwm_.init(pub.yQ_, bitSize, local::winSize);
}
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
@@ -1740,6 +1765,18 @@ public:
}
throw cybozu::Exception("she:CipherText:sub:mixed CipherText");
}
+ static void neg(CipherText& y, const CipherText& x)
+ {
+ if (x.isMultiplied()) {
+ y.isMultiplied_ = true;
+ CipherTextGT::neg(y.m_, x.m_);
+ return;
+ } else {
+ y.isMultiplied_ = false;
+ CipherTextA::neg(y.a_, x.a_);
+ return;
+ }
+ }
static void mul(CipherText& z, const CipherText& x, const CipherText& y)
{
if (x.isMultiplied() || y.isMultiplied()) {
@@ -1821,16 +1858,20 @@ public:
bool operator!=(const CipherTextGT& rhs) const { return !operator==(rhs); }
};
};
+typedef local::HashTable<G1> HashTableG1;
+typedef local::HashTable<G2> HashTableG2;
+typedef local::HashTable<Fp12, false> HashTableGT;
template<size_t dummyInpl> G1 SHET<dummyInpl>::P_;
template<size_t dummyInpl> G2 SHET<dummyInpl>::Q_;
template<size_t dummyInpl> Fp12 SHET<dummyInpl>::ePQ_;
template<size_t dummyInpl> std::vector<Fp6> SHET<dummyInpl>::Qcoeff_;
-template<size_t dummyInpl> local::HashTable<G1> SHET<dummyInpl>::PhashTbl_;
-template<size_t dummyInpl> local::HashTable<G2> SHET<dummyInpl>::QhashTbl_;
-template<size_t dummyInpl> local::HashTable<Fp12, false> SHET<dummyInpl>::ePQhashTbl_;
+template<size_t dummyInpl> HashTableG1 SHET<dummyInpl>::PhashTbl_;
+template<size_t dummyInpl> HashTableG2 SHET<dummyInpl>::QhashTbl_;
+template<size_t dummyInpl> HashTableGT SHET<dummyInpl>::ePQhashTbl_;
template<size_t dummyInpl> bool SHET<dummyInpl>::useDecG1ViaGT_;
template<size_t dummyInpl> bool SHET<dummyInpl>::useDecG2ViaGT_;
+template<size_t dummyInpl> bool SHET<dummyInpl>::isG1only_;
typedef mcl::she::SHET<> SHE;
typedef SHE::SecretKey SecretKey;
typedef SHE::PublicKey PublicKey;
@@ -1849,6 +1890,10 @@ inline void init(const mcl::CurveParam& cp = mcl::BN254, size_t hashSize = 1024,
{
SHE::init(cp, hashSize, tryNum);
}
+inline void initG1only(const mcl::EcParam& para, size_t hashSize = 1024, size_t tryNum = local::defaultTryNum)
+{
+ SHE::initG1only(para, hashSize, tryNum);
+}
inline void init(size_t hashSize, size_t tryNum = local::defaultTryNum) { SHE::init(hashSize, tryNum); }
inline void setRangeForG1DLP(size_t hashSize) { SHE::setRangeForG1DLP(hashSize); }
inline void setRangeForG2DLP(size_t hashSize) { SHE::setRangeForG2DLP(hashSize); }
@@ -1857,6 +1902,36 @@ inline void setRangeForDLP(size_t hashSize) { SHE::setRangeForDLP(hashSize); }
inline void setTryNum(size_t tryNum) { SHE::setTryNum(tryNum); }
inline void useDecG1ViaGT(bool use = true) { SHE::useDecG1ViaGT(use); }
inline void useDecG2ViaGT(bool use = true) { SHE::useDecG2ViaGT(use); }
+inline HashTableG1& getHashTableG1() { return SHE::PhashTbl_; }
+inline HashTableG2& getHashTableG2() { return SHE::QhashTbl_; }
+inline HashTableGT& getHashTableGT() { return SHE::ePQhashTbl_; }
+
+inline void add(CipherTextG1& z, const CipherTextG1& x, const CipherTextG1& y) { CipherTextG1::add(z, x, y); }
+inline void add(CipherTextG2& z, const CipherTextG2& x, const CipherTextG2& y) { CipherTextG2::add(z, x, y); }
+inline void add(CipherTextGT& z, const CipherTextGT& x, const CipherTextGT& y) { CipherTextGT::add(z, x, y); }
+inline void add(CipherText& z, const CipherText& x, const CipherText& y) { CipherText::add(z, x, y); }
+
+inline void sub(CipherTextG1& z, const CipherTextG1& x, const CipherTextG1& y) { CipherTextG1::sub(z, x, y); }
+inline void sub(CipherTextG2& z, const CipherTextG2& x, const CipherTextG2& y) { CipherTextG2::sub(z, x, y); }
+inline void sub(CipherTextGT& z, const CipherTextGT& x, const CipherTextGT& y) { CipherTextGT::sub(z, x, y); }
+inline void sub(CipherText& z, const CipherText& x, const CipherText& y) { CipherText::sub(z, x, y); }
+
+inline void neg(CipherTextG1& y, const CipherTextG1& x) { CipherTextG1::neg(y, x); }
+inline void neg(CipherTextG2& y, const CipherTextG2& x) { CipherTextG2::neg(y, x); }
+inline void neg(CipherTextGT& y, const CipherTextGT& x) { CipherTextGT::neg(y, x); }
+inline void neg(CipherText& y, const CipherText& x) { CipherText::neg(y, x); }
+
+template<class INT>
+inline void mul(CipherTextG1& z, const CipherTextG1& x, const INT& y) { CipherTextG1::mul(z, x, y); }
+template<class INT>
+inline void mul(CipherTextG2& z, const CipherTextG2& x, const INT& y) { CipherTextG2::mul(z, x, y); }
+template<class INT>
+inline void mul(CipherTextGT& z, const CipherTextGT& x, const INT& y) { CipherTextGT::mul(z, x, y); }
+template<class INT>
+inline void mul(CipherText& z, const CipherText& x, const INT& y) { CipherText::mul(z, x, y); }
+
+inline void mul(CipherTextGT& z, const CipherTextG1& x, const CipherTextG2& y) { CipherTextGT::mul(z, x, y); }
+inline void mul(CipherText& z, const CipherText& x, const CipherText& y) { CipherText::mul(z, x, y); }
} } // mcl::she
diff --git a/sample/she_make_dlp_table.cpp b/sample/she_make_dlp_table.cpp
index 6b57999..41f18e2 100644
--- a/sample/she_make_dlp_table.cpp
+++ b/sample/she_make_dlp_table.cpp
@@ -34,13 +34,13 @@ void run(const Param& param)
switch (param.group) {
case 1:
- makeTable(param, "g1", SHE::PhashTbl_, SHE::P_);
+ makeTable(param, "g1", getHashTableG1(), SHE::P_);
break;
case 2:
- makeTable(param, "g2", SHE::QhashTbl_, SHE::Q_);
+ makeTable(param, "g2", getHashTableG2(), SHE::Q_);
break;
case 3:
- makeTable(param, "gt", SHE::ePQhashTbl_, SHE::ePQ_);
+ makeTable(param, "gt", getHashTableGT(), SHE::ePQ_);
break;
default:
throw cybozu::Exception("bad group") << param.group;
diff --git a/src/she_c_impl.hpp b/src/she_c_impl.hpp
index 58afe2a..d025f24 100644
--- a/src/she_c_impl.hpp
+++ b/src/she_c_impl.hpp
@@ -217,15 +217,15 @@ mclSize loadTable(HashTable& table, const void *buf, mclSize bufSize)
mclSize sheLoadTableForG1DLP(const void *buf, mclSize bufSize)
{
- return loadTable(SHE::PhashTbl_, buf, bufSize);
+ return loadTable(getHashTableG1(), buf, bufSize);
}
mclSize sheLoadTableForG2DLP(const void *buf, mclSize bufSize)
{
- return loadTable(SHE::QhashTbl_, buf, bufSize);
+ return loadTable(getHashTableG2(), buf, bufSize);
}
mclSize sheLoadTableForGTDLP(const void *buf, mclSize bufSize)
{
- return loadTable(SHE::ePQhashTbl_, buf, bufSize);
+ return loadTable(getHashTableGT(), buf, bufSize);
}
template<class HashTable>
diff --git a/test/she_test.cpp b/test/she_test.cpp
index 28ea730..6dff0e5 100644
--- a/test/she_test.cpp
+++ b/test/she_test.cpp
@@ -5,9 +5,9 @@
#include <fstream>
#include <time.h>
#include <mcl/she.hpp>
+#include <mcl/ecparam.hpp> // for secp192k1
using namespace mcl::she;
-using namespace mcl::bn;
SecretKey g_sec;
@@ -88,18 +88,18 @@ CYBOZU_TEST_AUTO(bench2)
t1 = clk2msec(cybozu::bench::g_clk, C);
printf("DEC L2 %.2e\n", t1);
- CYBOZU_BENCH_C("", C, CipherTextG1::add, d1, d1, c1);
+ CYBOZU_BENCH_C("", C, add, d1, d1, c1);
t1 = clk2msec(cybozu::bench::g_clk, C);
- CYBOZU_BENCH_C("", C, CipherTextG2::add, d2, d2, c2);
+ CYBOZU_BENCH_C("", C, add, d2, d2, c2);
t2 = clk2msec(cybozu::bench::g_clk, C);
printf("Add L1 %.2e\n", t1 + t2);
- CYBOZU_BENCH_C("", C, CipherTextGT::add, dt, dt, ct);
+ CYBOZU_BENCH_C("", C, add, dt, dt, ct);
t1 = clk2msec(cybozu::bench::g_clk, C);
printf("Add L2 %.2e\n", t1);
- CYBOZU_BENCH_C("", C, CipherTextGT::mul, ct, c1, c2);
+ CYBOZU_BENCH_C("", C, mul, ct, c1, c2);
t1 = clk2msec(cybozu::bench::g_clk, C);
printf("Mul %.2e\n", t1);
@@ -328,21 +328,21 @@ CYBOZU_TEST_AUTO(add_sub_mul)
CipherText c1, c2, c3;
pub.enc(c1, m1);
pub.enc(c2, m2);
- CipherText::add(c3, c1, c2);
+ add(c3, c1, c2);
CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
pub.reRand(c3);
CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
- CipherText::sub(c3, c1, c2);
+ sub(c3, c1, c2);
CYBOZU_TEST_EQUAL(m1 - m2, sec.dec(c3));
- CipherText::mul(c3, c1, 5);
+ mul(c3, c1, 5);
CYBOZU_TEST_EQUAL(m1 * 5, sec.dec(c3));
- CipherText::mul(c3, c1, -123);
+ mul(c3, c1, -123);
CYBOZU_TEST_EQUAL(m1 * -123, sec.dec(c3));
- CipherText::mul(c3, c1, c2);
+ mul(c3, c1, c2);
CYBOZU_TEST_EQUAL(m1 * m2, sec.dec(c3));
pub.reRand(c3);
@@ -354,7 +354,7 @@ CYBOZU_TEST_AUTO(add_sub_mul)
pub.enc(c1, m1, true);
CYBOZU_TEST_EQUAL(m1, sec.dec(c1));
pub.enc(c2, m2, true);
- CipherText::add(c3, c1, c2);
+ add(c3, c1, c2);
CYBOZU_TEST_EQUAL(m1 + m2, sec.dec(c3));
}
}
@@ -372,14 +372,14 @@ CYBOZU_TEST_AUTO(largeEnc)
pub.enc(c1, x);
const int64_t m = 123;
pub.enc(c2, x + m);
- CipherTextG1::sub(c1, c1, c2);
+ sub(c1, c1, c2);
CYBOZU_TEST_EQUAL(sec.dec(c1), -m);
pub.enc(c1, 0);
- CipherTextG1::mul(c1, c1, x);
+ mul(c1, c1, x);
CYBOZU_TEST_ASSERT(sec.isZero(c1));
pub.enc(c1, 1);
- CipherTextG1::mul(c1, c1, x);
+ mul(c1, c1, x);
CYBOZU_TEST_ASSERT(!sec.isZero(c1));
}
@@ -700,3 +700,44 @@ CYBOZU_TEST_AUTO(hashBench)
}
#endif
+CYBOZU_TEST_AUTO(liftedElGamal)
+{
+ const size_t hashSize = 1024;
+ initG1only(mcl::ecparam::secp192k1, hashSize);
+ const size_t byteSize = 192 / 8;
+ SecretKey sec;
+ sec.setByCSPRNG();
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ CipherTextG1 c1, c2, c3;
+ int m1 = 12, m2 = 34;
+ pub.enc(c1, m1);
+ pub.enc(c2, m2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m2);
+ add(c3, c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c3), m1 + m2);
+ neg(c1, c2);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), -m2);
+ mul(c1, c2, m1);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m2 * m1);
+
+ char buf[1024];
+ size_t n = sec.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ SecretKey sec2;
+ n = sec2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize);
+ CYBOZU_TEST_EQUAL(sec, sec2);
+
+ n = pub.serialize(buf, sizeof(buf));
+ CYBOZU_TEST_EQUAL(n, byteSize + 1); // +1 is for sign of y
+ PublicKey pub2;
+ n = pub2.deserialize(buf, n);
+ CYBOZU_TEST_EQUAL(n, byteSize + 1);
+ CYBOZU_TEST_EQUAL(pub, pub2);
+
+ PublicKey pub3;
+ sec2.getPublicKey(pub3);
+ CYBOZU_TEST_EQUAL(pub, pub3);
+}