split CipherTextA and CipherTextM

dev
MITSUNARI Shigeo 8 years ago
parent 1fa9768f3c
commit e38c542a95
  1. 146
      include/mcl/bgn.hpp
  2. 2
      test/bgn_test.cpp

@ -283,6 +283,8 @@ struct BGNT {
class SecretKey; class SecretKey;
class PublicKey; class PublicKey;
class CipherTextA; // additive HE
class CipherTextM; // multiplicative HE
class CipherText; class CipherText;
static G1 P; static G1 P;
@ -341,6 +343,7 @@ struct BGNT {
G2::mul(pub.yQ, Q, y2); G2::mul(pub.yQ, Q, y2);
G2::mul(pub.zQ, Q, z2); G2::mul(pub.zQ, Q, z2);
} }
#if 0
// log_x(y) // log_x(y)
int log(const GT& x, const GT& y) const int log(const GT& x, const GT& y) const
{ {
@ -358,9 +361,9 @@ struct BGNT {
} }
throw cybozu::Exception("BGN:dec:log:not found"); throw cybozu::Exception("BGN:dec:log:not found");
} }
int dec(const CipherText& c) const #endif
int64_t dec(const CipherTextA& c) const
{ {
if (!c.isMultiplied()) {
/* /*
S = myP + rP S = myP + rP
T = mzP + rxP T = mzP + rxP
@ -370,7 +373,7 @@ struct BGNT {
G1::mul(R1, c.S1, x1); G1::mul(R1, c.S1, x1);
R1 -= c.T1; R1 -= c.T1;
// int m1 = local::log(B1, R1); // int m1 = local::log(B1, R1);
int m1 = ecHashTbl.log(R1); int64_t m1 = ecHashTbl.log(R1);
#if 0 // for debug #if 0 // for debug
G2 R2; G2 R2;
G2::mul(R2, c.S2, x2); G2::mul(R2, c.S2, x2);
@ -382,6 +385,8 @@ struct BGNT {
#endif #endif
return m1; return m1;
} }
int64_t dec(const CipherTextM& c) const
{
/* /*
(s, t, u, v) := (e(S, S'), e(S, T'), e(T, S'), e(T, T')) (s, t, u, v) := (e(S, S'), e(S, T'), e(T, S'), e(T, T'))
s^(xx') v / (t^x u^x') s^(xx') v / (t^x u^x')
@ -402,6 +407,14 @@ struct BGNT {
return gtHashTbl.log(s); return gtHashTbl.log(s);
// return log(g, s); // return log(g, s);
} }
int64_t dec(const CipherText& c) const
{
if (c.isMultiplied()) {
return dec(c.m);
} else {
return dec(c.a);
}
}
}; };
class PublicKey { class PublicKey {
@ -426,34 +439,51 @@ struct BGNT {
} }
public: public:
template<class RG> template<class RG>
void enc(CipherText& c, int m, RG& rg) const void enc(CipherTextA& c, int m, RG& rg) const
{ {
enc1(c.S1, c.T1, P, xP, yP, zP, m, rg); enc1(c.S1, c.T1, P, xP, yP, zP, m, rg);
enc1(c.S2, c.T2, Q, xQ, yQ, zQ, m, rg); enc1(c.S2, c.T2, Q, xQ, yQ, zQ, m, rg);
} }
template<class RG>
void enc(CipherText& c, int m, RG& rg) const
{
c.isMultiplied_ = false;
enc(c.a, m, rg);
}
/* /*
cy = cx * Enc(1) convert from CipherTextA to CipherTextM
cm = ca * Enc(1)
*/ */
void mulEnc1(CipherText& cy, const CipherText& cx) const void convertCipherText(CipherTextM& cm, const CipherTextA& ca) const
{ {
if (cx.isMultiplied()) throw cybozu::Exception("PublicKey:mulEnc1:already multiplied");
/* /*
Enc(1) = (S, T) = (yP + rP, zP + r xP) = (yP, zP) if r = 0 Enc(1) = (S, T) = (yP + rP, zP + r xP) = (yP, zP) if r = 0
cy = cx * (yP, zP) cm = ca * (yP, zP)
*/ */
cy.g.resize(4); BN::millerLoop(cm.g[0], yP, ca.S2);
BN::millerLoop(cy.g[0], yP, cx.S2); BN::millerLoop(cm.g[1], yP, ca.T2);
BN::millerLoop(cy.g[1], yP, cx.T2); BN::millerLoop(cm.g[2], zP, ca.S2);
BN::millerLoop(cy.g[2], zP, cx.S2); BN::millerLoop(cm.g[3], zP, ca.T2);
BN::millerLoop(cy.g[3], zP, cx.T2); }
void convertCipherText(CipherText& cm, const CipherText& ca) const
{
if (ca.isMultiplied()) throw cybozu::Exception("bgn:PublicKey:convertCipherText:already isMultiplied");
cm.isMultiplied_ = true;
convertCipherText(cm.m, ca.a);
} }
/* /*
c += Enc(0) c += Enc(0)
*/ */
template<class RG> template<class RG>
void rerandomize(CipherText& c, RG& rg) const void rerandomize(CipherTextA& c, RG& rg) const
{
CipherTextA c0;
enc(c0, 0, rg);
addA(c, c, c0);
}
template<class RG>
void rerandomize(CipherTextM& c, RG& rg) const
{ {
if (c.isMultiplied()) {
/* /*
add Enc(0) * Enc(0) add Enc(0) * Enc(0)
(S1, T1) * (S2, T2) = (rP, rxP) * (r'Q, r'xQ) (S1, T1) * (S2, T2) = (rP, rxP) * (r'Q, r'xQ)
@ -474,35 +504,38 @@ struct BGNT {
c.g[2] *= e; c.g[2] *= e;
BN::millerLoop(e, T1, xQ); BN::millerLoop(e, T1, xQ);
c.g[3] *= e; c.g[3] *= e;
}
template<class RG>
void rerandomize(CipherText& c, RG& rg) const
{
if (c.isMultiplied()) {
rerandomize(c.m, rg);
} else { } else {
CipherText c0; rerandomize(c.a, rg);
enc(c0, 0, rg);
c.add(c0);
} }
} }
}; };
class CipherText { class CipherTextA {
typedef std::vector<GT> GTVec; public:
G1 S1, T1; G1 S1, T1;
G2 S2, T2; G2 S2, T2;
GTVec g;
friend class SecretKey; friend class SecretKey;
friend class PublicKey; friend class PublicKey;
public: public:
bool isMultiplied() const { return !g.empty(); } void add(const CipherTextA& c) { add(*this, *this, c); }
static inline void add(CipherText& z, const CipherText& x, const CipherText& y) };
class CipherTextM {
public:
GT g[4];
friend class SecretKey;
friend class PublicKey;
public:
};
static inline void addA(CipherTextA& z, const CipherTextA& x, const CipherTextA& y)
{ {
if (x.isMultiplied() && y.isMultiplied()) {
/*
(g[i]) * (g'[i]) = (g[i] * g'[i])
*/
for (size_t i = 0; i < z.g.size(); i++) {
GT::mul(z.g[i], x.g[i], y.g[i]);
}
return;
}
if (!x.isMultiplied() && !y.isMultiplied()) {
/* /*
(S, T) + (S', T') = (S + S', T + T') (S, T) + (S', T') = (S + S', T + T')
*/ */
@ -510,25 +543,58 @@ struct BGNT {
G1::add(z.T1, x.T1, y.T1); G1::add(z.T1, x.T1, y.T1);
G2::add(z.S2, x.S2, y.S2); G2::add(z.S2, x.S2, y.S2);
G2::add(z.T2, x.T2, y.T2); G2::add(z.T2, x.T2, y.T2);
return;
} }
throw cybozu::Exception("bgn:CipherText:add:mixed CipherText") << x.isMultiplied() << y.isMultiplied(); static inline void addM(CipherTextM& z, const CipherTextM& x, const CipherTextM& y)
}
static inline void mul(CipherText& z, const CipherText& x, const CipherText& y)
{ {
if (x.isMultiplied() || y.isMultiplied()) { /*
throw cybozu::Exception("bgn:CipherText:mul:already mul"); (g[i]) * (g'[i]) = (g[i] * g'[i])
*/
for (size_t i = 0; i < 4; i++) {
GT::mul(z.g[i], x.g[i], y.g[i]);
} }
}
static inline void mulA(CipherTextM& z, const CipherTextA& x, const CipherTextA& y)
{
/* /*
(S1, T1) * (S2, T2) = (e(S1, S2), e(S1, T2), e(T1, S2), e(T1, T2)) (S1, T1) * (S2, T2) = (e(S1, S2), e(S1, T2), e(T1, S2), e(T1, T2))
call finalExp at once in decrypting c call finalExp at once in decrypting c
*/ */
z.g.resize(4);
BN::millerLoop(z.g[0], x.S1, y.S2); BN::millerLoop(z.g[0], x.S1, y.S2);
BN::millerLoop(z.g[1], x.S1, y.T2); BN::millerLoop(z.g[1], x.S1, y.T2);
BN::millerLoop(z.g[2], x.T1, y.S2); BN::millerLoop(z.g[2], x.T1, y.S2);
BN::millerLoop(z.g[3], x.T1, y.T2); BN::millerLoop(z.g[3], x.T1, y.T2);
} }
class CipherText {
CipherTextA a;
CipherTextM m;
bool isMultiplied_;
friend class SecretKey;
friend class PublicKey;
public:
CipherText() : isMultiplied_(false) {}
bool isMultiplied() const { return isMultiplied_; }
static inline void add(CipherText& z, const CipherText& x, const CipherText& y)
{
if (x.isMultiplied() && y.isMultiplied()) {
z.isMultiplied_ = true;
addM(z.m, x.m, y.m);
return;
}
if (!x.isMultiplied() && !y.isMultiplied()) {
z.isMultiplied_ = false;
addA(z.a, x.a, y.a);
return;
}
throw cybozu::Exception("bgn:CipherText:add:mixed CipherText");
}
static inline void mul(CipherText& z, const CipherText& x, const CipherText& y)
{
if (x.isMultiplied() || y.isMultiplied()) {
throw cybozu::Exception("bgn:CipherText:mul:mixed CipherText");
}
z.isMultiplied_ = true;
mulA(z.m, x.a, y.a);
}
void add(const CipherText& c) { add(*this, *this, c); } void add(const CipherText& c) { add(*this, *this, c); }
void mul(const CipherText& c) { mul(*this, *this, c); } void mul(const CipherText& c) { mul(*this, *this, c); }
}; };

@ -125,7 +125,7 @@ CYBOZU_TEST_AUTO(add_mul_add)
CYBOZU_TEST_EQUAL(sec.dec(c[i]), m[i]); CYBOZU_TEST_EQUAL(sec.dec(c[i]), m[i]);
CYBOZU_TEST_ASSERT(!c[i].isMultiplied()); CYBOZU_TEST_ASSERT(!c[i].isMultiplied());
CipherText mc; CipherText mc;
pub.mulEnc1(mc, c[i]); pub.convertCipherText(mc, c[i]);
CYBOZU_TEST_ASSERT(mc.isMultiplied()); CYBOZU_TEST_ASSERT(mc.isMultiplied());
CYBOZU_TEST_EQUAL(sec.dec(mc), m[i]); CYBOZU_TEST_EQUAL(sec.dec(mc), m[i]);
} }

Loading…
Cancel
Save