github.com/cloudflare/circl@v1.5.0/sign/bls/bls.go (about) 1 // Package bls provides BLS signatures using the BLS12-381 pairing curve. 2 // 3 // This packages implements the IETF/CFRG draft for BLS signatures [1]. 4 // Currently only the BASIC mode (one of the three modes specified 5 // in the draft) is supported. The pairing function is instantiated 6 // with the BLS12-381 curve. 7 // 8 // # Groups 9 // 10 // The BLS signature scheme can be instantiated with keys in one of the 11 // two groups: G1 or G2, which correspond to the input domain of a pairing 12 // function e(G1,G2) -> Gt. 13 // Thus, choosing keys in G1 implies that signature values are internally 14 // represented in G2; or viceversa. Use the types KeyG1SigG2 or KeyG2SigG1 15 // to express this preference. 16 // 17 // # Serialization 18 // 19 // The serialization of elements in G1 and G2 follows the recommendation 20 // given in [2], in order to be compatible with other implementations of 21 // BLS12-381 curve. 22 // 23 // # References 24 // 25 // [1] https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05 26 // 27 // [2] https://github.com/zkcrypto/bls12_381/blob/0.7.0/src/notes/serialization.rs 28 package bls 29 30 import ( 31 "crypto" 32 "crypto/sha256" 33 "encoding/binary" 34 "errors" 35 "io" 36 37 GG "github.com/cloudflare/circl/ecc/bls12381" 38 "golang.org/x/crypto/hkdf" 39 ) 40 41 var ( 42 ErrInvalid = errors.New("bls: invalid BLS instance") 43 ErrInvalidKey = errors.New("bls: invalid key") 44 ErrKeyGen = errors.New("bls: too many unsuccessful key generation tries") 45 ErrShortIKM = errors.New("bls: IKM material shorter than 32 bytes") 46 ErrAggregate = errors.New("bls: error while aggregating signatures") 47 ) 48 49 const ( 50 dstG1 = "BLS_SIG_BLS12381G1_XMD:SHA-256_SSWU_RO_NUL_" 51 dstG2 = "BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_" 52 ) 53 54 type Signature = []byte 55 56 type ( 57 // G1 group used for keys defined in pairing group G1. 58 G1 struct{ g GG.G1 } 59 // G2 group used for keys defined in pairing group G2. 60 G2 struct{ g GG.G2 } 61 // KeyG1SigG2 sets the keys to G1 and signatures to G2. 62 KeyG1SigG2 = G1 63 // KeyG2SigG1 sets the keys to G2 and signatures to G1. 64 KeyG2SigG1 = G2 65 ) 66 67 func (f *G1) setBytes(b []byte) error { return f.g.SetBytes(b) } 68 func (f *G2) setBytes(b []byte) error { return f.g.SetBytes(b) } 69 70 func (f *G1) hash(msg []byte) { f.g.Hash(msg, []byte(dstG1)) } 71 func (f *G2) hash(msg []byte) { f.g.Hash(msg, []byte(dstG2)) } 72 73 // KeyGroup determines the group used for keys, while the other 74 // group is used for signatures. 75 type KeyGroup interface{ G1 | G2 } 76 77 type PrivateKey[K KeyGroup] struct { 78 key GG.Scalar 79 pub *PublicKey[K] 80 } 81 82 type PublicKey[K KeyGroup] struct{ key K } 83 84 func (k *PrivateKey[K]) Public() crypto.PublicKey { return k.PublicKey() } 85 86 // PublicKey computes the corresponding public key. The key is cached 87 // for further invocations to this function. 88 func (k *PrivateKey[K]) PublicKey() *PublicKey[K] { 89 if k.pub == nil { 90 k.pub = new(PublicKey[K]) 91 switch any(k).(type) { 92 case *PrivateKey[G1]: 93 kk := any(&k.pub.key).(*G1) 94 kk.g.ScalarMult(&k.key, GG.G1Generator()) 95 case *PrivateKey[G2]: 96 kk := any(&k.pub.key).(*G2) 97 kk.g.ScalarMult(&k.key, GG.G2Generator()) 98 default: 99 panic(ErrInvalid) 100 } 101 } 102 103 return k.pub 104 } 105 106 func (k *PrivateKey[K]) Equal(x crypto.PrivateKey) bool { 107 xx, ok := x.(*PrivateKey[K]) 108 if !ok { 109 return false 110 } 111 112 switch any(k).(type) { 113 case *PrivateKey[G1], *PrivateKey[G2]: 114 return k.key.IsEqual(&xx.key) == 1 115 default: 116 panic(ErrInvalid) 117 } 118 } 119 120 // Validate explicitly determines if a private key is valid. 121 func (k *PrivateKey[K]) Validate() bool { 122 switch any(k).(type) { 123 case *PrivateKey[G1], *PrivateKey[G2]: 124 return k.key.IsZero() == 0 125 default: 126 panic(ErrInvalid) 127 } 128 } 129 130 // MarshalBinary returns a slice with the representation of 131 // the underlying PrivateKey scalar (in big-endian order). 132 func (k *PrivateKey[K]) MarshalBinary() ([]byte, error) { 133 switch any(k).(type) { 134 case *PrivateKey[G1], *PrivateKey[G2]: 135 return k.key.MarshalBinary() 136 default: 137 panic(ErrInvalid) 138 } 139 } 140 141 func (k *PrivateKey[K]) UnmarshalBinary(data []byte) error { 142 switch any(k).(type) { 143 case *PrivateKey[G1], *PrivateKey[G2]: 144 if err := k.key.UnmarshalBinary(data); err != nil { 145 return err 146 } 147 if !k.Validate() { 148 return ErrInvalidKey 149 } 150 k.pub = nil 151 return nil 152 default: 153 panic(ErrInvalid) 154 } 155 } 156 157 // Validate explicitly determines if a public key is valid. 158 func (k *PublicKey[K]) Validate() bool { 159 switch any(k).(type) { 160 case *PublicKey[G1]: 161 kk := any(k.key).(G1) 162 return !kk.g.IsIdentity() && kk.g.IsOnG1() 163 case *PublicKey[G2]: 164 kk := any(k.key).(G2) 165 return !kk.g.IsIdentity() && kk.g.IsOnG2() 166 default: 167 panic(ErrInvalid) 168 } 169 } 170 171 func (k *PublicKey[K]) Equal(x crypto.PublicKey) bool { 172 xx, ok := x.(*PublicKey[K]) 173 if !ok { 174 return false 175 } 176 177 switch any(k).(type) { 178 case *PublicKey[G1]: 179 xxx := any(xx.key).(G1) 180 kk := any(k.key).(G1) 181 return kk.g.IsEqual(&xxx.g) 182 case *PublicKey[G2]: 183 xxx := any(xx.key).(G2) 184 kk := any(k.key).(G2) 185 return kk.g.IsEqual(&xxx.g) 186 default: 187 panic(ErrInvalid) 188 } 189 } 190 191 // MarshalBinary returns a slice with the compressed 192 // representation of the underlying element in G1 or G2. 193 func (k *PublicKey[K]) MarshalBinary() ([]byte, error) { 194 switch any(k).(type) { 195 case *PublicKey[G1]: 196 kk := any(k.key).(G1) 197 return kk.g.BytesCompressed(), nil 198 case *PublicKey[G2]: 199 kk := any(k.key).(G2) 200 return kk.g.BytesCompressed(), nil 201 default: 202 panic(ErrInvalid) 203 } 204 } 205 206 func (k *PublicKey[K]) UnmarshalBinary(data []byte) error { 207 switch any(k).(type) { 208 case *PublicKey[G1]: 209 kk := any(&k.key).(*G1) 210 return kk.setBytes(data) 211 case *PublicKey[G2]: 212 kk := any(&k.key).(*G2) 213 return kk.setBytes(data) 214 default: 215 panic(ErrInvalid) 216 } 217 } 218 219 // KeyGen derives a private key for the specified group (G1 or G2). 220 // The length of ikm material should be at least 32 bytes length. 221 // The salt value should be either empty or a uniformly random 222 // bytes whose length equals the output length of SHA-256. 223 func KeyGen[K KeyGroup](ikm, salt, keyInfo []byte) (*PrivateKey[K], error) { 224 // Implements recommended method at: 225 // https://datatracker.ietf.org/doc/html/draft-irtf-cfrg-bls-signature-05#name-keygen 226 if len(ikm) < 32 { 227 return nil, ErrShortIKM 228 } 229 230 ikmZero := make([]byte, len(ikm)+1) 231 keyInfoTwo := make([]byte, len(keyInfo)+2) 232 copy(ikmZero, ikm) 233 copy(keyInfoTwo, keyInfo) 234 const L = uint16(48) 235 binary.BigEndian.PutUint16(keyInfoTwo[len(keyInfo):], L) 236 OKM := make([]byte, L) 237 238 var ss GG.Scalar 239 for tries := 8; tries > 0; tries-- { 240 rd := hkdf.New(sha256.New, ikmZero, salt, keyInfoTwo) 241 n, err := io.ReadFull(rd, OKM) 242 if n != len(OKM) || err != nil { 243 return nil, err 244 } 245 246 ss.SetBytes(OKM) 247 248 if ss.IsZero() == 1 { 249 digest := sha256.Sum256(salt) 250 salt = digest[:] 251 } else { 252 return &PrivateKey[K]{key: ss, pub: nil}, nil 253 } 254 } 255 256 return nil, ErrKeyGen 257 } 258 259 // Sign computes a signature of a message using a key (defined in 260 // G1 or G1). 261 func Sign[K KeyGroup](k *PrivateKey[K], msg []byte) Signature { 262 if !k.Validate() { 263 panic(ErrInvalidKey) 264 } 265 266 switch any(k).(type) { 267 case *PrivateKey[G1]: 268 var Q GG.G2 269 Q.Hash(msg, []byte(dstG2)) 270 Q.ScalarMult(&k.key, &Q) 271 return Q.BytesCompressed() 272 case *PrivateKey[G2]: 273 var Q GG.G1 274 Q.Hash(msg, []byte(dstG1)) 275 Q.ScalarMult(&k.key, &Q) 276 return Q.BytesCompressed() 277 default: 278 panic(ErrInvalid) 279 } 280 } 281 282 // Verify returns true if the signature of a message is valid for the 283 // corresponding public key. 284 func Verify[K KeyGroup](pub *PublicKey[K], msg []byte, sig Signature) bool { 285 var ( 286 a, b interface { 287 setBytes([]byte) error 288 hash([]byte) 289 } 290 listG1 [2]*GG.G1 291 listG2 [2]*GG.G2 292 ) 293 294 switch any(pub).(type) { 295 case *PublicKey[G1]: 296 aa, bb := new(G2), new(G2) 297 a, b = aa, bb 298 k := any(pub.key).(G1) 299 listG1[0], listG1[1] = &k.g, GG.G1Generator() 300 listG2[0], listG2[1] = &aa.g, &bb.g 301 case *PublicKey[G2]: 302 aa, bb := new(G1), new(G1) 303 a, b = aa, bb 304 k := any(pub.key).(G2) 305 listG2[0], listG2[1] = &k.g, GG.G2Generator() 306 listG1[0], listG1[1] = &aa.g, &bb.g 307 default: 308 panic(ErrInvalid) 309 } 310 311 err := b.setBytes(sig) 312 if err != nil { 313 return false 314 } 315 if !pub.Validate() { 316 return false 317 } 318 a.hash(msg) 319 320 res := GG.ProdPairFrac(listG1[:], listG2[:], []int{1, -1}) 321 return res.IsIdentity() 322 } 323 324 // Aggregate produces a unified signature given a list of signatures. 325 // To specify the group of keys pass either G1{} or G2{} as the first 326 // parameter. 327 func Aggregate[K KeyGroup](k K, sigs []Signature) (Signature, error) { 328 if len(sigs) == 0 { 329 return nil, ErrAggregate 330 } 331 332 switch any(k).(type) { 333 case G1: 334 var P, Q GG.G2 335 P.SetIdentity() 336 for _, sig := range sigs { 337 if err := Q.SetBytes(sig); err != nil { 338 return nil, err 339 } 340 P.Add(&P, &Q) 341 } 342 return P.BytesCompressed(), nil 343 344 case G2: 345 var P, Q GG.G1 346 P.SetIdentity() 347 for _, sig := range sigs { 348 if err := Q.SetBytes(sig); err != nil { 349 return nil, err 350 } 351 P.Add(&P, &Q) 352 } 353 return P.BytesCompressed(), nil 354 355 default: 356 panic(ErrInvalid) 357 } 358 } 359 360 // VerifyAggregate returns true if the aggregated signature is valid for 361 // the list of messages and public keys provided. The slices must have 362 // equal size and have at least one element. 363 func VerifyAggregate[K KeyGroup](pubs []*PublicKey[K], msgs [][]byte, aggSig Signature) bool { 364 if len(pubs) != len(msgs) || len(pubs) == 0 { 365 return false 366 } 367 368 for _, p := range pubs { 369 if !p.Validate() { 370 return false 371 } 372 } 373 374 n := len(pubs) 375 listG1 := make([]*GG.G1, n+1) 376 listG2 := make([]*GG.G2, n+1) 377 listSigns := make([]int, n+1) 378 379 listG1[n] = GG.G1Generator() 380 listG2[n] = GG.G2Generator() 381 listSigns[n] = -1 382 383 switch any(pubs).(type) { 384 case []*PublicKey[G1]: 385 for i := range msgs { 386 listG2[i] = new(GG.G2) 387 listG2[i].Hash(msgs[i], []byte(dstG2)) 388 389 xP := any(pubs[i].key).(G1) 390 listG1[i] = &xP.g 391 listSigns[i] = 1 392 } 393 394 err := listG2[n].SetBytes(aggSig) 395 if err != nil { 396 return false 397 } 398 399 case []*PublicKey[G2]: 400 for i := range msgs { 401 listG1[i] = new(GG.G1) 402 listG1[i].Hash(msgs[i], []byte(dstG1)) 403 404 xP := any(pubs[i].key).(G2) 405 listG2[i] = &xP.g 406 listSigns[i] = 1 407 } 408 409 err := listG1[n].SetBytes(aggSig) 410 if err != nil { 411 return false 412 } 413 414 default: 415 panic(ErrInvalid) 416 } 417 418 C := GG.ProdPairFrac(listG1, listG2, listSigns) 419 return C.IsIdentity() 420 }