github.com/dusk-network/dusk-crypto@v0.1.3/bls/bls.go (about) 1 // Package bls implements the compact BLS Multisignature construction which preappends the public key to the signature 2 // according to the *plain public-key model*. 3 // The form implemented uses an array of distinct keys (as in https://crypto.stanford.edu/~dabo/pubs/papers/BLSmultisig.html) 4 // instead of the aggregated form (as in https://eprint.iacr.org/2018/483.pdf where {pk₁,...,pkₙ} would be appended to each pkᵢ 5 //according to apk ← ∏ⁿᵢ₌₁ pk^H₁(pkᵢ, {pk₁,...,pkₙ}) 6 package bls 7 8 import ( 9 "crypto/rand" 10 "crypto/subtle" 11 "encoding/base64" 12 "encoding/hex" 13 "fmt" 14 "io" 15 "math/big" 16 17 "github.com/dusk-network/bn256" 18 "github.com/dusk-network/dusk-crypto/hash" 19 "github.com/pkg/errors" 20 "golang.org/x/crypto/sha3" 21 ) 22 23 var ( 24 // g1Str is the hexadecimal string representing the base specified for the G1 base point. It is taken from the cloudflare's bn256 implementation. 25 g1Str = "00000000000000000000000000000000000000000000000000000000000000018fb501e34aa387f9aa6fecb86184dc21ee5b88d120b5b59e185cac6c5e089665" 26 27 // g1Base is the base point specified for the G1 group. If one wants to use a 28 // different point, set this variable before using any public methods / structs of this package. 29 g1Base *bn256.G1 30 31 // g2Str is the hexadecimal string representing the base specified for the G1 base point. 32 g2Str = "012ecca446ff6f3d4d03c76e9b5c752f28bc37b364cb05ac4a37eb32e1c32459708f25386f72c9462b81597d65ae2092c4b97792155dcdaad32b8a6dd41792534c2db10ef5233b0fe3962b9ee6a4bbc2b5bde01a54f3513d42df972e128f31bf12274e5747e8cafacc3716cc8699db79b22f0e4ff3c23e898f694420a3be3087a5" 33 34 // g2Base is the base point specified for the G2 group. If one wants to use a 35 // different point, set this variable before using any public methods / structs of this package. 36 g2Base *bn256.G2 37 ) 38 39 // TODO: We should probably transform BLS in a struct and delegate initialization to the code user. The motivation is that they might want to use a different curve altogether 40 func init() { 41 g1Base = newG1Base(g1Str) 42 g2Base = newG2Base(g2Str) 43 } 44 45 // newG1 is the constructor for the G1 group as in the BN256 curve 46 func newG1() *bn256.G1 { 47 return new(bn256.G1) 48 } 49 50 // newG2 is the constructor for the G2 group as in the BN256 curve 51 func newG2() *bn256.G2 { 52 return new(bn256.G2) 53 } 54 55 // newG1Base is the initialization function for the G1Base point for BN256. It takes as input the HEX string representation of a base point 56 func newG1Base(strRepr string) *bn256.G1 { 57 buff, err := hex.DecodeString(strRepr) 58 if err != nil { 59 panic(errors.Wrap(err, "bn256: can't decode base point on G1. Fatal error")) 60 } 61 g1Base = new(bn256.G1) 62 63 _, err = g1Base.Unmarshal(buff) 64 if err != nil { 65 panic(errors.Wrap(err, "bn256: can't decode base point on G1. Fatal error")) 66 } 67 68 return g1Base 69 } 70 71 // newG2Base is the initialization function for the G2Base point for BN256 72 func newG2Base(strRepr string) *bn256.G2 { 73 buff, err := hex.DecodeString(strRepr) 74 if err != nil { 75 panic(errors.Wrap(err, "bn256: can't decode base point on G2. Fatal error")) 76 } 77 g2Base = new(bn256.G2) 78 79 _, err = g2Base.Unmarshal(buff) 80 if err != nil { 81 panic(errors.Wrap(err, "bn256: can't decode base point on G2. Fatal error")) 82 } 83 84 return g2Base 85 } 86 87 // SecretKey has "x" as secret for the BLS signature 88 type SecretKey struct { 89 x *big.Int 90 } 91 92 // PublicKey is calculated as g^x 93 type PublicKey struct { 94 gx *bn256.G2 95 } 96 97 // Apk is the short aggregated public key struct 98 type Apk struct { 99 *PublicKey 100 } 101 102 // Signature is the plain public key model of the BLS signature being resilient to rogue key attack 103 type Signature struct { 104 e *bn256.G1 105 } 106 107 // UnsafeSignature is the BLS Signature Struct not resilient to rogue-key attack 108 type UnsafeSignature struct { 109 e *bn256.G1 110 } 111 112 // GenKeyPair generates Public and Private Keys 113 func GenKeyPair(randReader io.Reader) (*PublicKey, *SecretKey, error) { 114 if randReader == nil { 115 randReader = rand.Reader 116 } 117 x, gx, err := bn256.RandomG2(randReader) 118 119 if err != nil { 120 return nil, nil, err 121 } 122 123 return &PublicKey{gx}, &SecretKey{x}, nil 124 } 125 126 // UnmarshalPk unmarshals a byte array into a BLS PublicKey 127 func UnmarshalPk(b []byte) (*PublicKey, error) { 128 pk := &PublicKey{nil} 129 if err := pk.Unmarshal(b); err != nil { 130 return nil, err 131 } 132 return pk, nil 133 } 134 135 //hashFn is the hash function used to digest a message before mapping it to a point. 136 var hashFn = sha3.New256 137 138 // h0 is the hash-to-curve-point function 139 // Hₒ : M -> Gₒ 140 // TODO: implement the Elligator algorithm for deterministic random-looking hashing to BN256 point. See https://eprint.iacr.org/2014/043.pdf 141 func h0(msg []byte) (*bn256.G1, error) { 142 hashed, err := hash.PerformHash(hashFn(), msg) 143 if err != nil { 144 return nil, err 145 } 146 k := new(big.Int).SetBytes(hashed) 147 return newG1().ScalarBaseMult(k), nil 148 } 149 150 // h1 is the hashing function used in the modified BLS multi-signature construction 151 // H₁: G₂->R 152 func h1(pk *PublicKey) (*big.Int, error) { 153 // marshalling G2 into a []byte 154 pkb := pk.Marshal() 155 // hashing into Z 156 h, err := hash.PerformHash(hashFn(), pkb) 157 if err != nil { 158 return nil, err 159 } 160 161 return new(big.Int).SetBytes(h), nil 162 } 163 164 func pkt(pk *PublicKey) (*bn256.G2, error) { 165 t, err := h1(pk) 166 if err != nil { 167 return nil, err 168 } 169 170 //TODO: maybe a bit inefficient to recreate G2 instances instead of mutating the underlying group 171 return newG2().ScalarMult(pk.gx, t), nil 172 } 173 174 // NewApk creates an Apk either from a public key or scratch 175 func NewApk(pk *PublicKey) *Apk { 176 if pk == nil { 177 return nil 178 } 179 180 gx, _ := pkt(pk) 181 return &Apk{ 182 PublicKey: &PublicKey{gx}, 183 } 184 } 185 186 // Copy the APK by marshalling and unmarshalling the internals. It is somewhat 187 // wasteful but does the job 188 func (apk *Apk) Copy() *Apk { 189 g2 := new(bn256.G2) 190 b := apk.gx.Marshal() 191 // no need to check errors. We deal with well formed APKs 192 _, _ = g2.Unmarshal(b) 193 194 cpy := &Apk{ 195 PublicKey: &PublicKey{g2}, 196 } 197 return cpy 198 } 199 200 // UnmarshalApk unmarshals a byte array into an aggregated PublicKey 201 func UnmarshalApk(b []byte) (*Apk, error) { 202 apk := &Apk{ 203 PublicKey: &PublicKey{gx: nil}, 204 } 205 206 if err := apk.Unmarshal(b); err != nil { 207 return nil, err 208 } 209 return apk, nil 210 } 211 212 // AggregateApk aggregates the public key according to the following formula: 213 // apk ← ∏ⁿᵢ₌₁ pk^H₁(pkᵢ) 214 func AggregateApk(pks []*PublicKey) (*Apk, error) { 215 var apk *Apk 216 for i, pk := range pks { 217 if i == 0 { 218 apk = NewApk(pk) 219 continue 220 } 221 222 if err := apk.Aggregate(pk); err != nil { 223 return nil, err 224 } 225 } 226 227 return apk, nil 228 } 229 230 // Aggregate a Public Key to the Apk struct 231 // according to the formula pk^H₁(pkᵢ) 232 func (apk *Apk) Aggregate(pk *PublicKey) error { 233 gxt, err := pkt(pk) 234 if err != nil { 235 return err 236 } 237 238 apk.gx.Add(apk.gx, gxt) 239 return nil 240 } 241 242 // AggregateBytes is a convenient method to aggregate the unmarshalled form of PublicKey directly 243 func (apk *Apk) AggregateBytes(b []byte) error { 244 pk := &PublicKey{} 245 if err := pk.Unmarshal(b); err != nil { 246 return err 247 } 248 return apk.Aggregate(pk) 249 } 250 251 // Sign creates a signature from the private key and the public key pk 252 func Sign(sk *SecretKey, pk *PublicKey, msg []byte) (*Signature, error) { 253 sig, err := UnsafeSign(sk, msg) 254 if err != nil { 255 return nil, err 256 } 257 258 return apkSigWrap(pk, sig) 259 } 260 261 // UnmarshalSignature unmarshals a byte array into a BLS signature 262 func UnmarshalSignature(sig []byte) (*Signature, error) { 263 sigma := &Signature{} 264 if err := sigma.Unmarshal(sig); err != nil { 265 return nil, err 266 } 267 return sigma, nil 268 } 269 270 // Copy (inefficiently) the Signature by unmarshaling and marshaling the 271 // embedded G1 272 func (sigma *Signature) Copy() *Signature { 273 b := sigma.e.Marshal() 274 s := &Signature{ 275 e: new(bn256.G1), 276 } 277 _, _ = s.e.Unmarshal(b) 278 return s 279 } 280 281 // Add creates an aggregated signature from a normal BLS Signature and related public key 282 func (sigma *Signature) Add(pk *PublicKey, sig *UnsafeSignature) error { 283 other, err := apkSigWrap(pk, sig) 284 if err != nil { 285 return err 286 } 287 288 sigma.Aggregate(other) 289 return nil 290 } 291 292 // AggregateBytes is a shorthand for unmarshalling a byte array into a Signature and thus mutate Signature sigma by aggregating the unmarshalled signature 293 func (sigma *Signature) AggregateBytes(other []byte) error { 294 sig := &Signature{e: nil} 295 if err := sig.Unmarshal(other); err != nil { 296 return err 297 } 298 sigma.Aggregate(sig) 299 return nil 300 } 301 302 // Aggregate two Signature 303 func (sigma *Signature) Aggregate(other *Signature) *Signature { 304 sigma.e.Add(sigma.e, other.e) 305 return sigma 306 } 307 308 // Compress the signature to the 32 byte form 309 func (sigma *Signature) Compress() []byte { 310 return sigma.e.Compress() 311 } 312 313 // Decompress reconstructs the 64 byte signature from the compressed form 314 func (sigma *Signature) Decompress(x []byte) error { 315 e, err := bn256.Decompress(x) 316 if err != nil { 317 return err 318 } 319 sigma.e = e 320 return nil 321 } 322 323 // Marshal a Signature into a byte array 324 func (sigma *Signature) Marshal() []byte { 325 return sigma.e.Marshal() 326 } 327 328 // Unmarshal a byte array into a Signature 329 func (sigma *Signature) Unmarshal(msg []byte) error { 330 var err error 331 var e *bn256.G1 332 if len(msg) == 33 { 333 e, err = bn256.Decompress(msg) 334 if err != nil { 335 return err 336 } 337 sigma.e = e 338 return nil 339 } 340 341 e = newG1() 342 if _, err := e.Unmarshal(msg); err != nil { 343 return err 344 } 345 sigma.e = e 346 return nil 347 } 348 349 // apkSigWrap turns a BLS Signature into its modified construction 350 func apkSigWrap(pk *PublicKey, signature *UnsafeSignature) (*Signature, error) { 351 // creating tᵢ by hashing PKᵢ 352 t, err := h1(pk) 353 if err != nil { 354 return nil, err 355 } 356 357 sigma := newG1() 358 359 sigma.ScalarMult(signature.e, t) 360 361 return &Signature{e: sigma}, nil 362 } 363 364 // Verify is the verification step of an aggregated apk signature 365 func Verify(apk *Apk, msg []byte, sigma *Signature) error { 366 return verify(apk.gx, msg, sigma.e) 367 } 368 369 // VerifyBatch is the verification step of a batch of aggregated apk signatures 370 // TODO: consider adding the possibility to handle non distinct messages (at batch level after aggregating APK) 371 func VerifyBatch(apks []*Apk, msgs [][]byte, sigma *Signature) error { 372 if len(msgs) != len(apks) { 373 return fmt.Errorf( 374 "BLS Verify APK Batch: the nr of Public Keys (%d) and the nr. of messages (%d) do not match", 375 len(apks), 376 len(msgs), 377 ) 378 } 379 380 pks := make([]*bn256.G2, len(apks)) 381 for i, pk := range apks { 382 pks[i] = pk.gx 383 } 384 385 return verifyBatch(pks, msgs, sigma.e, false) 386 } 387 388 // UnsafeSign generates an UnsafeSignature being vulnerable to the rogue-key attack and therefore can only be used if the messages are distinct 389 func UnsafeSign(key *SecretKey, msg []byte) (*UnsafeSignature, error) { 390 hash, err := h0(msg) 391 if err != nil { 392 return nil, err 393 } 394 p := newG1() 395 p.ScalarMult(hash, key.x) 396 return &UnsafeSignature{p}, nil 397 } 398 399 // Compress the signature to the 32 byte form 400 func (usig *UnsafeSignature) Compress() []byte { 401 return usig.e.Compress() 402 } 403 404 // Decompress reconstructs the 64 byte signature from the compressed form 405 func (usig *UnsafeSignature) Decompress(x []byte) error { 406 e, err := bn256.Decompress(x) 407 if err != nil { 408 return err 409 } 410 usig.e = e 411 return nil 412 } 413 414 // Marshal an UnsafeSignature into a byte array 415 func (usig *UnsafeSignature) Marshal() []byte { 416 return usig.e.Marshal() 417 } 418 419 // Unmarshal a byte array into an UnsafeSignature 420 func (usig *UnsafeSignature) Unmarshal(msg []byte) error { 421 e := newG1() 422 if _, err := e.Unmarshal(msg); err != nil { 423 return err 424 } 425 usig.e = e 426 return nil 427 } 428 429 // UnsafeAggregate combines signatures on distinct messages. 430 func UnsafeAggregate(one, other *UnsafeSignature) *UnsafeSignature { 431 res := newG1() 432 res.Add(one.e, other.e) 433 return &UnsafeSignature{e: res} 434 } 435 436 // UnsafeBatch is a utility function to aggregate distinct messages 437 // (if not distinct the scheme is vulnerable to chosen-key attack) 438 func UnsafeBatch(sigs ...*UnsafeSignature) (*UnsafeSignature, error) { 439 var sum *UnsafeSignature 440 for i, sig := range sigs { 441 if i == 0 { 442 sum = sig 443 } else { 444 sum = UnsafeAggregate(sum, sig) 445 } 446 } 447 448 return sum, nil 449 } 450 451 // VerifyUnsafeBatch verifies a batch of messages signed with aggregated signature 452 // the rogue-key attack is prevented by making all messages distinct 453 func VerifyUnsafeBatch(pkeys []*PublicKey, msgList [][]byte, signature *UnsafeSignature) error { 454 g2s := make([]*bn256.G2, len(pkeys)) 455 for i, pk := range pkeys { 456 g2s[i] = pk.gx 457 } 458 return verifyBatch(g2s, msgList, signature.e, false) 459 } 460 461 // VerifyUnsafe checks the given BLS signature bls on the message m using the 462 // public key pkey by verifying that the equality e(H(m), X) == e(H(m), x*B2) == 463 // e(x*H(m), B2) == e(S, B2) holds where e is the pairing operation and B2 is the base point from curve G2. 464 func VerifyUnsafe(pkey *PublicKey, msg []byte, signature *UnsafeSignature) error { 465 return verify(pkey.gx, msg, signature.e) 466 } 467 468 func verify(pk *bn256.G2, msg []byte, sigma *bn256.G1) error { 469 h0m, err := h0(msg) 470 if err != nil { 471 return err 472 } 473 474 pairH0mPK := bn256.Pair(h0m, pk).Marshal() 475 pairSigG2 := bn256.Pair(sigma, g2Base).Marshal() 476 if subtle.ConstantTimeCompare(pairH0mPK, pairSigG2) != 1 { 477 msg := fmt.Sprintf( 478 "bls apk: Invalid Signature.\nG1Sig pair (length %d): %v...\nApk H0(m) pair (length %d): %v...", 479 len(pairSigG2), 480 hex.EncodeToString(pairSigG2[0:10]), 481 len(pairH0mPK), 482 hex.EncodeToString(pairH0mPK[0:10]), 483 ) 484 return errors.New(msg) 485 } 486 487 return nil 488 } 489 490 func verifyBatch(pkeys []*bn256.G2, msgList [][]byte, sig *bn256.G1, allowDistinct bool) error { 491 if !allowDistinct && !distinct(msgList) { 492 return errors.New("bls: Messages are not distinct") 493 } 494 495 var pairH0mPKs *bn256.GT 496 // TODO: I suspect that this could be sped up by doing the addition through a pool of goroutines 497 for i := range msgList { 498 h0m, err := h0(msgList[i]) 499 if err != nil { 500 return err 501 } 502 503 if i == 0 { 504 pairH0mPKs = bn256.Pair(h0m, pkeys[i]) 505 } else { 506 pairH0mPKs.Add(pairH0mPKs, bn256.Pair(h0m, pkeys[i])) 507 } 508 } 509 510 pairSigG2 := bn256.Pair(sig, g2Base) 511 512 if subtle.ConstantTimeCompare(pairSigG2.Marshal(), pairH0mPKs.Marshal()) != 1 { 513 return errors.New("bls: Invalid Signature") 514 } 515 516 return nil 517 } 518 519 // VerifyCompressed verifies a Compressed marshalled signature 520 func VerifyCompressed(pks []*bn256.G2, msgList [][]byte, compressedSig []byte, allowDistinct bool) error { 521 sig, err := bn256.Decompress(compressedSig) 522 if err != nil { 523 return err 524 } 525 return verifyBatch(pks, msgList, sig, allowDistinct) 526 } 527 528 // distinct makes sure that the msg list is composed of different messages 529 func distinct(msgList [][]byte) bool { 530 m := make(map[[32]byte]bool) 531 for _, msg := range msgList { 532 h := sha3.Sum256(msg) 533 if m[h] { 534 return false 535 } 536 m[h] = true 537 } 538 return true 539 } 540 541 // Aggregate is a shortcut for Public Key aggregation 542 func (pk *PublicKey) Aggregate(pp *PublicKey) *PublicKey { 543 p3 := newG2() 544 p3.Add(pk.gx, pp.gx) 545 return &PublicKey{p3} 546 } 547 548 // MarshalText encodes the string representation of the public key 549 func (pk *PublicKey) MarshalText() ([]byte, error) { 550 return encodeToText(pk.gx.Marshal()), nil 551 } 552 553 // UnmarshalText decode the string/byte representation into the public key 554 func (pk *PublicKey) UnmarshalText(data []byte) error { 555 bs, err := decodeText(data) 556 if err != nil { 557 return err 558 } 559 pk.gx = newG2() 560 _, err = pk.gx.Unmarshal(bs) 561 if err != nil { 562 return err 563 } 564 return nil 565 } 566 567 // Marshal returns the binary representation of the G2 point being the public key 568 func (pk *PublicKey) Marshal() []byte { 569 return pk.gx.Marshal() 570 } 571 572 // Unmarshal a public key from a byte array 573 func (pk *PublicKey) Unmarshal(data []byte) error { 574 pk.gx = newG2() 575 _, err := pk.gx.Unmarshal(data) 576 if err != nil { 577 return err 578 } 579 return nil 580 } 581 582 func encodeToText(data []byte) []byte { 583 buf := make([]byte, base64.RawURLEncoding.EncodedLen(len(data))) 584 base64.RawURLEncoding.Encode(buf, data) 585 return buf 586 } 587 588 func decodeText(data []byte) ([]byte, error) { 589 buf := make([]byte, base64.RawURLEncoding.DecodedLen(len(data))) 590 n, err := base64.RawURLEncoding.Decode(buf, data) 591 return buf[:n], err 592 }