|
|
|
@ -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_; |
|
|
|
|