aboutsummaryrefslogblamecommitdiffstats
path: root/include/bls/bls.hpp
blob: 741334555288cc2c412766ee370bdb902d6a87f5 (plain) (tree)
1
2
3
4
5
6
7
8
9







                                                   
                    
                    


                 
                   


               




                                         


                                                                 

  
  
                     


                                        
                      



                                           
 


                                                    
                                       
                                                         
                                       
  
                                                                                                
 
                                                                                         

                                                            
 















                                                                 
 
                 
  

                                                                              
                                       
  
                                          





                
 
                                            
                                            
                                            
                              
 
          
                    

                               
                               
       







                                                             
                                                                        




























                                                                                    
          
                                     
                                                   
          



                                                                      
                                                       



                                                                

  



                      
                           
       



                                                                    
                                                                               
























                                                                                    
          
                                                       
          




                                                                                  
          
                                                                   
                                                   
          



                                                                      
                                                       



                                                                
                          




                                                                            
                                                
                             











                                                                        
          

                                            
          
                                          
          
                                                                             
          








                                                                              


                                                    



                                                       


                                               

                                                                    
                                                                                                    

                                                                   
          
                              

                                       




                                              









                                                                                        

  
  

                       
                 
                           
                               
                               
       



                                                                    
                                                                               












                                                                               





                                                           










                                                           


                                                                                 
                                                                                 

                                                                         



                                                           


                                                                                    
                                                                                    

                                                                           
         
          
                                          
          



                                                       
          
                                               
          

                                                                    
                                                                                                    

                                                                   
          
                              
          



                                                    

                                              









                                                                                        

  
  
                          
  
                 
                           
                               
       



                                                                    
                                                                               












                                                                               





                                                           










                                                           


                                                                                 
                                                                                 

                                                                          



                                                           


                                                                                    
                                                                                    

                                                                           
         



                                                                           

                                                                     








                                                                               
         

                                                                                                                 
                                                                                                     
         
          
                                         
          





                                               
          
                                         
          

                                                                    
                                                                                                    

                                                                   
          
                             
          



                                                    

                                              




                                                                                        

  


                                                               







                                                                          
 



                                                         




                                                                                 
 
                                                                                             









                                                   


                                 
                                                                    






                                         
 
                                                                                                          
                                                                                                          
                                                                                                          
 
       
#pragma once
/**
    @file
    @brief BLS threshold signature on BN curve
    @author MITSUNARI Shigeo(@herumi)
    @license modified new BSD license
    http://opensource.org/licenses/BSD-3-Clause
*/
#include <bls/bls.h>
#include <stdexcept>
#include <vector>
#include <string>
#include <iosfwd>
#include <stdint.h>

namespace bls {

// same value with IoMode of mcl/op.hpp
enum {
    IoBin = 2, // binary number
    IoDec = 10, // decimal number
    IoHex = 16, // hexadecimal number
    IoPrefix = 128, // append '0b'(bin) or '0x'(hex)
    IoSerialize = 512,
    IoFixedByteSeq = IoSerialize // fixed byte representation
};

/*
    BLS signature
    e : G2 x G1 -> Fp12
    Q in G2 ; fixed global parameter
    H : {str} -> G1
    s : secret key
    sQ ; public key
    s H(m) ; signature of m
    verify ; e(sQ, H(m)) = e(Q, s H(m))
*/

/*
    initialize this library
    call this once before using the other method
    @param curve [in] type of curve
    @param compiledTimevar [in] use the default value
    @note init() is not thread safe
*/
inline void init(int curve = mclBn_CurveFp254BNb, int compiledTimeVar = MCLBN_COMPILED_TIME_VAR)
{
    if (blsInit(curve, compiledTimeVar) != 0) throw std::invalid_argument("blsInit");
}
inline size_t getOpUnitSize() { return blsGetOpUnitSize(); }

inline void getCurveOrder(std::string& str)
{
    str.resize(1024);
    mclSize n = blsGetCurveOrder(&str[0], str.size());
    if (n == 0) throw std::runtime_error("blsGetCurveOrder");
    str.resize(n);
}
inline void getFieldOrder(std::string& str)
{
    str.resize(1024);
    mclSize n = blsGetFieldOrder(&str[0], str.size());
    if (n == 0) throw std::runtime_error("blsGetFieldOrder");
    str.resize(n);
}
inline int getG1ByteSize() { return blsGetG1ByteSize(); }
inline int getFrByteSize() { return blsGetFrByteSize(); }

namespace local {
/*
    the value of secretKey and Id must be less than
    r = 0x2523648240000001ba344d8000000007ff9f800000000010a10000000000000d
    sizeof(uint64_t) * keySize byte
*/
const size_t keySize = MCLBN_FP_UNIT_SIZE;
}

class SecretKey;
class PublicKey;
class Signature;
class Id;

typedef std::vector<SecretKey> SecretKeyVec;
typedef std::vector<PublicKey> PublicKeyVec;
typedef std::vector<Signature> SignatureVec;
typedef std::vector<Id> IdVec;

class Id {
    blsId self_;
    friend class PublicKey;
    friend class SecretKey;
    friend class Signature;
public:
    Id(unsigned int id = 0)
    {
        blsIdSetInt(&self_, id);
    }
    bool operator==(const Id& rhs) const
    {
        return blsIdIsEqual(&self_, &rhs.self_) == 1;
    }
    bool operator!=(const Id& rhs) const { return !(*this == rhs); }
    friend std::ostream& operator<<(std::ostream& os, const Id& id)
    {
        std::string str;
        id.getStr(str, 16|IoPrefix);
        return os << str;
    }
    friend std::istream& operator>>(std::istream& is, Id& id)
    {
        std::string str;
        is >> str;
        id.setStr(str, 16);
        return is;
    }
    void getStr(std::string& str, int ioMode = 0) const
    {
        str.resize(1024);
        size_t n = mclBnFr_getStr(&str[0], str.size(), &self_.v, ioMode);
        if (n == 0) throw std::runtime_error("mclBnFr_getStr");
        str.resize(n);
    }
    void setStr(const std::string& str, int ioMode = 0)
    {
        int ret = mclBnFr_setStr(&self_.v, str.c_str(), str.size(), ioMode);
        if (ret != 0) throw std::runtime_error("mclBnFr_setStr");
    }
    bool isZero() const
    {
        return mclBnFr_isZero(&self_.v) == 1;
    }
    /*
        set p[0, .., keySize)
        @note the value must be less than r
    */
    void set(const uint64_t *p)
    {
        setLittleEndian(p, local::keySize * sizeof(uint64_t));
    }
    // bufSize is truncted/zero extended to keySize
    void setLittleEndian(const void *buf, size_t bufSize)
    {
        mclBnFr_setLittleEndian(&self_.v, buf, bufSize);
    }
};

/*
    s ; secret key
*/
class SecretKey {
    blsSecretKey self_;
public:
    bool operator==(const SecretKey& rhs) const
    {
        return blsSecretKeyIsEqual(&self_, &rhs.self_) == 1;
    }
    bool operator!=(const SecretKey& rhs) const { return !(*this == rhs); }
    friend std::ostream& operator<<(std::ostream& os, const SecretKey& sec)
    {
        std::string str;
        sec.getStr(str, 16|IoPrefix);
        return os << str;
    }
    friend std::istream& operator>>(std::istream& is, SecretKey& sec)
    {
        std::string str;
        is >> str;
        sec.setStr(str);
        return is;
    }
    void getStr(std::string& str, int ioMode = 0) const
    {
        str.resize(1024);
        size_t n = mclBnFr_getStr(&str[0], str.size(), &self_.v, ioMode);
        if (n == 0) throw std::runtime_error("mclBnFr_getStr");
        str.resize(n);
    }
    void setStr(const std::string& str, int ioMode = 0)
    {
        int ret = mclBnFr_setStr(&self_.v, str.c_str(), str.size(), ioMode);
        if (ret != 0) throw std::runtime_error("mclBnFr_setStr");
    }
    /*
        initialize secretKey with random number
    */
    void init()
    {
        int ret = blsSecretKeySetByCSPRNG(&self_);
        if (ret != 0) throw std::runtime_error("blsSecretKeySetByCSPRNG");
    }
    /*
        set secretKey with p[0, .., keySize) and set id = 0
        @note the value must be less than r
    */
    void set(const uint64_t *p)
    {
        setLittleEndian(p, local::keySize * sizeof(uint64_t));
    }
    // bufSize is truncted/zero extended to keySize
    void setLittleEndian(const void *buf, size_t bufSize)
    {
        mclBnFr_setLittleEndian(&self_.v, buf, bufSize);
    }
    // set hash of buf
    void setHashOf(const void *buf, size_t bufSize)
    {
        int ret = mclBnFr_setHashOf(&self_.v, buf, bufSize);
        if (ret != 0) throw std::runtime_error("mclBnFr_setHashOf");
    }
    void getPublicKey(PublicKey& pub) const;
    // constant time sign
    // sign hash(m)
    void sign(Signature& sig, const void *m, size_t size) const;
    void sign(Signature& sig, const std::string& m) const
    {
        sign(sig, m.c_str(), m.size());
    }
    // sign hashed value
    void signHash(Signature& sig, const void *h, size_t size) const;
    void signHash(Signature& sig, const std::string& h) const
    {
        signHash(sig, h.c_str(), h.size());
    }
    /*
        make Pop(Proof of Possesion)
        pop = prv.sign(pub)
    */
    void getPop(Signature& pop) const;
    /*
        make [s_0, ..., s_{k-1}] to prepare k-out-of-n secret sharing
    */
    void getMasterSecretKey(SecretKeyVec& msk, size_t k) const
    {
        if (k <= 1) throw std::invalid_argument("getMasterSecretKey");
        msk.resize(k);
        msk[0] = *this;
        for (size_t i = 1; i < k; i++) {
            msk[i].init();
        }
    }
    /*
        set a secret key for id > 0 from msk
    */
    void set(const SecretKeyVec& msk, const Id& id)
    {
        set(msk.data(), msk.size(), id);
    }
    /*
        recover secretKey from k secVec
    */
    void recover(const SecretKeyVec& secVec, const IdVec& idVec)
    {
        if (secVec.size() != idVec.size()) throw std::invalid_argument("SecretKey:recover");
        recover(secVec.data(), idVec.data(), idVec.size());
    }
    /*
        add secret key
    */
    void add(const SecretKey& rhs);

    // the following methods are for C api
    /*
        the size of msk must be k
    */
    void set(const SecretKey *msk, size_t k, const Id& id)
    {
        int ret = blsSecretKeyShare(&self_, &msk->self_, k, &id.self_);
        if (ret != 0) throw std::runtime_error("blsSecretKeyShare");
    }
    void recover(const SecretKey *secVec, const Id *idVec, size_t n)
    {
        int ret = blsSecretKeyRecover(&self_, &secVec->self_, &idVec->self_, n);
        if (ret != 0) throw std::runtime_error("blsSecretKeyRecover:same id");
    }
};

/*
    sQ ; public key
*/
class PublicKey {
    blsPublicKey self_;
    friend class SecretKey;
    friend class Signature;
public:
    bool operator==(const PublicKey& rhs) const
    {
        return blsPublicKeyIsEqual(&self_, &rhs.self_) == 1;
    }
    bool operator!=(const PublicKey& rhs) const { return !(*this == rhs); }
    friend std::ostream& operator<<(std::ostream& os, const PublicKey& pub)
    {
        std::string str;
        pub.getStr(str, 16|IoPrefix);
        return os << str;
    }
    friend std::istream& operator>>(std::istream& is, PublicKey& pub)
    {
        std::string str;
        is >> str;
        if (str != "0") {
            // 1 <x.a> <x.b> <y.a> <y.b>
            std::string t;
#ifdef BLS_SWAP_G
            const int elemNum = 2;
#else
            const int elemNum = 4;
#endif
            for (int i = 0; i < elemNum; i++) {
                is >> t;
                str += ' ';
                str += t;
            }
        }
        pub.setStr(str, 16);
        return is;
    }
    void getStr(std::string& str, int ioMode = 0) const
    {
        str.resize(1024);
#ifdef BLS_SWAP_G
        size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode);
#else
        size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode);
#endif
        if (n == 0) throw std::runtime_error("PublicKey:getStr");
        str.resize(n);
    }
    void setStr(const std::string& str, int ioMode = 0)
    {
#ifdef BLS_SWAP_G
        int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode);
#else
        int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode);
#endif
        if (ret != 0) throw std::runtime_error("PublicKey:setStr");
    }
    /*
        set public for id from mpk
    */
    void set(const PublicKeyVec& mpk, const Id& id)
    {
        set(mpk.data(), mpk.size(), id);
    }
    /*
        recover publicKey from k pubVec
    */
    void recover(const PublicKeyVec& pubVec, const IdVec& idVec)
    {
        if (pubVec.size() != idVec.size()) throw std::invalid_argument("PublicKey:recover");
        recover(pubVec.data(), idVec.data(), idVec.size());
    }
    /*
        add public key
    */
    void add(const PublicKey& rhs)
    {
        blsPublicKeyAdd(&self_, &rhs.self_);
    }

    // the following methods are for C api
    void set(const PublicKey *mpk, size_t k, const Id& id)
    {
        int ret = blsPublicKeyShare(&self_, &mpk->self_, k, &id.self_);
        if (ret != 0) throw std::runtime_error("blsPublicKeyShare");
    }
    void recover(const PublicKey *pubVec, const Id *idVec, size_t n)
    {
        int ret = blsPublicKeyRecover(&self_, &pubVec->self_, &idVec->self_, n);
        if (ret != 0) throw std::runtime_error("blsPublicKeyRecover");
    }
};

/*
    s H(m) ; signature
*/
class Signature {
    blsSignature self_;
    friend class SecretKey;
public:
    bool operator==(const Signature& rhs) const
    {
        return blsSignatureIsEqual(&self_, &rhs.self_) == 1;
    }
    bool operator!=(const Signature& rhs) const { return !(*this == rhs); }
    friend std::ostream& operator<<(std::ostream& os, const Signature& sig)
    {
        std::string str;
        sig.getStr(str, 16|IoPrefix);
        return os << str;
    }
    friend std::istream& operator>>(std::istream& is, Signature& sig)
    {
        std::string str;
        is >> str;
        if (str != "0") {
            // 1 <x> <y>
            std::string t;
#ifdef BLS_SWAP_G
            const int elemNum = 4;
#else
            const int elemNum = 2;
#endif
            for (int i = 0; i < elemNum; i++) {
                is >> t;
                str += ' ';
                str += t;
            }
        }
        sig.setStr(str, 16);
        return is;
    }
    void getStr(std::string& str, int ioMode = 0) const
    {
        str.resize(1024);
#ifdef BLS_SWAP_G
        size_t n = mclBnG2_getStr(&str[0], str.size(), &self_.v, ioMode);
#else
        size_t n = mclBnG1_getStr(&str[0], str.size(), &self_.v, ioMode);
#endif
        if (n == 0) throw std::runtime_error("Signature:tgetStr");
        str.resize(n);
    }
    void setStr(const std::string& str, int ioMode = 0)
    {
#ifdef BLS_SWAP_G
        int ret = mclBnG2_setStr(&self_.v, str.c_str(), str.size(), ioMode);
#else
        int ret = mclBnG1_setStr(&self_.v, str.c_str(), str.size(), ioMode);
#endif
        if (ret != 0) throw std::runtime_error("Signature:setStr");
    }
    bool verify(const PublicKey& pub, const void *m, size_t size) const
    {
        return blsVerify(&self_, &pub.self_, m, size) == 1;
    }
    bool verify(const PublicKey& pub, const std::string& m) const
    {
        return verify(pub, m.c_str(), m.size());
    }
    bool verifyHash(const PublicKey& pub, const void *h, size_t size) const
    {
        return blsVerifyHash(&self_, &pub.self_, h, size) == 1;
    }
    bool verifyHash(const PublicKey& pub, const std::string& h) const
    {
        return verifyHash(pub, h.c_str(), h.size());
    }
    bool verifyAggregatedHashes(const PublicKey *pubVec, const void *hVec, size_t sizeofHash, size_t n) const
    {
        return blsVerifyAggregatedHashes(&self_, &pubVec[0].self_, hVec, sizeofHash, n) == 1;
    }
    /*
        verify self(pop) with pub
    */
    bool verify(const PublicKey& pub) const
    {
        std::string str;
        pub.getStr(str);
        return verify(pub, str);
    }
    /*
        recover sig from k sigVec
    */
    void recover(const SignatureVec& sigVec, const IdVec& idVec)
    {
        if (sigVec.size() != idVec.size()) throw std::invalid_argument("Signature:recover");
        recover(sigVec.data(), idVec.data(), idVec.size());
    }
    /*
        add signature
    */
    void add(const Signature& rhs)
    {
        blsSignatureAdd(&self_, &rhs.self_);
    }

    // the following methods are for C api
    void recover(const Signature* sigVec, const Id *idVec, size_t n)
    {
        int ret = blsSignatureRecover(&self_, &sigVec->self_, &idVec->self_, n);
        if (ret != 0) throw std::runtime_error("blsSignatureRecover:same id");
    }
};

/*
    make master public key [s_0 Q, ..., s_{k-1} Q] from msk
*/
inline void getMasterPublicKey(PublicKeyVec& mpk, const SecretKeyVec& msk)
{
    const size_t n = msk.size();
    mpk.resize(n);
    for (size_t i = 0; i < n; i++) {
        msk[i].getPublicKey(mpk[i]);
    }
}

inline void SecretKey::getPublicKey(PublicKey& pub) const
{
    blsGetPublicKey(&pub.self_, &self_);
}
inline void SecretKey::sign(Signature& sig, const void *m, size_t size) const
{
    blsSign(&sig.self_, &self_, m, size);
}
inline void SecretKey::signHash(Signature& sig, const void *h, size_t size) const
{
    if (blsSignHash(&sig.self_, &self_, h, size) != 0) throw std::runtime_error("bad h");
}
inline void SecretKey::getPop(Signature& pop) const
{
    PublicKey pub;
    getPublicKey(pub);
    std::string m;
    pub.getStr(m);
    sign(pop, m);
}

/*
    make pop from msk and mpk
*/
inline void getPopVec(SignatureVec& popVec, const SecretKeyVec& msk)
{
    const size_t n = msk.size();
    popVec.resize(n);
    for (size_t i = 0; i < n; i++) {
        msk[i].getPop(popVec[i]);
    }
}

inline Signature operator+(const Signature& a, const Signature& b) { Signature r(a); r.add(b); return r; }
inline PublicKey operator+(const PublicKey& a, const PublicKey& b) { PublicKey r(a); r.add(b); return r; }
inline SecretKey operator+(const SecretKey& a, const SecretKey& b) { SecretKey r(a); r.add(b); return r; }

} //bls