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 */ 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))) } }