aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/bls.hpp26
-rw-r--r--src/bls.cpp93
-rw-r--r--test/bls_test.cpp29
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);
+ }
+}