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 }