reduce parameter of elgamal

pull/2/head
MITSUNARI Shigeo 6 years ago
parent f33ef2ee85
commit 8cbdc129f6
  1. 86
      include/mcl/elgamal.hpp

@ -179,7 +179,6 @@ struct ElgamalT {
class PublicKey { class PublicKey {
size_t bitSize; size_t bitSize;
Ec f;
Ec g; Ec g;
Ec h; Ec h;
bool enableWindowMethod_; bool enableWindowMethod_;
@ -196,8 +195,6 @@ struct ElgamalT {
} }
} }
template<class N> template<class N>
void mulF(Ec& z, const N& n) const { mulDispatch(z, f, n, wm_f); }
template<class N>
void mulG(Ec& z, const N& n) const { mulDispatch(z, g, n, wm_g); } void mulG(Ec& z, const N& n) const { mulDispatch(z, g, n, wm_g); }
template<class N> template<class N>
void mulH(Ec& z, const N& n) const { mulDispatch(z, h, n, wm_h); } void mulH(Ec& z, const N& n) const { mulDispatch(z, h, n, wm_h); }
@ -209,16 +206,14 @@ struct ElgamalT {
} }
void enableWindowMethod(size_t winSize = 10) void enableWindowMethod(size_t winSize = 10)
{ {
wm_f.init(f, bitSize, winSize);
wm_g.init(g, bitSize, winSize); wm_g.init(g, bitSize, winSize);
wm_h.init(h, bitSize, winSize); wm_h.init(h, bitSize, winSize);
enableWindowMethod_ = true; enableWindowMethod_ = true;
} }
const Ec& getF() const { return f; } const Ec& getG() const { return g; }
void init(size_t bitSize, const Ec& f, const Ec& g, const Ec& h) void init(size_t bitSize, const Ec& g, const Ec& h)
{ {
this->bitSize = bitSize; this->bitSize = bitSize;
this->f = f;
this->g = g; this->g = g;
this->h = h; this->h = h;
enableWindowMethod_ = false; enableWindowMethod_ = false;
@ -227,7 +222,7 @@ struct ElgamalT {
/* /*
encode message encode message
input : m input : m
output : c = (c1, c2) = (g^u, h^u f^m) output : c = (c1, c2) = (g^u, h^u g^m)
*/ */
void enc(CipherText& c, const Zn& m, fp::RandGen rg = fp::RandGen()) const void enc(CipherText& c, const Zn& m, fp::RandGen rg = fp::RandGen()) const
{ {
@ -236,7 +231,7 @@ struct ElgamalT {
mulG(c.c1, u); mulG(c.c1, u);
mulH(c.c2, u); mulH(c.c2, u);
Ec t; Ec t;
mulF(t, m); mulG(t, m);
Ec::add(c.c2, c.c2, t); Ec::add(c.c2, c.c2, t);
} }
/* /*
@ -254,7 +249,7 @@ struct ElgamalT {
mulG(c.c1, u); mulG(c.c1, u);
mulH(c.c2, u); mulH(c.c2, u);
if (m) { if (m) {
Ec::add(c.c2, c.c2, f); Ec::add(c.c2, c.c2, g);
Zn r1; Zn r1;
r1.setRand(rg); r1.setRand(rg);
zkp.c0.setRand(rg); zkp.c0.setRand(rg);
@ -270,7 +265,7 @@ struct ElgamalT {
mulG(R11, r1); mulG(R11, r1);
mulH(R12, r1); mulH(R12, r1);
std::ostringstream os; std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << g << h;
Zn cc; Zn cc;
cc.setHashOf(os.str()); cc.setHashOf(os.str());
zkp.c1 = cc - zkp.c0; zkp.c1 = cc - zkp.c0;
@ -288,11 +283,11 @@ struct ElgamalT {
Ec::mul(t2, c.c1, zkp.c1); Ec::mul(t2, c.c1, zkp.c1);
Ec::sub(R11, t1, t2); Ec::sub(R11, t1, t2);
mulH(t1, zkp.s1); mulH(t1, zkp.s1);
Ec::sub(t2, c.c2, f); Ec::sub(t2, c.c2, g);
Ec::mul(t2, t2, zkp.c1); Ec::mul(t2, t2, zkp.c1);
Ec::sub(R12, t1, t2); Ec::sub(R12, t1, t2);
std::ostringstream os; std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << g << h;
Zn cc; Zn cc;
cc.setHashOf(os.str()); cc.setHashOf(os.str());
zkp.c0 = cc - zkp.c1; zkp.c0 = cc - zkp.c1;
@ -316,11 +311,11 @@ struct ElgamalT {
Ec::mul(t2, c.c1, zkp.c1); Ec::mul(t2, c.c1, zkp.c1);
Ec::sub(R11, t1, t2); Ec::sub(R11, t1, t2);
mulH(t1, zkp.s1); mulH(t1, zkp.s1);
Ec::sub(t2, c.c2, f); Ec::sub(t2, c.c2, g);
Ec::mul(t2, t2, zkp.c1); Ec::mul(t2, t2, zkp.c1);
Ec::sub(R12, t1, t2); Ec::sub(R12, t1, t2);
std::ostringstream os; std::ostringstream os;
os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << f << g << h; os << R01 << R02 << R11 << R12 << c.c1 << c.c2 << g << h;
Zn cc; Zn cc;
cc.setHashOf(os.str()); cc.setHashOf(os.str());
return cc == zkp.c0 + zkp.c1; return cc == zkp.c0 + zkp.c1;
@ -343,13 +338,13 @@ struct ElgamalT {
/* /*
add encoded message with plain message add encoded message with plain message
input : c = Enc(m1) = (c1, c2), m2 input : c = Enc(m1) = (c1, c2), m2
ouput : c = Enc(m1 + m2) = (c1, c2 f^m2) ouput : c = Enc(m1 + m2) = (c1, c2 g^m2)
*/ */
template<class N> template<class N>
void add(CipherText& c, const N& m) const void add(CipherText& c, const N& m) const
{ {
Ec fm; Ec fm;
mulF(fm, m); mulG(fm, m);
Ec::add(c.c2, c.c2, fm); Ec::add(c.c2, c.c2, fm);
} }
template<class InputStream> template<class InputStream>
@ -358,10 +353,9 @@ struct ElgamalT {
std::string s; std::string s;
mcl::fp::local::loadWord(s, is); mcl::fp::local::loadWord(s, is);
bitSize = cybozu::atoi(s); bitSize = cybozu::atoi(s);
f.load(is, ioMode);
g.load(is, ioMode); g.load(is, ioMode);
h.load(is, ioMode); h.load(is, ioMode);
init(bitSize, f, g, h); init(bitSize, g, h);
} }
template<class OutputStream> template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const void save(OutputStream& os, int ioMode = IoSerialize) const
@ -371,7 +365,6 @@ struct ElgamalT {
cybozu::writeChar(os, ' '); cybozu::writeChar(os, ' ');
const char sep = *fp::getIoSeparator(ioMode); const char sep = *fp::getIoSeparator(ioMode);
f.save(os, ioMode);
if (sep) cybozu::writeChar(os, sep); if (sep) cybozu::writeChar(os, sep);
g.save(os, ioMode); g.save(os, ioMode);
if (sep) cybozu::writeChar(os, sep); if (sep) cybozu::writeChar(os, sep);
@ -410,7 +403,7 @@ struct ElgamalT {
void fromStr(const std::string& str) { setStr(str); } void fromStr(const std::string& str) { setStr(str); }
}; };
/* /*
create table f^i for i in [rangeMin, rangeMax] create table g^i for i in [rangeMin, rangeMax]
*/ */
struct PowerCache { struct PowerCache {
#if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CP03) #if (CYBOZU_CPP_VERSION > CYBOZU_CPP_VERSION_CP03)
@ -419,18 +412,18 @@ struct ElgamalT {
typedef std::map<Ec, int> Cache; typedef std::map<Ec, int> Cache;
#endif #endif
Cache cache; Cache cache;
void init(const Ec& f, int rangeMin, int rangeMax) void init(const Ec& g, int rangeMin, int rangeMax)
{ {
if (rangeMin > rangeMax) throw cybozu::Exception("mcl:ElgamalT:PowerCache:bad range") << rangeMin << rangeMax; if (rangeMin > rangeMax) throw cybozu::Exception("mcl:ElgamalT:PowerCache:bad range") << rangeMin << rangeMax;
Ec x; Ec x;
x.clear(); x.clear();
cache[x] = 0; cache[x] = 0;
for (int i = 1; i <= rangeMax; i++) { for (int i = 1; i <= rangeMax; i++) {
Ec::add(x, x, f); Ec::add(x, x, g);
cache[x] = i; cache[x] = i;
} }
Ec nf; Ec nf;
Ec::neg(nf, f); Ec::neg(nf, g);
x.clear(); x.clear();
for (int i = -1; i >= rangeMin; i--) { for (int i = -1; i >= rangeMin; i--) {
Ec::add(x, x, nf); Ec::add(x, x, nf);
@ -438,17 +431,17 @@ struct ElgamalT {
} }
} }
/* /*
return m such that f^m = g return m such that g^m = y
*/ */
int getExponent(const Ec& g, bool *b = 0) const int getExponent(const Ec& y, bool *b = 0) const
{ {
typename Cache::const_iterator i = cache.find(g); typename Cache::const_iterator i = cache.find(y);
if (i == cache.end()) { if (i == cache.end()) {
if (b) { if (b) {
*b = false; *b = false;
return 0; return 0;
} }
throw cybozu::Exception("Elgamal:PowerCache:getExponent:not found") << g; throw cybozu::Exception("Elgamal:PowerCache:getExponent:not found") << y;
} }
if (b) *b = true; if (b) *b = true;
return i->second; return i->second;
@ -469,20 +462,17 @@ struct ElgamalT {
public: public:
/* /*
init init
input : f input : g
output : (g, h, z) output : (h, z)
Ec = <f> Ec = <g>
g in Ec
h = g^z h = g^z
*/ */
void init(const Ec& f, size_t bitSize, fp::RandGen rg = fp::RandGen()) void init(const Ec& g, size_t bitSize, fp::RandGen rg = fp::RandGen())
{ {
Ec g, h; Ec h;
z.setRand(rg);
Ec::mul(g, f, z);
z.setRand(rg); z.setRand(rg);
Ec::mul(h, g, z); Ec::mul(h, g, z);
pub.init(bitSize, f, g, h); pub.init(bitSize, g, h);
} }
const PublicKey& getPublicKey() const { return pub; } const PublicKey& getPublicKey() const { return pub; }
/* /*
@ -490,12 +480,12 @@ struct ElgamalT {
input : c = (c1, c2) input : c = (c1, c2)
output : m output : m
M = c2 / c1^z M = c2 / c1^z
find m such that M = f^m and |m| < limit find m such that M = g^m and |m| < limit
@memo 7sec@core i3 for m = 1e6 @memo 7sec@core i3 for m = 1e6
*/ */
void dec(Zn& m, const CipherText& c, int limit = 100000) const void dec(Zn& m, const CipherText& c, int limit = 100000) const
{ {
const Ec& f = pub.getF(); const Ec& g = pub.getG();
Ec c1z; Ec c1z;
Ec::mul(c1z, c.c1, z); Ec::mul(c1z, c.c1, z);
if (c1z == c.c2) { if (c1z == c.c2) {
@ -505,12 +495,12 @@ struct ElgamalT {
Ec t1(c1z); Ec t1(c1z);
Ec t2(c.c2); Ec t2(c.c2);
for (int i = 1; i < limit; i++) { for (int i = 1; i < limit; i++) {
Ec::add(t1, t1, f); Ec::add(t1, t1, g);
if (t1 == c.c2) { if (t1 == c.c2) {
m = i; m = i;
return; return;
} }
Ec::add(t2, t2, f); Ec::add(t2, t2, g);
if (t2 == c1z) { if (t2 == c1z) {
m = -i; m = -i;
return; return;
@ -519,20 +509,20 @@ struct ElgamalT {
throw cybozu::Exception("elgamal:PrivateKey:dec:overflow"); throw cybozu::Exception("elgamal:PrivateKey:dec:overflow");
} }
/* /*
powfm = c2 / c1^z = f^m powgm = c2 / c1^z = g^m
*/ */
void getPowerf(Ec& powfm, const CipherText& c) const void getPowerg(Ec& powgm, const CipherText& c) const
{ {
Ec c1z; Ec c1z;
Ec::mul(c1z, c.c1, z); Ec::mul(c1z, c.c1, z);
Ec::sub(powfm, c.c2, c1z); Ec::sub(powgm, c.c2, c1z);
} }
/* /*
set range of message to decode quickly set range of message to decode quickly
*/ */
void setCache(int rangeMin, int rangeMax) void setCache(int rangeMin, int rangeMax)
{ {
cache.init(pub.getF(), rangeMin, rangeMax); cache.init(pub.getG(), rangeMin, rangeMax);
} }
/* /*
clear cache clear cache
@ -550,9 +540,9 @@ struct ElgamalT {
*/ */
int dec(const CipherText& c, bool *b = 0) const int dec(const CipherText& c, bool *b = 0) const
{ {
Ec powfm; Ec powgm;
getPowerf(powfm, c); getPowerg(powgm, c);
return cache.getExponent(powfm, b); return cache.getExponent(powgm, b);
} }
/* /*
check whether c is encrypted zero message check whether c is encrypted zero message

Loading…
Cancel
Save