aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMITSUNARI Shigeo <herumi@nifty.com>2018-03-14 04:20:06 +0800
committerMITSUNARI Shigeo <herumi@nifty.com>2018-03-14 04:20:06 +0800
commitaedea9028819a67e0370412525a24feaf5381462 (patch)
tree92288ab741b81d11c123504c2e9c44b9c7029ed1
parent34c914247756fa9f5a3d645848286b92fd36a360 (diff)
downloadtangerine-mcl-aedea9028819a67e0370412525a24feaf5381462.tar.gz
tangerine-mcl-aedea9028819a67e0370412525a24feaf5381462.tar.zst
tangerine-mcl-aedea9028819a67e0370412525a24feaf5381462.zip
add ZkpBinEq
-rw-r--r--include/mcl/she.h16
-rw-r--r--include/mcl/she.hpp290
-rw-r--r--src/she_c_impl.hpp67
-rw-r--r--test/she_c_test.hpp47
-rw-r--r--test/she_test.cpp56
5 files changed, 455 insertions, 21 deletions
diff --git a/include/mcl/she.h b/include/mcl/she.h
index 6c11050..f40097b 100644
--- a/include/mcl/she.h
+++ b/include/mcl/she.h
@@ -64,6 +64,14 @@ typedef struct {
typedef struct {
mclBnFr d[4];
} sheZkpBin;
+
+typedef struct {
+ mclBnFr d[4];
+} sheZkpEq;
+
+typedef struct {
+ mclBnFr d[7];
+} sheZkpBinEq;
/*
initialize this library
call this once before using the other functions
@@ -82,6 +90,8 @@ MCLSHE_DLL_API mclSize sheCipherTextG1Serialize(void *buf, mclSize maxBufSize, c
MCLSHE_DLL_API mclSize sheCipherTextG2Serialize(void *buf, mclSize maxBufSize, const sheCipherTextG2 *c);
MCLSHE_DLL_API mclSize sheCipherTextGTSerialize(void *buf, mclSize maxBufSize, const sheCipherTextGT *c);
MCLSHE_DLL_API mclSize sheZkpBinSerialize(void *buf, mclSize maxBufSize, const sheZkpBin *zkp);
+MCLSHE_DLL_API mclSize sheZkpEqSerialize(void *buf, mclSize maxBufSize, const sheZkpEq *zkp);
+MCLSHE_DLL_API mclSize sheZkpBinEqSerialize(void *buf, mclSize maxBufSize, const sheZkpBinEq *zkp);
// return read byte size if sucess else 0
MCLSHE_DLL_API mclSize sheSecretKeyDeserialize(sheSecretKey* sec, const void *buf, mclSize bufSize);
@@ -90,6 +100,8 @@ MCLSHE_DLL_API mclSize sheCipherTextG1Deserialize(sheCipherTextG1* c, const void
MCLSHE_DLL_API mclSize sheCipherTextG2Deserialize(sheCipherTextG2* c, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheCipherTextGTDeserialize(sheCipherTextGT* c, const void *buf, mclSize bufSize);
MCLSHE_DLL_API mclSize sheZkpBinDeserialize(sheZkpBin* zkp, const void *buf, mclSize bufSize);
+MCLSHE_DLL_API mclSize sheZkpEqDeserialize(sheZkpEq* zkp, const void *buf, mclSize bufSize);
+MCLSHE_DLL_API mclSize sheZkpBinEqDeserialize(sheZkpBinEq* zkp, const void *buf, mclSize bufSize);
/*
set secretKey if system has /dev/urandom or CryptGenRandom
@@ -149,6 +161,7 @@ MCLSHE_DLL_API int sheEncGT(sheCipherTextGT *c, const shePublicKey *pub, mclInt
*/
MCLSHE_DLL_API int sheEncWithZkpBinG1(sheCipherTextG1 *c, sheZkpBin *zkp, const shePublicKey *pub, int m);
MCLSHE_DLL_API int sheEncWithZkpBinG2(sheCipherTextG2 *c, sheZkpBin *zkp, const shePublicKey *pub, int m);
+MCLSHE_DLL_API int sheEncWithZkpBinEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpBinEq *zkp, const shePublicKey *pub, int m);
/*
decode c and set m
@@ -163,8 +176,10 @@ MCLSHE_DLL_API int sheDecGT(mclInt *m, const sheSecretKey *sec, const sheCipherT
*/
MCLSHE_DLL_API int sheVerifyZkpBinG1(const shePublicKey *pub, const sheCipherTextG1 *c, const sheZkpBin *zkp);
MCLSHE_DLL_API int sheVerifyZkpBinG2(const shePublicKey *pub, const sheCipherTextG2 *c, const sheZkpBin *zkp);
+MCLSHE_DLL_API int sheVerifyZkpBinEq(const shePublicKey *pub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG1(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c, const sheZkpBin *zkp);
MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinG2(const shePrecomputedPublicKey *ppub, const sheCipherTextG2 *c, const sheZkpBin *zkp);
+MCLSHE_DLL_API int shePrecomputedPublicKeyVerifyZkpBinEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp);
/*
decode c via GT and set m
return 0 if success
@@ -232,6 +247,7 @@ MCLSHE_DLL_API int shePrecomputedPublicKeyEncGT(sheCipherTextGT *c, const shePre
*/
MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpBinG1(sheCipherTextG1 *c, sheZkpBin *zkp, const shePrecomputedPublicKey *ppub, int m);
MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpBinG2(sheCipherTextG2 *c, sheZkpBin *zkp, const shePrecomputedPublicKey *ppub, int m);
+MCLSHE_DLL_API int shePrecomputedPublicKeyEncWithZkpBinEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpBinEq *zkp, const shePrecomputedPublicKey *ppub, int m);
#ifdef __cplusplus
}
diff --git a/include/mcl/she.hpp b/include/mcl/she.hpp
index 788bb15..1ea5c99 100644
--- a/include/mcl/she.hpp
+++ b/include/mcl/she.hpp
@@ -471,13 +471,13 @@ private:
tensorProductML(g,S1, T1, S2,T2);
finalExp4(g, g);
}
-public:
- struct ZkpBin : public fp::Serializable<ZkpBin> {
- Fr d_[4];
+ template<class Tag, size_t n>
+ struct ZkpT : public fp::Serializable<ZkpT<Tag, n> > {
+ Fr d_[n];
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
- for (size_t i = 0; i < CYBOZU_NUM_OF_ARRAY(d_); i++) {
+ for (size_t i = 0; i < n; i++) {
d_[i].load(is, ioMode);
}
}
@@ -486,22 +486,38 @@ public:
{
const char sep = *fp::getIoSeparator(ioMode);
d_[0].save(os, ioMode);
- for (size_t i = 1; i < CYBOZU_NUM_OF_ARRAY(d_); i++) {
+ for (size_t i = 1; i < n; i++) {
if (sep) cybozu::writeChar(os, sep);
d_[i].save(os, ioMode);
}
}
- friend std::istream& operator>>(std::istream& is, ZkpBin& self)
+ friend std::istream& operator>>(std::istream& is, ZkpT& self)
{
self.load(is, fp::detectIoMode(Fr::getIoMode(), is));
return is;
}
- friend std::ostream& operator<<(std::ostream& os, const ZkpBin& self)
+ friend std::ostream& operator<<(std::ostream& os, const ZkpT& self)
{
self.save(os, fp::detectIoMode(Fr::getIoMode(), os));
return os;
}
};
+ struct ZkpBinTag;
+ struct ZkpEqTag; // d_[] = { c, sp, ss, sm }
+ struct ZkpBinEqTag; // d_[] = { d0, d1, sp0, sp1, ss, sp, sm }
+public:
+ /*
+ Zkp for m = 0 or 1
+ */
+ typedef ZkpT<ZkpBinTag, 4> ZkpBin;
+ /*
+ Zkp for decG1(c1) == decG2(c2)
+ */
+ typedef ZkpT<ZkpEqTag, 4> ZkpEq;
+ /*
+ Zkp for (m = 0 or 1) and decG1(c1) == decG2(c2)
+ */
+ typedef ZkpT<ZkpBinEqTag, 7> ZkpBinEq;
typedef CipherTextAT<G1> CipherTextG1;
typedef CipherTextAT<G2> CipherTextG2;
@@ -735,14 +751,17 @@ private:
(S, T) = (m P + r xP, rP)
Pmul.mul(X, a) // X = a P
xPmul.mul(X, a) // X = a xP
- encRand is used to compute Zkp
+ use *encRand if encRand is not null
*/
template<class G, class INT, class MulG, class I>
- static void ElGamalEnc(G& S, G& T, const INT& m, const mcl::fp::WindowMethod<I>& Pmul, const MulG& xPmul, Fr *encRand = 0)
+ static void ElGamalEnc(G& S, G& T, const INT& m, const mcl::fp::WindowMethod<I>& Pmul, const MulG& xPmul, const Fr *encRand = 0)
{
Fr r;
- r.setRand();
- if (encRand) *encRand = r;
+ if (encRand) {
+ r = *encRand;
+ } else {
+ r.setRand();
+ }
Pmul.mul(static_cast<I&>(T), r);
xPmul.mul(S, r); // S = r xP
if (m == 0) return;
@@ -840,6 +859,197 @@ private:
return c == d[0] + d[1];
}
/*
+ encRand1, encRand2 are random values use for ElGamalEnc()
+ */
+ template<class G1, class G2, class INT, class I1, class I2, class MulG1, class MulG2>
+ static void makeZkpEq(ZkpEq& zkp, G1& S1, G1& T1, G2& S2, G2& T2, const INT& m, const mcl::fp::WindowMethod<I1>& Pmul, const MulG1& xPmul, const mcl::fp::WindowMethod<I2>& Qmul, const MulG2& yQmul)
+ {
+ Fr p, s;
+ p.setRand();
+ s.setRand();
+ ElGamalEnc(S1, T1, m, Pmul, xPmul, &p);
+ ElGamalEnc(S2, T2, m, Qmul, yQmul, &s);
+ Fr rp, rs, rm;
+ rp.setRand();
+ rs.setRand();
+ rm.setRand();
+ G1 R1, R2;
+ G2 R3, R4;
+ ElGamalEnc(R1, R2, rm, Pmul, xPmul, &rp);
+ ElGamalEnc(R3, R4, rm, Qmul, yQmul, &rs);
+ char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ S1.save(os);
+ T1.save(os);
+ S2.save(os);
+ T2.save(os);
+ R1.save(os);
+ R2.save(os);
+ R3.save(os);
+ R4.save(os);
+ Fr& c = zkp.d_[0];
+ Fr& sp = zkp.d_[1];
+ Fr& ss = zkp.d_[2];
+ Fr& sm = zkp.d_[3];
+ c.setHashOf(buf, os.getPos());
+ Fr::mul(sp, c, p);
+ sp += rp;
+ Fr::mul(ss, c, s);
+ ss += rs;
+ Fr::mul(sm, c, m);
+ sm += rm;
+ }
+ template<class G1, class G2, class I1, class I2, class MulG1, class MulG2>
+ static bool verifyZkpEq(const ZkpEq& zkp, const G1& S1, const G1& T1, const G2& S2, const G2& T2, const mcl::fp::WindowMethod<I1>& Pmul, const MulG1& xPmul, const mcl::fp::WindowMethod<I2>& Qmul, const MulG2& yQmul)
+ {
+ const Fr& c = zkp.d_[0];
+ const Fr& sp = zkp.d_[1];
+ const Fr& ss = zkp.d_[2];
+ const Fr& sm = zkp.d_[3];
+ G1 R1, R2, X1;
+ G2 R3, R4, X2;
+ ElGamalEnc(R1, R2, sm, Pmul, xPmul, &sp);
+ G1::mul(X1, S1, c);
+ R1 -= X1;
+ G1::mul(X1, T1, c);
+ R2 -= X1;
+ ElGamalEnc(R3, R4, sm, Qmul, yQmul, &ss);
+ G2::mul(X2, S2, c);
+ R3 -= X2;
+ G2::mul(X2, T2, c);
+ R4 -= X2;
+ char buf[sizeof(G1) * 4 + sizeof(G2) * 4];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ S1.save(os);
+ T1.save(os);
+ S2.save(os);
+ T2.save(os);
+ R1.save(os);
+ R2.save(os);
+ R3.save(os);
+ R4.save(os);
+ Fr c2;
+ c2.setHashOf(buf, os.getPos());
+ return c == c2;
+ }
+ /*
+ encRand1, encRand2 are random values use for ElGamalEnc()
+ */
+ template<class G1, class G2, class I1, class I2, class MulG1, class MulG2>
+ static void makeZkpBinEq(ZkpBinEq& zkp, G1& S1, G1& T1, G2& S2, G2& T2, int m, const mcl::fp::WindowMethod<I1>& Pmul, const MulG1& xPmul, const mcl::fp::WindowMethod<I2>& Qmul, const MulG2& yQmul)
+ {
+ if (m != 0 && m != 1) throw cybozu::Exception("makeZkpBinEq:bad m") << m;
+ Fr *d = &zkp.d_[0];
+ Fr *spm = &zkp.d_[2];
+ Fr& ss = zkp.d_[4];
+ Fr& sp = zkp.d_[5];
+ Fr& sm = zkp.d_[6];
+ Fr p, s;
+ p.setRand();
+ s.setRand();
+ ElGamalEnc(S1, T1, m, Pmul, xPmul, &p);
+ ElGamalEnc(S2, T2, m, Qmul, yQmul, &s);
+ d[1-m].setRand();
+ spm[1-m].setRand();
+ G1 R1[2], R2[2], X1;
+ Pmul.mul(static_cast<I1&>(R1[1-m]), spm[1-m]);
+ G1::mul(X1, T1, d[1-m]);
+ R1[1-m] -= X1;
+ if (m == 0) {
+ G1::sub(X1, S1, P_);
+ G1::mul(X1, X1, d[1-m]);
+ } else {
+ G1::mul(X1, S1, d[1-m]);
+ }
+ xPmul.mul(R2[1-m], spm[1-m]);
+ R2[1-m] -= X1;
+ Fr rpm, rp, rs, rm;
+ rpm.setRand();
+ rp.setRand();
+ rs.setRand();
+ rm.setRand();
+ ElGamalEnc(R2[m], R1[m], 0, Pmul, xPmul, &rpm);
+ G1 R3, R4;
+ G2 R5, R6;
+ ElGamalEnc(R4, R3, rm, Pmul, xPmul, &rp);
+ ElGamalEnc(R6, R5, rm, Qmul, yQmul, &rs);
+ char buf[sizeof(Fr) * 12];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ S1.save(os);
+ T1.save(os);
+ R1[0].save(os);
+ R1[1].save(os);
+ R2[0].save(os);
+ R2[1].save(os);
+ R3.save(os);
+ R4.save(os);
+ R5.save(os);
+ R6.save(os);
+ Fr c;
+ c.setHashOf(buf, os.getPos());
+ Fr::sub(d[m], c, d[1-m]);
+ Fr::mul(spm[m], d[m], p);
+ spm[m] += rpm;
+ Fr::mul(sp, c, p);
+ sp += rp;
+ Fr::mul(ss, c, s);
+ ss += rs;
+ Fr::mul(sm, c, m);
+ sm += rm;
+ }
+ template<class G1, class G2, class I1, class I2, class MulG1, class MulG2>
+ static bool verifyZkpBinEq(const ZkpBinEq& zkp, const G1& S1, const G1& T1, const G2& S2, const G2& T2, const mcl::fp::WindowMethod<I1>& Pmul, const MulG1& xPmul, const mcl::fp::WindowMethod<I2>& Qmul, const MulG2& yQmul)
+ {
+ const Fr *d = &zkp.d_[0];
+ const Fr *spm = &zkp.d_[2];
+ const Fr& ss = zkp.d_[4];
+ const Fr& sp = zkp.d_[5];
+ const Fr& sm = zkp.d_[6];
+ G1 R1[2], R2[2], X1;
+ for (int i = 0; i < 2; i++) {
+ Pmul.mul(static_cast<I1&>(R1[i]), spm[i]);
+ G1::mul(X1, T1, d[i]);
+ R1[i] -= X1;
+ }
+ xPmul.mul(R2[0], spm[0]);
+ G1::mul(X1, S1, d[0]);
+ R2[0] -= X1;
+ xPmul.mul(R2[1], spm[1]);
+ G1::sub(X1, S1, P_);
+ G1::mul(X1, X1, d[1]);
+ R2[1] -= X1;
+ Fr c;
+ Fr::add(c, d[0], d[1]);
+ G1 R3, R4;
+ G2 R5, R6;
+ ElGamalEnc(R4, R3, sm, Pmul, xPmul, &sp);
+ G1::mul(X1, T1, c);
+ R3 -= X1;
+ G1::mul(X1, S1, c);
+ R4 -= X1;
+ ElGamalEnc(R6, R5, sm, Qmul, yQmul, &ss);
+ G2 X2;
+ G2::mul(X2, T2, c);
+ R5 -= X2;
+ G2::mul(X2, S2, c);
+ R6 -= X2;
+ char buf[sizeof(Fr) * 12];
+ cybozu::MemoryOutputStream os(buf, sizeof(buf));
+ S1.save(os);
+ T1.save(os);
+ R1[0].save(os);
+ R1[1].save(os);
+ R2[0].save(os);
+ R2[1].save(os);
+ R3.save(os);
+ R4.save(os);
+ R5.save(os);
+ R6.save(os);
+ Fr c2;
+ c2.setHashOf(buf, os.getPos());
+ return c == c2;
+ }
+ /*
common method for PublicKey and PrecomputedPublicKey
*/
template<class T>
@@ -858,16 +1068,6 @@ private:
{
static_cast<const T&>(*this).encG2(c, m);
}
-#if 0
- void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, bool m) const
- {
- static_cast<const T&>(*this).encWithZkpBinG1(c, zkp, m);
- }
- void encWithZkpBin(CipherTextG2& c, ZkpBin& zkp, bool m) const
- {
- static_cast<const T&>(*this).encWithZkpBinG2(c, zkp, m);
- }
-#endif
template<class INT>
void enc(CipherTextA& c, const INT& m) const
{
@@ -990,6 +1190,7 @@ public:
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
Fr encRand;
+ encRand.setRand();
const MulG<G1> xPmul(xP_);
ElGamalEnc(c.S_, c.T_, m, PhashTbl_.getWM(), xPmul, &encRand);
makeZkpBin(zkp, c.S_, c.T_, encRand, P_, m, PhashTbl_.getWM(), xPmul);
@@ -997,6 +1198,7 @@ public:
void encWithZkpBin(CipherTextG2& c, ZkpBin& zkp, int m) const
{
Fr encRand;
+ encRand.setRand();
const MulG<G2> yQmul(yQ_);
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul, &encRand);
makeZkpBin(zkp, c.S_, c.T_, encRand, Q_, m, QhashTbl_.getWM(), yQmul);
@@ -1012,6 +1214,31 @@ public:
return verifyZkpBin(c.S_, c.T_, Q_, zkp, QhashTbl_.getWM(), yQmul);
}
template<class INT>
+ void encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const
+ {
+ const MulG<G1> xPmul(xP_);
+ const MulG<G2> yQmul(yQ_);
+ makeZkpEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, m, PhashTbl_.getWM(), xPmul, QhashTbl_.getWM(), yQmul);
+ }
+ bool verify(const CipherTextG1& c1, const CipherTextG2& c2, const ZkpEq& zkp) const
+ {
+ const MulG<G1> xPmul(xP_);
+ const MulG<G2> yQmul(yQ_);
+ return verifyZkpEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, PhashTbl_.getWM(), xPmul, QhashTbl_.getWM(), yQmul);
+ }
+ void encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const
+ {
+ const MulG<G1> xPmul(xP_);
+ const MulG<G2> yQmul(yQ_);
+ makeZkpBinEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, m, PhashTbl_.getWM(), xPmul, QhashTbl_.getWM(), yQmul);
+ }
+ bool verify(const CipherTextG1& c1, const CipherTextG2& c2, const ZkpBinEq& zkp) const
+ {
+ const MulG<G1> xPmul(xP_);
+ const MulG<G2> yQmul(yQ_);
+ return verifyZkpBinEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, PhashTbl_.getWM(), xPmul, QhashTbl_.getWM(), yQmul);
+ }
+ template<class INT>
void encGT(CipherTextGT& c, const INT& m) const
{
/*
@@ -1147,12 +1374,14 @@ public:
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
Fr encRand;
+ encRand.setRand();
ElGamalEnc(c.S_, c.T_, m, PhashTbl_.getWM(), xPwm_, &encRand);
makeZkpBin(zkp, c.S_, c.T_, encRand, P_, m, PhashTbl_.getWM(), xPwm_);
}
void encWithZkpBin(CipherTextG2& c, ZkpBin& zkp, int m) const
{
Fr encRand;
+ encRand.setRand();
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQwm_, &encRand);
makeZkpBin(zkp, c.S_, c.T_, encRand, Q_, m, QhashTbl_.getWM(), yQwm_);
}
@@ -1164,6 +1393,23 @@ public:
{
return verifyZkpBin(c.S_, c.T_, Q_, zkp, QhashTbl_.getWM(), yQwm_);
}
+ template<class INT>
+ void encWithZkpEq(CipherTextG1& c1, CipherTextG2& c2, ZkpEq& zkp, const INT& m) const
+ {
+ makeZkpEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, m, PhashTbl_.getWM(), xPwm_, QhashTbl_.getWM(), yQwm_);
+ }
+ bool verify(const CipherTextG1& c1, const CipherTextG2& c2, const ZkpEq& zkp) const
+ {
+ return verifyZkpEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, PhashTbl_.getWM(), xPwm_, QhashTbl_.getWM(), yQwm_);
+ }
+ void encWithZkpBinEq(CipherTextG1& c1, CipherTextG2& c2, ZkpBinEq& zkp, int m) const
+ {
+ makeZkpBinEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, m, PhashTbl_.getWM(), xPwm_, QhashTbl_.getWM(), yQwm_);
+ }
+ bool verify(const CipherTextG1& c1, const CipherTextG2& c2, const ZkpBinEq& zkp) const
+ {
+ return verifyZkpBinEq(zkp, c1.S_, c1.T_, c2.S_, c2.T_, PhashTbl_.getWM(), xPwm_, QhashTbl_.getWM(), yQwm_);
+ }
};
class CipherTextA {
CipherTextG1 c1_;
@@ -1471,6 +1717,8 @@ typedef SHE::CipherTextA CipherTextA;
typedef CipherTextGT CipherTextGM; // old class
typedef SHE::CipherText CipherText;
typedef SHE::ZkpBin ZkpBin;
+typedef SHE::ZkpEq ZkpEq;
+typedef SHE::ZkpBinEq ZkpBinEq;
} } // mcl::she
diff --git a/src/she_c_impl.hpp b/src/she_c_impl.hpp
index c6ed603..37d78e7 100644
--- a/src/she_c_impl.hpp
+++ b/src/she_c_impl.hpp
@@ -42,6 +42,12 @@ static const CipherTextGT *cast(const sheCipherTextGT *p) { return reinterpret_c
static ZkpBin *cast(sheZkpBin *p) { return reinterpret_cast<ZkpBin*>(p); }
static const ZkpBin *cast(const sheZkpBin *p) { return reinterpret_cast<const ZkpBin*>(p); }
+static ZkpEq *cast(sheZkpEq *p) { return reinterpret_cast<ZkpEq*>(p); }
+static const ZkpEq *cast(const sheZkpEq *p) { return reinterpret_cast<const ZkpEq*>(p); }
+
+static ZkpBinEq *cast(sheZkpBinEq *p) { return reinterpret_cast<ZkpBinEq*>(p); }
+static const ZkpBinEq *cast(const sheZkpBinEq *p) { return reinterpret_cast<const ZkpBinEq*>(p); }
+
int sheInit(int curve, int maxUnitSize)
try
{
@@ -125,6 +131,16 @@ mclSize sheZkpBinSerialize(void *buf, mclSize maxBufSize, const sheZkpBin *zkp)
return serialize(buf, maxBufSize, zkp);
}
+mclSize sheZkpEqSerialize(void *buf, mclSize maxBufSize, const sheZkpEq *zkp)
+{
+ return serialize(buf, maxBufSize, zkp);
+}
+
+mclSize sheZkpBinEqSerialize(void *buf, mclSize maxBufSize, const sheZkpBinEq *zkp)
+{
+ return serialize(buf, maxBufSize, zkp);
+}
+
template<class T>
mclSize deserialize(T *x, const void *buf, mclSize bufSize)
try
@@ -165,6 +181,16 @@ mclSize sheZkpBinDeserialize(sheZkpBin* zkp, const void *buf, mclSize bufSize)
return deserialize(zkp, buf, bufSize);
}
+mclSize sheZkpEqDeserialize(sheZkpEq* zkp, const void *buf, mclSize bufSize)
+{
+ return deserialize(zkp, buf, bufSize);
+}
+
+mclSize sheZkpBinEqDeserialize(sheZkpBinEq* zkp, const void *buf, mclSize bufSize)
+{
+ return deserialize(zkp, buf, bufSize);
+}
+
int sheSecretKeySetByCSPRNG(sheSecretKey *sec)
try
{
@@ -322,6 +348,27 @@ int shePrecomputedPublicKeyEncWithZkpBinG2(sheCipherTextG2 *c, sheZkpBin *zkp, c
return encWithZkpBinT(c, zkp, pub, m);
}
+template<class PK>
+int encWithZkpBinEqT(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpBinEq *zkp, const PK *pub, int m)
+ try
+{
+ cast(pub)->encWithZkpBinEq(*cast(c1), *cast(c2), *cast(zkp), m);
+ return 0;
+} catch (std::exception& e) {
+ fprintf(stderr, "err %s\n", e.what());
+ return -1;
+}
+
+int sheEncWithZkpBinEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpBinEq *zkp, const shePublicKey *pub, int m)
+{
+ return encWithZkpBinEqT(c1, c2, zkp, pub, m);
+}
+
+int shePrecomputedPublicKeyEncWithZkpBinEq(sheCipherTextG1 *c1, sheCipherTextG2 *c2, sheZkpBinEq *zkp, const shePrecomputedPublicKey *ppub, int m)
+{
+ return encWithZkpBinEqT(c1, c2, zkp, ppub, m);
+}
+
template<class CT>
int decT(mclInt *m, const sheSecretKey *sec, const CT *c)
try
@@ -618,3 +665,23 @@ int shePrecomputedPublicKeyVerifyZkpBinG2(const shePrecomputedPublicKey *pub, co
{
return verifyT(*cast(pub), *cast(c), *cast(zkp));
}
+
+template<class PK>
+int verifyT(const PK& pub, const CipherTextG1& c1, const CipherTextG2& c2, const ZkpBinEq& zkp)
+ try
+{
+ return pub.verify(c1, c2, zkp);
+} catch (std::exception& e) {
+ fprintf(stderr, "err %s\n", e.what());
+ return 0;
+}
+
+int sheVerifyZkpBinEq(const shePublicKey *pub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp)
+{
+ return verifyT(*cast(pub), *cast(c1), *cast(c2), *cast(zkp));
+}
+int shePrecomputedPublicKeyVerifyZkpBinEq(const shePrecomputedPublicKey *ppub, const sheCipherTextG1 *c1, const sheCipherTextG2 *c2, const sheZkpBinEq *zkp)
+{
+ return verifyT(*cast(ppub), *cast(c1), *cast(c2), *cast(zkp));
+}
+
diff --git a/test/she_c_test.hpp b/test/she_c_test.hpp
index 77bf893..a6d1176 100644
--- a/test/she_c_test.hpp
+++ b/test/she_c_test.hpp
@@ -317,6 +317,53 @@ CYBOZU_TEST_AUTO(ZkpBin)
shePrecomputedPublicKeyDestroy(ppub);
}
+template<class PK, class encWithZkpFunc, class verifyFunc>
+void ZkpBinEqTest(const sheSecretKey *sec, const PK *pub, encWithZkpFunc encWithZkp, verifyFunc verify)
+{
+ sheCipherTextG1 c1;
+ sheCipherTextG2 c2;
+ sheZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ CYBOZU_TEST_EQUAL(encWithZkp(&c1, &c2, &zkp, pub, m), 0);
+ mclInt mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG1(&mDec, sec, &c1), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ mDec = -1;
+ CYBOZU_TEST_EQUAL(sheDecG2(&mDec, sec, &c2), 0);
+ CYBOZU_TEST_EQUAL(mDec, m);
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 1);
+ {
+ char buf[2048];
+ size_t n = sheZkpBinEqSerialize(buf, sizeof(buf), &zkp);
+ CYBOZU_TEST_EQUAL(n, mclBn_getOpUnitSize() * 8 * 7);
+ sheZkpBinEq zkp2;
+ size_t r = sheZkpBinEqDeserialize(&zkp2, buf, n);
+ CYBOZU_TEST_EQUAL(r, n);
+ CYBOZU_TEST_ASSERT(memcmp(&zkp, &zkp2, n) == 0);
+ }
+ zkp.d[0].d[0]++;
+ CYBOZU_TEST_EQUAL(verify(pub, &c1, &c2, &zkp), 0);
+ }
+ CYBOZU_TEST_ASSERT(encWithZkp(&c1, &c2, &zkp, pub, 2) != 0);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ sheSecretKey sec;
+ sheSecretKeySetByCSPRNG(&sec);
+ shePublicKey pub;
+ sheGetPublicKey(&pub, &sec);
+
+ ZkpBinEqTest(&sec, &pub, sheEncWithZkpBinEq, sheVerifyZkpBinEq);
+
+ shePrecomputedPublicKey *ppub = shePrecomputedPublicKeyCreate();
+ CYBOZU_TEST_EQUAL(shePrecomputedPublicKeyInit(ppub, &pub), 0);
+
+ ZkpBinEqTest(&sec, ppub, shePrecomputedPublicKeyEncWithZkpBinEq, shePrecomputedPublicKeyVerifyZkpBinEq);
+
+ shePrecomputedPublicKeyDestroy(ppub);
+}
+
CYBOZU_TEST_AUTO(finalExp)
{
sheSecretKey sec;
diff --git a/test/she_test.cpp b/test/she_test.cpp
index dac5cbd..def7bd7 100644
--- a/test/she_test.cpp
+++ b/test/she_test.cpp
@@ -150,6 +150,62 @@ CYBOZU_TEST_AUTO(ZkpBin)
ZkpBinTest<CipherTextG2>(sec, ppub);
}
+template<class PubT>
+void ZkpEqTest(const SecretKey& sec, const PubT& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpEq zkp;
+ for (int m = -4; m < 4; m++) {
+ pub.encWithZkpEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+}
+
+CYBOZU_TEST_AUTO(ZkpEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpEqTest(sec, pub);
+ ZkpEqTest(sec, ppub);
+}
+
+template<class PK>
+void ZkpBinEqTest(const SecretKey& sec, const PK& pub)
+{
+ CipherTextG1 c1;
+ CipherTextG2 c2;
+ ZkpBinEq zkp;
+ for (int m = 0; m < 2; m++) {
+ pub.encWithZkpBinEq(c1, c2, zkp, m);
+ CYBOZU_TEST_EQUAL(sec.dec(c1), m);
+ CYBOZU_TEST_EQUAL(sec.dec(c2), m);
+ CYBOZU_TEST_ASSERT(pub.verify(c1, c2, zkp));
+ zkp.d_[0] += 1;
+ CYBOZU_TEST_ASSERT(!pub.verify(c1, c2, zkp));
+ }
+ CYBOZU_TEST_EXCEPTION(pub.encWithZkpBinEq(c1, c2, zkp, 2), cybozu::Exception);
+}
+
+CYBOZU_TEST_AUTO(ZkpBinEq)
+{
+ const SecretKey& sec = g_sec;
+ PublicKey pub;
+ sec.getPublicKey(pub);
+ ZkpBinEqTest(sec, pub);
+
+ PrecomputedPublicKey ppub;
+ ppub.init(pub);
+ ZkpBinEqTest(sec, ppub);
+}
+
CYBOZU_TEST_AUTO(add_sub_mul)
{
const SecretKey& sec = g_sec;