aboutsummaryrefslogblamecommitdiffstats
path: root/ffi/go/bls/bls.go
blob: e9a6be33edabea0922fb9459313b9d21ca15bcc4 (plain) (tree)
1
2
3
4
5
6
7
8
           

  
                                        
                                                     
                                        
                                                     
                                                                   





                                                                            

                                                                   
                    


            
               
           
                      
 
          

                                                             
                            
                                                                 
                     
                                                             
         
                  
 
 

                
            

 


                                         
                                             

 

                                        
                               

 

                                                 
                                        

 
                  
                                     
                                 

 
                  
                                     
                                 

 
                  
                                            
                                    

 
                  
                                            
                                    

 

                                     


                                    
                                   

 






















                                                          
               
                       
            

 
                
                                                        
                 
                                                     

 

                                                
                                

 

                                                         
                                         

 









                                                         
                  
                                             
                                  

 
                  
                                             
                                  

 
                  
                                                    
                                     

 
                  
                                                    
                                     

 

                                                    


                                     
                                    

 


                                     

 
         
                                           
                                     

 
                        


                                                                   
                                
                                    



                  






















                                                                  
                        
                                                            
                     
                                  
                                
                                               



                  
         
                                                          

                                                                                  

 
             
                                                                     

                                                                                                                   

 
            
                                             
                        
                                                        


                   
               
                       
            

 
                
                                                        
                 
                                                     

 

                                          
                                

 

                                                     
                                     

 









                                                         
                  
                                             
                                  

 
                  
                                                    
                                     

 

                                                    


                                     
                                    

 
         
                                           
                                     
 

         
                                                          

                                                                                  

 
             
                                                                     

                                                                                                                   
 
 






















                                                              
           
                  
            

 
                
                                                    
                 
                                                      

 

                                      
                                 

 

                                                 
                                      

 









                                                     
                  
                                         
                                   

 
                  
                                                
                                      

 

                                           


                                      
                                     

 
                  
                                                       
                            
                                                             


                  
                                
                                                   
                        
                        
                 
                                                                                                   


                   
         
                                  
                                                              
 

             
                                                             

                                                                                                                     
 
 
            
                                                         
                        
                 
                                                                                                                 

 
               
                                                  


                                    
                                                                       
 
 






















                                                          




                                                                                













                                                           


                                                                                      

                                                                                        














                                                                                                                


                                    
                 

                                                                                                                       
















                                                                                 


                                          

                                                                                                                                                  


   
                          









                                                                
                                            






                                        
                                        







                                                                                        
package bls

/*
#cgo bn256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=4
#cgo bn256 LDFLAGS:${SRCDIR}/../../../lib/libbls256.a
#cgo bn384 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
#cgo bn384 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a
#cgo bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6 -DMCLBN_FR_UNIT_SIZE=4
#cgo bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384_256.a
#cgo !bn256,!bn384,!bn384_256 CFLAGS:-DMCLBN_FP_UNIT_SIZE=6
#cgo !bn256,!bn384,!bn384_256 LDFLAGS:${SRCDIR}/../../../lib/libbls384.a
#cgo CFLAGS:-I${SRCDIR}/../../../include -I${SRCDIR}/../../../../mcl/include
#cgo LDFLAGS:${SRCDIR}/../../../../mcl/lib/libmcl.a -lgmpxx -lgmp
#cgo pkg-config: libcrypto
typedef unsigned int (*ReadRandFunc)(void *, void *, unsigned int);
int wrapReadRandCgo(void *self, void *buf, unsigned int n);
#include <bls/bls.h>
*/
import "C"
import "fmt"
import "unsafe"
import "io"
import "encoding/json"

// Init --
// call this function before calling all the other operations
// this function is not thread safe
func Init(curve int) error {
    err := C.blsInit(C.int(curve), C.MCLBN_COMPILED_TIME_VAR)
    if err != 0 {
        return fmt.Errorf("ERR Init curve=%d", curve)
    }
    return nil
}

// ID --
type ID struct {
    v Fr
}

// getPointer --
func (id *ID) getPointer() (p *C.blsId) {
    // #nosec
    return (*C.blsId)(unsafe.Pointer(id))
}

// GetLittleEndian --
func (id *ID) GetLittleEndian() []byte {
    return id.v.Serialize()
}

// SetLittleEndian --
func (id *ID) SetLittleEndian(buf []byte) error {
    return id.v.SetLittleEndian(buf)
}

// GetHexString --
func (id *ID) GetHexString() string {
    return id.v.GetString(16)
}

// GetDecString --
func (id *ID) GetDecString() string {
    return id.v.GetString(10)
}

// SetHexString --
func (id *ID) SetHexString(s string) error {
    return id.v.SetString(s, 16)
}

// SetDecString --
func (id *ID) SetDecString(s string) error {
    return id.v.SetString(s, 10)
}

// IsEqual --
func (id *ID) IsEqual(rhs *ID) bool {
    if id == nil || rhs == nil {
        return false
    }
    return id.v.IsEqual(&rhs.v)
}

// MarshalJSON implements json.Marshaller.
func (id *ID) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        ID []byte `json:"id"`
    }{
        id.GetLittleEndian(),
    })
}

// UnmarshalJSON implements json.Unmarshaller.
func (id *ID) UnmarshalJSON(data []byte) error {
    aux := &struct {
        ID []byte `json:"id"`
    }{}
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    if err := id.SetLittleEndian(aux.ID); err != nil {
        return err
    }
    return nil
}

// SecretKey --
type SecretKey struct {
    v Fr
}

// getPointer --
func (sec *SecretKey) getPointer() (p *C.blsSecretKey) {
    // #nosec
    return (*C.blsSecretKey)(unsafe.Pointer(sec))
}

// GetLittleEndian --
func (sec *SecretKey) GetLittleEndian() []byte {
    return sec.v.Serialize()
}

// SetLittleEndian --
func (sec *SecretKey) SetLittleEndian(buf []byte) error {
    return sec.v.SetLittleEndian(buf)
}

// SerializeToHexStr --
func (sec *SecretKey) SerializeToHexStr() string {
    return sec.v.GetString(IoSerializeHexStr)
}

// DeserializeHexStr --
func (sec *SecretKey) DeserializeHexStr(s string) error {
    return sec.v.SetString(s, IoSerializeHexStr)
}

// GetHexString --
func (sec *SecretKey) GetHexString() string {
    return sec.v.GetString(16)
}

// GetDecString --
func (sec *SecretKey) GetDecString() string {
    return sec.v.GetString(10)
}

// SetHexString --
func (sec *SecretKey) SetHexString(s string) error {
    return sec.v.SetString(s, 16)
}

// SetDecString --
func (sec *SecretKey) SetDecString(s string) error {
    return sec.v.SetString(s, 10)
}

// IsEqual --
func (sec *SecretKey) IsEqual(rhs *SecretKey) bool {
    if sec == nil || rhs == nil {
        return false
    }
    return sec.v.IsEqual(&rhs.v)
}

// SetByCSPRNG --
func (sec *SecretKey) SetByCSPRNG() {
    sec.v.SetByCSPRNG()
}

// Add --
func (sec *SecretKey) Add(rhs *SecretKey) {
    FrAdd(&sec.v, &sec.v, &rhs.v)
}

// GetMasterSecretKey --
func (sec *SecretKey) GetMasterSecretKey(k int) (msk []SecretKey) {
    msk = make([]SecretKey, k)
    msk[0] = *sec
    for i := 1; i < k; i++ {
        msk[i].SetByCSPRNG()
    }
    return msk
}

// MarshalJSON implements json.Marshaller.
func (sec *SecretKey) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        SecretKey []byte `json:"secret_key"`
    }{
        sec.GetLittleEndian(),
    })
}

// UnmarshalJSON implements json.Unmarshaller.
func (sec *SecretKey) UnmarshalJSON(data []byte) error {
    aux := &struct {
        SecretKey []byte `json:"secret_key"`
    }{}
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    if err := sec.SetLittleEndian(aux.SecretKey); err != nil {
        return err
    }
    return nil
}

// GetMasterPublicKey --
func GetMasterPublicKey(msk []SecretKey) (mpk []PublicKey) {
    n := len(msk)
    mpk = make([]PublicKey, n)
    for i := 0; i < n; i++ {
        mpk[i] = *msk[i].GetPublicKey()
    }
    return mpk
}

// Set --
func (sec *SecretKey) Set(msk []SecretKey, id *ID) error {
    // #nosec
    return FrEvaluatePolynomial(&sec.v, *(*[]Fr)(unsafe.Pointer(&msk)), &id.v)
}

// Recover --
func (sec *SecretKey) Recover(secVec []SecretKey, idVec []ID) error {
    // #nosec
    return FrLagrangeInterpolation(&sec.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]Fr)(unsafe.Pointer(&secVec)))
}

// GetPop --
func (sec *SecretKey) GetPop() (sign *Sign) {
    sign = new(Sign)
    C.blsGetPop(sign.getPointer(), sec.getPointer())
    return sign
}

// PublicKey --
type PublicKey struct {
    v G2
}

// getPointer --
func (pub *PublicKey) getPointer() (p *C.blsPublicKey) {
    // #nosec
    return (*C.blsPublicKey)(unsafe.Pointer(pub))
}

// Serialize --
func (pub *PublicKey) Serialize() []byte {
    return pub.v.Serialize()
}

// Deserialize --
func (pub *PublicKey) Deserialize(buf []byte) error {
    return pub.v.Deserialize(buf)
}

// SerializeToHexStr --
func (pub *PublicKey) SerializeToHexStr() string {
    return pub.v.GetString(IoSerializeHexStr)
}

// DeserializeHexStr --
func (pub *PublicKey) DeserializeHexStr(s string) error {
    return pub.v.SetString(s, IoSerializeHexStr)
}

// GetHexString --
func (pub *PublicKey) GetHexString() string {
    return pub.v.GetString(16)
}

// SetHexString --
func (pub *PublicKey) SetHexString(s string) error {
    return pub.v.SetString(s, 16)
}

// IsEqual --
func (pub *PublicKey) IsEqual(rhs *PublicKey) bool {
    if pub == nil || rhs == nil {
        return false
    }
    return pub.v.IsEqual(&rhs.v)
}

// Add --
func (pub *PublicKey) Add(rhs *PublicKey) {
    G2Add(&pub.v, &pub.v, &rhs.v)
}

// Set --
func (pub *PublicKey) Set(mpk []PublicKey, id *ID) error {
    // #nosec
    return G2EvaluatePolynomial(&pub.v, *(*[]G2)(unsafe.Pointer(&mpk)), &id.v)
}

// Recover --
func (pub *PublicKey) Recover(pubVec []PublicKey, idVec []ID) error {
    // #nosec
    return G2LagrangeInterpolation(&pub.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]G2)(unsafe.Pointer(&pubVec)))
}

// MarshalJSON implements json.Marshaller.
func (pub *PublicKey) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        PublicKey []byte `json:"public_key"`
    }{
        pub.Serialize(),
    })
}

// UnmarshalJSON implements json.Unmarshaller.
func (pub *PublicKey) UnmarshalJSON(data []byte) error {
    aux := &struct {
        PublicKey []byte `json:"public_key"`
    }{}
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    if err := pub.Deserialize(aux.PublicKey); err != nil {
        return err
    }
    return nil
}

// Sign  --
type Sign struct {
    v G1
}

// getPointer --
func (sign *Sign) getPointer() (p *C.blsSignature) {
    // #nosec
    return (*C.blsSignature)(unsafe.Pointer(sign))
}

// Serialize --
func (sign *Sign) Serialize() []byte {
    return sign.v.Serialize()
}

// Deserialize --
func (sign *Sign) Deserialize(buf []byte) error {
    return sign.v.Deserialize(buf)
}

// SerializeToHexStr --
func (sign *Sign) SerializeToHexStr() string {
    return sign.v.GetString(IoSerializeHexStr)
}

// DeserializeHexStr --
func (sign *Sign) DeserializeHexStr(s string) error {
    return sign.v.SetString(s, IoSerializeHexStr)
}

// GetHexString --
func (sign *Sign) GetHexString() string {
    return sign.v.GetString(16)
}

// SetHexString --
func (sign *Sign) SetHexString(s string) error {
    return sign.v.SetString(s, 16)
}

// IsEqual --
func (sign *Sign) IsEqual(rhs *Sign) bool {
    if sign == nil || rhs == nil {
        return false
    }
    return sign.v.IsEqual(&rhs.v)
}

// GetPublicKey --
func (sec *SecretKey) GetPublicKey() (pub *PublicKey) {
    pub = new(PublicKey)
    C.blsGetPublicKey(pub.getPointer(), sec.getPointer())
    return pub
}

// Sign -- Constant Time version
func (sec *SecretKey) Sign(m string) (sign *Sign) {
    sign = new(Sign)
    buf := []byte(m)
    // #nosec
    C.blsSign(sign.getPointer(), sec.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf)))
    return sign
}

// Add --
func (sign *Sign) Add(rhs *Sign) {
    C.blsSignatureAdd(sign.getPointer(), rhs.getPointer())
}

// Recover --
func (sign *Sign) Recover(signVec []Sign, idVec []ID) error {
    // #nosec
    return G1LagrangeInterpolation(&sign.v, *(*[]Fr)(unsafe.Pointer(&idVec)), *(*[]G1)(unsafe.Pointer(&signVec)))
}

// Verify --
func (sign *Sign) Verify(pub *PublicKey, m string) bool {
    buf := []byte(m)
    // #nosec
    return C.blsVerify(sign.getPointer(), pub.getPointer(), unsafe.Pointer(&buf[0]), C.size_t(len(buf))) == 1
}

// VerifyPop --
func (sign *Sign) VerifyPop(pub *PublicKey) bool {
    if pub.getPointer() == nil {
        return false
    }
    return C.blsVerifyPop(sign.getPointer(), pub.getPointer()) == 1
}

// MarshalJSON implements json.Marshaller.
func (sign *Sign) MarshalJSON() ([]byte, error) {
    return json.Marshal(&struct {
        Sign []byte `json:"sign"`
    }{
        sign.Serialize(),
    })
}

// UnmarshalJSON implements json.Unmarshaller.
func (sign *Sign) UnmarshalJSON(data []byte) error {
    aux := &struct {
        Sign []byte `json:"sign"`
    }{}
    if err := json.Unmarshal(data, &aux); err != nil {
        return err
    }
    if err := sign.Deserialize(aux.Sign); err != nil {
        return err
    }
    return nil
}

// DHKeyExchange --
func DHKeyExchange(sec *SecretKey, pub *PublicKey) (out PublicKey) {
    C.blsDHKeyExchange(out.getPointer(), sec.getPointer(), pub.getPointer())
    return out
}

// HashAndMapToSignature --
func HashAndMapToSignature(buf []byte) *Sign {
    sig := new(Sign)
    err := sig.v.HashAndMapTo(buf)
    if err == nil {
        return sig
    } else {
        return nil
    }
}

// VerifyPairing --
func VerifyPairing(X *Sign, Y *Sign, pub *PublicKey) bool {
    if X.getPointer() == nil || Y.getPointer() == nil || pub.getPointer() == nil {
        return false
    }
    return C.blsVerifyPairing(X.getPointer(), Y.getPointer(), pub.getPointer()) == 1
}

// SignHash --
func (sec *SecretKey) SignHash(hash []byte) (sign *Sign) {
    sign = new(Sign)
    // #nosec
    err := C.blsSignHash(sign.getPointer(), sec.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash)))
    if err == 0 {
        return sign
    } else {
        return nil
    }
}

// VerifyHash --
func (sign *Sign) VerifyHash(pub *PublicKey, hash []byte) bool {
    if pub.getPointer() == nil {
        return false
    }
    // #nosec
    return C.blsVerifyHash(sign.getPointer(), pub.getPointer(), unsafe.Pointer(&hash[0]), C.size_t(len(hash))) == 1
}

func Min(x, y int) int {
    if x < y {
        return x
    }
    return y
}

// VerifyAggregateHashes --
func (sign *Sign) VerifyAggregateHashes(pubVec []PublicKey, hash [][]byte) bool {
    hashByte := GetOpUnitSize() * 8
    n := len(hash)
    h := make([]byte, n*hashByte)
    for i := 0; i < n; i++ {
        hn := len(hash[i])
        copy(h[i*hashByte:(i+1)*hashByte], hash[i][0:Min(hn, hashByte)])
    }
    if pubVec[0].getPointer() == nil {
        return false
    }
    return C.blsVerifyAggregatedHashes(sign.getPointer(), pubVec[0].getPointer(), unsafe.Pointer(&h[0]), C.size_t(hashByte), C.size_t(n)) == 1
}

///

var s_randReader io.Reader

func createSlice(buf *C.char, n C.uint) []byte {
    size := int(n)
    return (*[1 << 30]byte)(unsafe.Pointer(buf))[:size:size]
}

// this function can't be put in callback.go
//export wrapReadRandGo
func wrapReadRandGo(buf *C.char, n C.uint) C.uint {
    slice := createSlice(buf, n)
    ret, err := s_randReader.Read(slice)
    if ret == int(n) && err == nil {
        return n
    }
    return 0
}

// SetRandFunc --
func SetRandFunc(randReader io.Reader) {
    s_randReader = randReader
    if randReader != nil {
        C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(C.wrapReadRandCgo)))
    } else {
        // use default random generator
        C.blsSetRandFunc(nil, C.ReadRandFunc(unsafe.Pointer(nil)))
    }
}