diff options
-rw-r--r-- | include/bls.hpp | 26 | ||||
-rw-r--r-- | src/bls.cpp | 93 | ||||
-rw-r--r-- | test/bls_test.cpp | 29 |
3 files changed, 136 insertions, 12 deletions
diff --git a/include/bls.hpp b/include/bls.hpp index 82378be..fc29d5c 100644 --- a/include/bls.hpp +++ b/include/bls.hpp @@ -17,6 +17,7 @@ namespace impl { struct PublicKey; struct PrivateKey; struct Sign; +struct Verifier; } // bls::impl @@ -48,6 +49,24 @@ public: void recover(const std::vector<Sign>& signVec); }; +/* + Feldman's verifiable secret sharing +*/ +class Verifier { + impl::Verifier *self_; + friend class PrivateKey; + friend class PublicKey; +public: + Verifier(); + ~Verifier(); + Verifier(const Verifier& rhs); + Verifier& operator=(const Verifier& rhs); + bool operator==(const Verifier& rhs) const; + bool operator!=(const Verifier& rhs) const { return !(*this == rhs); } + friend std::ostream& operator<<(std::ostream& os, const Verifier& ver); + friend std::istream& operator>>(std::istream& is, Verifier& ver); +}; + class PublicKey { impl::PublicKey *self_; int id_; @@ -71,6 +90,10 @@ public: recover publicKey from k pubVec */ void recover(const std::vector<PublicKey>& pubVec); + /* + validate self by Verifier + */ + bool isValid(const Verifier& ver) const; }; class PrivateKey { @@ -95,8 +118,9 @@ public: void sign(Sign& sign, const std::string& m) const; /* k-out-of-n secret sharing of privateKey + set verifier if ver is not 0 */ - void share(std::vector<PrivateKey>& prvVec, int n, int k); + void share(std::vector<PrivateKey>& prvVec, int n, int k, Verifier *ver = 0); /* recover privateKey from k prvVec */ diff --git a/src/bls.cpp b/src/bls.cpp index 8577c95..898542b 100644 --- a/src/bls.cpp +++ b/src/bls.cpp @@ -52,13 +52,28 @@ static const G2& getQ() return Q; } -static void HashAndMapToG1(G1& P, const std::string& m) +static void mapToG1(G1& P, const Fp& t) { static mcl::bn::MapTo<Fp> mapTo; + mapTo.calcG1(P, t); +} +static void HashAndMapToG1(G1& P, const std::string& m) +{ std::string digest = cybozu::crypto::Hash::digest(cybozu::crypto::Hash::N_SHA256, m); Fp t; t.setArrayMask(digest.c_str(), digest.size()); - mapTo.calcG1(P, t); + mapToG1(P, t); +} + +template<class T, class G> +void evalPoly(G& y, const T& x, const std::vector<G>& c) +{ + if (c.size() < 2) throw cybozu::Exception("bls:evalPoly:bad size") << c.size(); + y = c[c.size() - 1]; + for (int i = (int)c.size() - 2; i >= 0; i--) { + G::mul(y, y, x); + G::add(y, y, c[i]); + } } struct Polynomial { @@ -76,13 +91,7 @@ struct Polynomial { void eval(Fr& y, int id) const { if (id == 0) throw cybozu::Exception("bls:Polynomial:eval:id is zero"); - if (c.size() < 2) throw cybozu::Exception("bls:Polynomial:eval:bad size") << c.size(); - const Fr x(id); - y = c[c.size() - 1]; - for (int i = (int)c.size() - 2; i >= 0; i--) { - y *= x; - y += c[i]; - } + evalPoly(y, Fr(id), c); } }; @@ -155,6 +164,10 @@ struct PublicKey { const G2& get() const { return sQ; } }; +struct Verifier { + std::vector<G2> vecR; +}; + struct PrivateKey { Fr s; const Fr& get() const { return s; } @@ -236,6 +249,53 @@ void Sign::recover(const std::vector<Sign>& signVec) id_ = 0; } +Verifier::Verifier() + : self_(new impl::Verifier()) +{ +} + +Verifier::~Verifier() +{ + delete self_; +} + +Verifier::Verifier(const Verifier& rhs) + : self_(new impl::Verifier(*rhs.self_)) +{ +} + +Verifier& Verifier::operator=(const Verifier& rhs) +{ + *self_ = *rhs.self_; + return *this; +} + +bool Verifier::operator==(const Verifier& rhs) const +{ + return self_->vecR == rhs.self_->vecR; +} + +std::ostream& operator<<(std::ostream& os, const Verifier& ver) +{ + const size_t n = ver.self_->vecR.size(); + os << n; + for (size_t i = 0; i < n; i++) { + os << '\n' << ver.self_->vecR[i]; + } + return os; +} + +std::istream& operator>>(std::istream& is, Verifier& ver) +{ + size_t n; + is >> n; + ver.self_->vecR.resize(n); + for (size_t i = 0; i < n; i++) { + is >> ver.self_->vecR[i]; + } + return is; +} + PublicKey::PublicKey() : self_(new impl::PublicKey()) , id_(0) @@ -301,6 +361,13 @@ void PublicKey::recover(const std::vector<PublicKey>& pubVec) id_ = 0; } +bool PublicKey::isValid(const Verifier& ver) const +{ + G2 v; + evalPoly(v, Fr(id_), ver.self_->vecR); + return v == self_->sQ; +} + PrivateKey::PrivateKey() : self_(new impl::PrivateKey()) , id_(0) @@ -370,7 +437,7 @@ void PrivateKey::sign(Sign& sign, const std::string& m) const sign.id_ = id_; } -void PrivateKey::share(std::vector<PrivateKey>& prvVec, int n, int k) +void PrivateKey::share(std::vector<PrivateKey>& prvVec, int n, int k, Verifier *ver) { if (id_ != 0) throw cybozu::Exception("bls:PrivateKey:share:already shared") << id_; if (n <= 0 || k <= 0 || k > n) throw cybozu::Exception("bls:PrivateKey:share:bad n, k") << n << k; @@ -382,6 +449,12 @@ void PrivateKey::share(std::vector<PrivateKey>& prvVec, int n, int k) poly.eval(prvVec[i].self_->s, id); prvVec[i].id_ = id; } + if (ver == 0) return; + std::vector<G2>& vecR = ver->self_->vecR; + vecR.resize(k); + for (size_t i = 0; i < vecR.size(); i++) { + G2::mul(vecR[i], getQ(), poly.c[i]); + } } void PrivateKey::recover(const std::vector<PrivateKey>& prvVec) diff --git a/test/bls_test.cpp b/test/bls_test.cpp index 59924d9..a2bcc08 100644 --- a/test/bls_test.cpp +++ b/test/bls_test.cpp @@ -1,6 +1,7 @@ #include <bls.hpp> #include <cybozu/test.hpp> #include <iostream> +#include <sstream> CYBOZU_TEST_AUTO(bls) { @@ -42,7 +43,6 @@ CYBOZU_TEST_AUTO(bls) CYBOZU_TEST_AUTO(k_of_n) { - bls::init(); const std::string m = "abc"; const int n = 5; const int k = 3; @@ -170,3 +170,30 @@ CYBOZU_TEST_AUTO(k_of_n) CYBOZU_TEST_EQUAL(pub, pub0); } } + +CYBOZU_TEST_AUTO(verifier) +{ + const int n = 6; + const int k = 3; + bls::PrivateKey prv0; + prv0.init(); + bls::PublicKey pub0; + prv0.getPublicKey(pub0); + std::vector<bls::PrivateKey> prvVec; + bls::Verifier ver; + prv0.share(prvVec, n, k, &ver); + CYBOZU_TEST_ASSERT(pub0.isValid(ver)); + for (size_t i = 0; i < prvVec.size(); i++) { + bls::PublicKey pub; + prvVec[i].getPublicKey(pub); + CYBOZU_TEST_ASSERT(pub.isValid(ver)); + } + { + std::ostringstream oss; + oss << ver; + bls::Verifier ver2; + std::istringstream iss(oss.str()); + iss >> ver2; + CYBOZU_TEST_EQUAL(ver, ver2); + } +} |