a portable and fast pairing-based cryptography library
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 
mcl/include/mcl/aggregate_sig.hpp

265 lines
6.5 KiB

#pragma once
/**
@file
@brief aggregate signature
@author MITSUNARI Shigeo(@herumi)
see http://crypto.stanford.edu/~dabo/papers/aggreg.pdf
@license modified new BSD license
http://opensource.org/licenses/BSD-3-Clause
*/
#include <cmath>
#include <vector>
#include <iosfwd>
#include <set>
#ifndef MCLBN_FP_UNIT_SIZE
#define MCLBN_FP_UNIT_SIZE 4
#endif
#if MCLBN_FP_UNIT_SIZE == 4
#include <mcl/bn256.hpp>
namespace mcl {
using namespace mcl::bn256;
}
#elif MCLBN_FP_UNIT_SIZE == 6
#include <mcl/bn384.hpp>
namespace mcl {
using namespace mcl::bn384;
}
#elif MCLBN_FP_UNIT_SIZE == 8
#include <mcl/bn512.hpp>
namespace mcl {
using namespace mcl::bn512;
}
#else
#error "MCLBN_FP_UNIT_SIZE must be 4, 6, or 8"
#endif
namespace mcl { namespace aggs {
/*
AGGregate Signature Template class
*/
template<size_t dummyImpl = 0>
struct AGGST {
typedef typename G1::BaseFp Fp;
class SecretKey;
class PublicKey;
class Signature;
static G1 P_;
static G2 Q_;
static std::vector<Fp6> Qcoeff_;
public:
static void init(const mcl::CurveParam& cp = mcl::BN254)
{
initPairing(cp);
hashAndMapToG1(P_, "0");
hashAndMapToG2(Q_, "0");
precomputeG2(Qcoeff_, Q_);
}
class Signature : public fp::Serializable<Signature> {
G1 S_;
friend class SecretKey;
friend class PublicKey;
public:
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
S_.load(is, ioMode);
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
S_.save(os, ioMode);
}
friend std::istream& operator>>(std::istream& is, Signature& self)
{
self.load(is, fp::detectIoMode(G1::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const Signature& self)
{
self.save(os, fp::detectIoMode(G1::getIoMode(), os));
return os;
}
bool operator==(const Signature& rhs) const
{
return S_ == rhs.S_;
}
bool operator!=(const Signature& rhs) const { return !operator==(rhs); }
/*
aggregate sig[0..n) and set *this
*/
void aggregate(const Signature *sig, size_t n)
{
G1 S;
S.clear();
for (size_t i = 0; i < n; i++) {
S += sig[i].S_;
}
S_ = S;
}
void aggregate(const std::vector<Signature>& sig)
{
aggregate(sig.data(), sig.size());
}
/*
aggregate verification
*/
bool verify(const void *const *msgVec, const size_t *sizeVec, const PublicKey *pubVec, size_t n) const
{
if (n == 0) return false;
typedef std::set<Fp> FpSet;
FpSet msgSet;
typedef std::vector<G1> G1Vec;
G1Vec hv(n);
for (size_t i = 0; i < n; i++) {
Fp h;
h.setHashOf(msgVec[i], sizeVec[i]);
std::pair<typename FpSet::iterator, bool> ret = msgSet.insert(h);
if (!ret.second) throw cybozu::Exception("aggs::verify:same msg");
mapToG1(hv[i], h);
}
/*
e(aggSig, xQ) = prod_i e(hv[i], pub[i].Q)
<=> finalExp(e(-aggSig, xQ) * prod_i millerLoop(hv[i], pub[i].xQ)) == 1
*/
GT e1, e2;
precomputedMillerLoop(e1, -S_, Qcoeff_);
millerLoop(e2, hv[0], pubVec[0].xQ_);
for (size_t i = 1; i < n; i++) {
GT e;
millerLoop(e, hv[i], pubVec[i].xQ_);
e2 *= e;
}
e1 *= e2;
finalExp(e1, e1);
return e1.isOne();
}
bool verify(const std::vector<std::string>& msgVec, const std::vector<PublicKey>& pubVec) const
{
const size_t n = msgVec.size();
if (n != pubVec.size()) throw cybozu::Exception("aggs:Signature:verify:bad size") << msgVec.size() << pubVec.size();
if (n == 0) return false;
std::vector<const void*> mv(n);
std::vector<size_t> sv(n);
for (size_t i = 0; i < n; i++) {
mv[i] = msgVec[i].c_str();
sv[i] = msgVec[i].size();
}
return verify(&mv[0], &sv[0], &pubVec[0], n);
}
};
class PublicKey : public fp::Serializable<PublicKey> {
G2 xQ_;
friend class SecretKey;
friend class Signature;
public:
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
xQ_.load(is, ioMode);
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
xQ_.save(os, ioMode);
}
friend std::istream& operator>>(std::istream& is, PublicKey& self)
{
self.load(is, fp::detectIoMode(G2::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const PublicKey& self)
{
self.save(os, fp::detectIoMode(G2::getIoMode(), os));
return os;
}
bool operator==(const PublicKey& rhs) const
{
return xQ_ == rhs.xQ_;
}
bool operator!=(const PublicKey& rhs) const { return !operator==(rhs); }
bool verify(const Signature& sig, const void *m, size_t mSize) const
{
/*
H = hash(m)
e(S, Q) = e(H, xQ) where S = xH
<=> e(S, Q)e(-H, xQ) = 1
<=> finalExp(millerLoop(S, Q)e(-H, x)) = 1
*/
G1 H;
hashAndMapToG1(H, m, mSize);
G1::neg(H, H);
GT e1, e2;
precomputedMillerLoop(e1, sig.S_, Qcoeff_);
millerLoop(e2, H, xQ_);
e1 *= e2;
finalExp(e1, e1);
return e1.isOne();
}
bool verify(const Signature& sig, const std::string& m) const
{
return verify(sig, m.c_str(), m.size());
}
};
class SecretKey : public fp::Serializable<SecretKey> {
Fr x_;
friend class PublicKey;
friend class Signature;
public:
template<class InputStream>
void load(InputStream& is, int ioMode = IoSerialize)
{
x_.load(is, ioMode);
}
template<class OutputStream>
void save(OutputStream& os, int ioMode = IoSerialize) const
{
x_.save(os, ioMode);
}
friend std::istream& operator>>(std::istream& is, SecretKey& self)
{
self.load(is, fp::detectIoMode(Fr::getIoMode(), is));
return is;
}
friend std::ostream& operator<<(std::ostream& os, const SecretKey& self)
{
self.save(os, fp::detectIoMode(Fr::getIoMode(), os));
return os;
}
bool operator==(const SecretKey& rhs) const
{
return x_ == rhs.x_;
}
bool operator!=(const SecretKey& rhs) const { return !operator==(rhs); }
void init()
{
x_.setByCSPRNG();
}
void getPublicKey(PublicKey& pub) const
{
G2::mul(pub.xQ_, Q_, x_);
}
void sign(Signature& sig, const void *m, size_t mSize) const
{
hashAndMapToG1(sig.S_, m, mSize);
G1::mul(sig.S_, sig.S_, x_);
}
void sign(Signature& sig, const std::string& m) const
{
sign(sig, m.c_str(), m.size());
}
};
};
template<size_t dummyImpl> G1 AGGST<dummyImpl>::P_;
template<size_t dummyImpl> G2 AGGST<dummyImpl>::Q_;
template<size_t dummyImpl> std::vector<Fp6> AGGST<dummyImpl>::Qcoeff_;
typedef AGGST<> AGGS;
typedef AGGS::SecretKey SecretKey;
typedef AGGS::PublicKey PublicKey;
typedef AGGS::Signature Signature;
} } // mcl::aggs