github.com/bigzoro/my_simplechain@v0.0.0-20240315012955-8ad0a2a29bb9/consensus/hotstuff/bls12-381/crypto.go (about)

     1  package bls
     2  
     3  import (
     4  	"crypto/rand"
     5  	"encoding/binary"
     6  	"encoding/json"
     7  	"errors"
     8  	"fmt"
     9  	"math/big"
    10  
    11  	"github.com/bigzoro/my_simplechain/consensus/hotstuff/common"
    12  	"github.com/bits-and-blooms/bitset"
    13  	bls12381 "github.com/kilic/bls12-381"
    14  )
    15  
    16  const (
    17  	BLSfpByteSize = 48
    18  )
    19  
    20  var (
    21  	// errBytesLength is returned if the unmarshaled raw bytes do not conform
    22  	// to the specification of a bls12381 scheme.
    23  	errBytesLength = errors.New("invalid raw byte length")
    24  
    25  	// errPublicKeyNotFound is returned if the public key corresponding to the
    26  	// signature ID cannot be found in the quorum during signature verification.
    27  	errPublicKeyNotFound = errors.New("public key not found")
    28  
    29  	// errInsufficientSigners is returned if a quorum certificate does not
    30  	// contain enough signatures.
    31  	errInsufficientSigners = errors.New("insufficient signers")
    32  
    33  	// errFailedVerification is returned if signature verification fails.
    34  	errFailedVerification = errors.New("verification fails")
    35  )
    36  
    37  type quorum interface {
    38  	// Count returns the total number of participating replicas.
    39  	Count() int
    40  
    41  	// Threshold returns the minimum number of consensus nodes required to achieve
    42  	// aggregation criteria.
    43  	Threshold() int
    44  
    45  	// PublicKey returns the public key corresponding to the signature ID.
    46  	PublicKey(common.ID) (*PublicKey, bool)
    47  
    48  	// ForEach calls f for each ID in the quorum.
    49  	ForEach(f func(common.ID, *PublicKey))
    50  
    51  	// RangeWhile calls f for each ID in the quorum until f returns false
    52  	RangeWhile(f func(common.ID, *PublicKey) bool)
    53  }
    54  
    55  // PublicKey is a bls12-381 public key.
    56  type PublicKey struct {
    57  	point *bls12381.PointG1
    58  }
    59  
    60  // ToBytes marshals the public key to a byte slice.
    61  func (k PublicKey) ToBytes() []byte {
    62  	return bls12381.NewG1().ToCompressed(k.point)
    63  }
    64  
    65  // FromBytes unmarshals the public key from a byte slice.
    66  func (k *PublicKey) FromBytes(b []byte) (err error) {
    67  	k.point, err = bls12381.NewG1().FromCompressed(b)
    68  	if err != nil {
    69  		return fmt.Errorf("bls12: failed to decompress public key: %w", err)
    70  	}
    71  	return nil
    72  }
    73  
    74  func (k *PublicKey) UnmarshalJSON(data []byte) error {
    75  	var pbytes []byte
    76  	if err := json.Unmarshal(data, &pbytes); err != nil {
    77  		return err
    78  	}
    79  	return k.FromBytes(pbytes)
    80  }
    81  
    82  func (k *PublicKey) MarshalJSON() ([]byte, error) {
    83  	return json.Marshal(k.ToBytes())
    84  }
    85  
    86  // PrivateKey is a bls12-381 private key.
    87  type PrivateKey struct {
    88  	sec    *big.Int
    89  	pubkey *PublicKey
    90  }
    91  
    92  // SignWithId signs the message and generates a partial signature based on the ID.
    93  func (k *PrivateKey) SignWithId(msg []byte, id common.ID) (*PartialSignature, error) {
    94  	point, err := sign(k.sec, msg)
    95  	if err != nil {
    96  		return nil, err
    97  	}
    98  	return &PartialSignature{pointg2: point, id: id}, nil
    99  }
   100  
   101  // Public returns the public key associated with this private key.
   102  func (k *PrivateKey) Public() *PublicKey {
   103  	if k.pubkey == nil {
   104  		k.pubkey = &PublicKey{point: bls12381.NewG1().MulScalarBig(new(bls12381.PointG1), &bls12381.G1One, k.sec)}
   105  	}
   106  	return k.pubkey
   107  }
   108  
   109  // ToBytes marshals the private key to a byte slice.
   110  func (k PrivateKey) ToBytes() []byte {
   111  	return k.sec.Bytes()
   112  }
   113  
   114  // FromBytes unmarshals the private key from a byte slice.
   115  func (k *PrivateKey) FromBytes(b []byte) {
   116  	k.sec = new(big.Int)
   117  	k.sec.SetBytes(b)
   118  }
   119  
   120  // GeneratePrivateKey generates a random private key.
   121  func GeneratePrivateKey() *PrivateKey {
   122  	rd, _ := rand.Int(rand.Reader, curveOrder)
   123  	return &PrivateKey{sec: rd}
   124  }
   125  
   126  // AggregateSignature is a bls12-381 aggregate signature. The participants
   127  // field contains the IDs of the replicas that participated in signature
   128  // creation. This allows us to build an aggregated public key to verify the signature.
   129  type AggregateSignature struct {
   130  	pointg2      *bls12381.PointG2
   131  	participants *bitset.BitSet // The ids of the replicas who submitted signatures.
   132  }
   133  
   134  // AggregateVerify verifys if the aggregate signature is valid for the message.
   135  func (s *AggregateSignature) Verify(qr quorum, msg []byte) error {
   136  	if s.participants.Count() < uint(qr.Threshold()) {
   137  		return errInsufficientSigners
   138  	}
   139  	pubs := make([]*bls12381.PointG1, 0, s.participants.Count())
   140  	qr.ForEach(func(id common.ID, pk *PublicKey) {
   141  		if s.participants.Test(uint(id.Uint32())) {
   142  			pubs = append(pubs, pk.point)
   143  		}
   144  	})
   145  
   146  	if !fastAggregateVerify(msg, s.pointg2, pubs...) {
   147  		return errFailedVerification
   148  	}
   149  	return nil
   150  }
   151  
   152  // ToBytes marshals the aggregate signature to a byte slice.
   153  func (s *AggregateSignature) ToBytes() ([]byte, error) {
   154  	id, err := s.participants.MarshalBinary()
   155  	if err != nil {
   156  		return nil, err
   157  	}
   158  	point := bls12381.NewG2().ToCompressed(s.pointg2)
   159  	return append(point, id...), nil
   160  }
   161  
   162  // FromBytes unmarshals the aggregate signature from a byte slice.
   163  func (s *AggregateSignature) FromBytes(data []byte) (err error) {
   164  	if len(data) < 2*BLSfpByteSize {
   165  		return errBytesLength
   166  	}
   167  	s.pointg2, err = bls12381.NewG2().FromCompressed(data[:2*BLSfpByteSize])
   168  	if err != nil {
   169  		return err
   170  	}
   171  	s.participants = bitset.New(1)
   172  	return s.participants.UnmarshalBinary(data[2*BLSfpByteSize:])
   173  }
   174  
   175  // Clone returns a copy of the aggregate signature.
   176  func (s *AggregateSignature) Clone() *AggregateSignature {
   177  	return &AggregateSignature{
   178  		pointg2:      new(bls12381.PointG2).Set(s.pointg2),
   179  		participants: s.participants.Clone(),
   180  	}
   181  }
   182  
   183  // PartialSignature is a bls12-381 partial signature. it contains the ID
   184  // of the replicas that signs this signature.
   185  type PartialSignature struct {
   186  	id      common.ID
   187  	pointg2 *bls12381.PointG2
   188  }
   189  
   190  // ID returns the id of signer.
   191  func (s *PartialSignature) ID() common.ID {
   192  	return s.id
   193  }
   194  
   195  // Verify verifys if the partial signature is valid for the message.
   196  func (s *PartialSignature) Verify(qr quorum, msg []byte) error {
   197  	pub, ok := qr.PublicKey(s.id)
   198  	if !ok {
   199  		return errPublicKeyNotFound
   200  	}
   201  	if !verify(pub.point, msg, s.pointg2) {
   202  		return errFailedVerification
   203  	}
   204  	return nil
   205  }
   206  
   207  // ToBytes marshals the partial signature to a byte slice.
   208  func (s *PartialSignature) ToBytes() ([]byte, error) {
   209  	buf := make([]byte, 4)
   210  	binary.LittleEndian.PutUint32(buf, s.id.Uint32())
   211  	return append(bls12381.NewG2().ToCompressed(s.pointg2), buf...), nil
   212  }
   213  
   214  // FromBytes unmarshals the partial signature from a byte slice.
   215  func (s *PartialSignature) FromBytes(data []byte) (err error) {
   216  	if len(data) != 2*BLSfpByteSize+4 {
   217  		return errBytesLength
   218  	}
   219  
   220  	s.id.SetUint32(binary.LittleEndian.Uint32(data[len(data)-4:]))
   221  	s.pointg2, err = bls12381.NewG2().FromCompressed(data[:2*BLSfpByteSize])
   222  	return
   223  }
   224  
   225  type PartialSignatureSet []*PartialSignature
   226  
   227  func (set PartialSignatureSet) Len() int { return len(set) }
   228  
   229  func (set PartialSignatureSet) Swap(i, j int) { set[i], set[j] = set[j], set[i] }
   230  
   231  func (set PartialSignatureSet) Less(i, j int) bool {
   232  	return set[i].ID().Less(set[j].ID())
   233  }
   234  
   235  // Combine aggregates some partial signatures into a single aggregate signature.
   236  func Combine(sigs ...*PartialSignature) (*AggregateSignature, error) {
   237  	points := make([]*bls12381.PointG2, 0, len(sigs))
   238  	bits := bitset.New(uint(len(sigs)))
   239  	for _, sig := range sigs {
   240  		points = append(points, sig.pointg2)
   241  		bits.Set(uint(sig.id.Uint32()))
   242  	}
   243  	return &AggregateSignature{pointg2: combine(points...), participants: bits}, nil
   244  }