From eab7d579e51e2f6dd40652ba28e140669a193d34 Mon Sep 17 00:00:00 2001 From: MITSUNARI Shigeo Date: Tue, 6 Feb 2018 06:18:38 +0900 Subject: [PATCH] [she] add ZkpBin --- include/mcl/randgen.hpp | 2 +- include/mcl/she.hpp | 174 ++++++++++++++++++++++++++++++++-------- test/she_test.cpp | 17 ++++ 3 files changed, 160 insertions(+), 33 deletions(-) diff --git a/include/mcl/randgen.hpp b/include/mcl/randgen.hpp index ed35a01..9e078d4 100644 --- a/include/mcl/randgen.hpp +++ b/include/mcl/randgen.hpp @@ -77,7 +77,7 @@ public: rg must be thread safe rg.read(void *buf, size_t bufSize); */ - void setRandGen(RandGen& rg) + static void setRandGen(const RandGen& rg) { get() = rg; } diff --git a/include/mcl/she.hpp b/include/mcl/she.hpp index ffb7d13..14e097c 100644 --- a/include/mcl/she.hpp +++ b/include/mcl/she.hpp @@ -472,6 +472,36 @@ private: finalExp4(g, g); } public: + struct ZkpBin : public fp::Serializable { + Fr d_[4]; + template + void load(InputStream& is, int ioMode = IoSerialize) + { + for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(d_); i++) { + d_[i].load(is, ioMode); + } + } + template + void save(OutputStream& os, int ioMode = IoSerialize) const + { + const char sep = *fp::getIoSeparator(ioMode); + d_[0].save(os, ioMode); + for (size_t i = 1; i < CYBOZU_NUM_OF_ARRAY(d_); i++) { + if (sep) cybozu::writeChar(os, sep); + d_[i].save(os, ioMode); + } + } + friend std::istream& operator>>(std::istream& is, ZkpBin& self) + { + self.load(is, fp::detectIoMode(Fr::getIoMode(), is)); + return is; + } + friend std::ostream& operator<<(std::ostream& os, const ZkpBin& self) + { + self.save(os, fp::detectIoMode(Fr::getIoMode(), os)); + return os; + } + }; typedef CipherTextAT CipherTextG1; typedef CipherTextAT CipherTextG2; @@ -719,6 +749,16 @@ private: { static_cast(*this).encG2(c, m); } +#if 0 + void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, bool m) const + { + static_cast(*this).encWithZkpBinG1(c, zkp, m); + } + void encWithZkpBin(CipherTextG2& c, ZkpBin& zkp, bool m) const + { + static_cast(*this).encWithZkpBinG2(c, zkp, m); + } +#endif template void enc(CipherTextA& c, const INT& m) const { @@ -814,10 +854,11 @@ public: (S, T) = (m P + r xP, rP) */ template - static void enc1(G& S, G& T, const G& /*P*/, const G& xP, const INT& m, const mcl::fp::WindowMethod& wm) + static void enc1(G& S, G& T, const G& /*P*/, const G& xP, const INT& m, const mcl::fp::WindowMethod& wm, Fr *encRand = 0) { Fr r; r.setRand(); + if (encRand) *encRand = r; // G::mul(T, P, r); wm.mul(static_cast(T), r); G::mul(S, xP, r); @@ -827,6 +868,94 @@ public: wm.mul(static_cast(C), m); S += C; } + /* + d[1-m] ; rand + s[1-m] ; rand + R[0][1-m] = s[1-m] P - d[1-m] T + R[1][1-m] = s[1-m] xP - d[1-m] (S - (1-m) P) + r ; rand + R[0][m] = r P + R[1][m] = r xP + c = H(S, T, R[0][0], R[0][1], R[1][0], R[1][1]) + d[m] = c - d[1-m] + s[m] = r + d[m] encRand + */ + template + static void makeZkpBin1(ZkpBin& zkp, const G& S, const G& T, const Fr& encRand, const G& P, const G& xP, int m) + { + if (m != 0 && m != 1) throw cybozu::Exception("makeZkpBin1:bad m") << m; + Fr *s = &zkp.d_[0]; + Fr *d = &zkp.d_[2]; + G R[2][2]; + d[1-m].setRand(); + s[1-m].setRand(); + G T1, T2; + G::mul(T1, P, s[1-m]); + G::mul(T2, T, d[1-m]); + G::sub(R[0][1-m], T1, T2); // s[1-m] P - d[1-m]T + G::mul(T1, xP, s[1-m]); + if (m == 0) { + G::sub(T2, S, P); + G::mul(T2, T2, d[1-m]); + } else { + G::mul(T2, S, d[1-m]); + } + G::sub(R[1][1-m], T1, T2); // s[1-m] xP - d[1-m](S - (1-m) P) + Fr r; + r.setRand(); + G::mul(R[0][m], P, r); + G::mul(R[1][m], xP, r); + char buf[sizeof(G) * 2]; + cybozu::MemoryOutputStream os(buf, sizeof(buf)); + S.save(os); + T.save(os); + R[0][0].save(os); + R[0][1].save(os); + R[1][0].save(os); + R[1][1].save(os); + Fr c; + c.setHashOf(buf, os.getPos()); + d[m] = c - d[1-m]; + s[m] = r + d[m] * encRand; + } + /* + R[0][i] = s[i] P - d[i] T ; i = 0,1 + R[1][0] = s[0] xP - d[0] S + R[1][1] = s[1] xP - d[1](S - P) + c = H(S, T, R[0][0], R[0][1], R[1][0], R[1][1]) + c == d[0] + d[1] + */ + template + static bool verifyZkpBin(const G& S, const G& T, const G& P, const G& xP, const ZkpBin& zkp) + { + const Fr *s = &zkp.d_[0]; + const Fr *d = &zkp.d_[2]; + G R[2][2]; + G T1, T2; + for (int i = 0; i < 2; i++) { + G::mul(T1, P, s[i]); + G::mul(T2, T, d[i]); + G::sub(R[0][i], T1, T2); + } + G::mul(T1, xP, s[0]); + G::mul(T2, S, d[0]); + G::sub(R[1][0], T1, T2); + G::mul(T1, xP, s[1]); + G::sub(T2, S, P); + G::mul(T2, T2, d[1]); + G::sub(R[1][1], T1, T2); + char buf[sizeof(G) * 2]; + cybozu::MemoryOutputStream os(buf, sizeof(buf)); + S.save(os); + T.save(os); + R[0][0].save(os); + R[0][1].save(os); + R[1][0].save(os); + R[1][1].save(os); + Fr c; + c.setHashOf(buf, os.getPos()); + return c == d[0] + d[1]; + } void set(const Fr& x, const Fr& y) { G1::mul(xP_, P_, x); @@ -842,6 +971,17 @@ public: { enc1(c.S_, c.T_, Q_, yQ_, m, QhashTbl_.getWM()); } +public: + void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const + { + Fr encRand; + enc1(c.S_, c.T_, P_, xP_, m, PhashTbl_.getWM(), &encRand); + makeZkpBin1(zkp, c.S_, c.T_, encRand, P_, xP_, m); + } + bool verify(const CipherTextG1& c, const ZkpBin& zkp) const + { + return verifyZkpBin(c.S_, c.T_, P_, xP_, zkp); + } template void encGT(CipherTextGT& c, const INT& m) const { @@ -991,37 +1131,6 @@ public: yQwm_.init(pub.yQ_, bitSize, local::winSize); } }; - - struct ZkpBin : public fp::Serializable { - Fr d_[4]; - template - void load(InputStream& is, int ioMode = IoSerialize) - { - for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(d_); i++) { - d_[i].load(is, ioMode); - } - } - template - void save(OutputStream& os, int ioMode = IoSerialize) const - { - const char sep = *fp::getIoSeparator(ioMode); - d_[0].save(os, ioMode); - for (size_t i = 1; i < CYBOZU_NUM_OF_ARRAY(d_); i++) { - if (sep) cybozu::writeChar(os, sep); - d_[i].save(os, ioMode); - } - } - friend std::istream& operator>>(std::istream& is, ZkpBin& self) - { - self.load(is, fp::detectIoMode(Fr::getIoMode(), is)); - return is; - } - friend std::ostream& operator<<(std::ostream& os, const ZkpBin& self) - { - self.save(os, fp::detectIoMode(Fr::getIoMode(), os)); - return os; - } - }; class CipherTextA { CipherTextG1 c1_; CipherTextG2 c2_; @@ -1327,6 +1436,7 @@ typedef SHE::CipherTextGT CipherTextGT; typedef SHE::CipherTextA CipherTextA; typedef CipherTextGT CipherTextGM; // old class typedef SHE::CipherText CipherText; +typedef SHE::ZkpBin ZkpBin; } } // mcl::she diff --git a/test/she_test.cpp b/test/she_test.cpp index b52f1fa..aa9f231 100644 --- a/test/she_test.cpp +++ b/test/she_test.cpp @@ -122,6 +122,23 @@ CYBOZU_TEST_AUTO(enc_dec) } } +CYBOZU_TEST_AUTO(ZkpBin) +{ + const SecretKey& sec = g_sec; + PublicKey pub; + sec.getPublicKey(pub); + CipherTextG1 c1; + ZkpBin zkp; + for (int m = 0; m < 2; m++) { + pub.encWithZkpBin(c1, zkp, m); + CYBOZU_TEST_EQUAL(sec.dec(c1), m); + CYBOZU_TEST_ASSERT(pub.verify(c1, zkp)); + zkp.d_[0] += 1; + CYBOZU_TEST_ASSERT(!pub.verify(c1, zkp)); + } + CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c1, zkp, 2), cybozu::Exception); +} + CYBOZU_TEST_AUTO(add_sub_mul) { const SecretKey& sec = g_sec;