[she] add ZkpBin for m = 0 or 1

dev
MITSUNARI Shigeo 7 years ago
parent eab7d579e5
commit 8c665543ad
  1. 286
      include/mcl/she.hpp
  2. 31
      test/she_test.cpp

@ -730,6 +730,115 @@ public:
bool operator!=(const SecretKey& rhs) const { return !operator==(rhs); }
};
private:
/*
simple ElGamal encryptionfor G1 and G2
(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
*/
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)
{
Fr r;
r.setRand();
if (encRand) *encRand = r;
Pmul.mul(static_cast<I&>(T), r);
xPmul.mul(S, r); // S = r xP
if (m == 0) return;
G C;
Pmul.mul(static_cast<I&>(C), m);
S += C;
}
/*
encRand is a random value used for ElGamalEnc()
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<class G, class I, class MulG>
static void makeZkpBin(ZkpBin& zkp, const G& S, const G& T, const Fr& encRand, const G& P, int m, const mcl::fp::WindowMethod<I>& Pmul, const MulG& xPmul)
{
if (m != 0 && m != 1) throw cybozu::Exception("makeZkpBin: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;
Pmul.mul(static_cast<I&>(T1), s[1-m]); // T1 = s[1-m] P
G::mul(T2, T, d[1-m]);
G::sub(R[0][1-m], T1, T2); // s[1-m] P - d[1-m]T
xPmul.mul(T1, s[1-m]); // T1 = s[1-m] xP
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();
Pmul.mul(static_cast<I&>(R[0][m]), r); // R[0][m] = r P
xPmul.mul(R[1][m], r); // R[1][m] = r xP
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<class G, class I, class MulG>
static bool verifyZkpBin(const G& S, const G& T, const G& P, const ZkpBin& zkp, const mcl::fp::WindowMethod<I>& Pmul, const MulG& xPmul)
{
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++) {
Pmul.mul(static_cast<I&>(T1), s[i]); // T1 = s[i] P
G::mul(T2, T, d[i]);
G::sub(R[0][i], T1, T2);
}
xPmul.mul(T1, s[0]); // T1 = s[0] xP
G::mul(T2, S, d[0]);
G::sub(R[1][0], T1, T2);
xPmul.mul(T1, s[1]); // T1 = x[1] xP
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];
}
/*
common method for PublicKey and PrecomputedPublicKey
*/
@ -850,112 +959,16 @@ public:
friend class PrecomputedPublicKey;
template<class T>
friend struct PublicKeyMethod;
/*
(S, T) = (m P + r xP, rP)
*/
template<class G, class INT, class I>
static void enc1(G& S, G& T, const G& /*P*/, const G& xP, const INT& m, const mcl::fp::WindowMethod<I>& wm, Fr *encRand = 0)
{
Fr r;
r.setRand();
if (encRand) *encRand = r;
// G::mul(T, P, r);
wm.mul(static_cast<I&>(T), r);
G::mul(S, xP, r);
if (m == 0) return;
G C;
// G::mul(C, P, m);
wm.mul(static_cast<I&>(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<class G>
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<class G>
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);
struct MulG {
const G& base;
MulG(const G& base) : base(base) {}
template<class INT>
void mul(G& out, const INT& m) const
{
G::mul(out, base, m);
}
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);
@ -964,23 +977,39 @@ public:
template<class INT>
void encG1(CipherTextG1& c, const INT& m) const
{
enc1(c.S_, c.T_, P_, xP_, m, PhashTbl_.getWM());
const MulG<G1> xPmul(xP_);
ElGamalEnc(c.S_, c.T_, m, PhashTbl_.getWM(), xPmul);
}
template<class INT>
void encG2(CipherTextG2& c, const INT& m) const
{
enc1(c.S_, c.T_, Q_, yQ_, m, QhashTbl_.getWM());
const MulG<G2> yQmul(yQ_);
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQmul);
}
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);
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);
}
void encWithZkpBin(CipherTextG2& c, ZkpBin& zkp, int m) const
{
Fr encRand;
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);
}
bool verify(const CipherTextG1& c, const ZkpBin& zkp) const
{
return verifyZkpBin(c.S_, c.T_, P_, xP_, zkp);
const MulG<G1> xPmul(xP_);
return verifyZkpBin(c.S_, c.T_, P_, zkp, PhashTbl_.getWM(), xPmul);
}
bool verify(const CipherTextG2& c, const ZkpBin& zkp) const
{
const MulG<G2> yQmul(yQ_);
return verifyZkpBin(c.S_, c.T_, Q_, zkp, QhashTbl_.getWM(), yQmul);
}
template<class INT>
void encGT(CipherTextGT& c, const INT& m) const
@ -1072,30 +1101,15 @@ public:
{
wm.mul(static_cast<GTasEC&>(x), y);
}
/*
(S, T) = (m P + r xP, rP)
*/
template<class G, class INT, class I>
void enc1(G& S, G& T, const INT& m, const mcl::fp::WindowMethod<I>& Pwm, const mcl::fp::WindowMethod<G>& xPwm) const
{
Fr r;
r.setRand();
Pwm.mul(static_cast<I&>(T), r);
xPwm.mul(S, r);
if (m == 0) return;
G C;
Pwm.mul(static_cast<I&>(C), m);
S += C;
}
template<class INT>
void encG1(CipherTextG1& c, const INT& m) const
{
enc1(c.S_, c.T_, m, PhashTbl_.getWM(), xPwm_);
ElGamalEnc(c.S_, c.T_, m, PhashTbl_.getWM(), xPwm_);
}
template<class INT>
void encG2(CipherTextG2& c, const INT& m) const
{
enc1(c.S_, c.T_, m, QhashTbl_.getWM(), yQwm_);
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQwm_);
}
template<class INT>
void encGT(CipherTextGT& c, const INT& m) const
@ -1130,6 +1144,26 @@ public:
xPwm_.init(pub.xP_, bitSize, local::winSize);
yQwm_.init(pub.yQ_, bitSize, local::winSize);
}
void encWithZkpBin(CipherTextG1& c, ZkpBin& zkp, int m) const
{
Fr encRand;
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;
ElGamalEnc(c.S_, c.T_, m, QhashTbl_.getWM(), yQwm_, &encRand);
makeZkpBin(zkp, c.S_, c.T_, encRand, Q_, m, QhashTbl_.getWM(), yQwm_);
}
bool verify(const CipherTextG1& c, const ZkpBin& zkp) const
{
return verifyZkpBin(c.S_, c.T_, P_, zkp, PhashTbl_.getWM(), xPwm_);
}
bool verify(const CipherTextG2& c, const ZkpBin& zkp) const
{
return verifyZkpBin(c.S_, c.T_, Q_, zkp, QhashTbl_.getWM(), yQwm_);
}
};
class CipherTextA {
CipherTextG1 c1_;

@ -122,21 +122,32 @@ CYBOZU_TEST_AUTO(enc_dec)
}
}
CYBOZU_TEST_AUTO(ZkpBin)
template<class CT, class PK>
void ZkpBinTest(const SecretKey& sec, const PK& pub)
{
const SecretKey& sec = g_sec;
PublicKey pub;
sec.getPublicKey(pub);
CipherTextG1 c1;
CT c;
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));
pub.encWithZkpBin(c, zkp, m);
CYBOZU_TEST_EQUAL(sec.dec(c), m);
CYBOZU_TEST_ASSERT(pub.verify(c, zkp));
zkp.d_[0] += 1;
CYBOZU_TEST_ASSERT(!pub.verify(c1, zkp));
CYBOZU_TEST_ASSERT(!pub.verify(c, zkp));
}
CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c1, zkp, 2), cybozu::Exception);
CYBOZU_TEST_EXCEPTION(pub.encWithZkpBin(c, zkp, 2), cybozu::Exception);
}
CYBOZU_TEST_AUTO(ZkpBin)
{
const SecretKey& sec = g_sec;
PublicKey pub;
sec.getPublicKey(pub);
ZkpBinTest<CipherTextG1>(sec, pub);
ZkpBinTest<CipherTextG2>(sec, pub);
PrecomputedPublicKey ppub;
ppub.init(pub);
ZkpBinTest<CipherTextG1>(sec, ppub);
ZkpBinTest<CipherTextG2>(sec, ppub);
}
CYBOZU_TEST_AUTO(add_sub_mul)

Loading…
Cancel
Save