Integrate blst signature library: https://github.com/supranational/blst

This commit is contained in:
Simon Peffers 2020-07-25 21:38:18 -04:00
parent c459a13dca
commit 0f3105a01f
6 changed files with 60 additions and 47 deletions

View File

@ -3,7 +3,6 @@ package gen
import (
"context"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid"
@ -17,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet"
"github.com/filecoin-project/lotus/lib/sigs/bls"
)
func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wallet, bt *api.BlockTemplate) (*types.FullBlock, error) {
@ -142,28 +142,27 @@ func MinerCreateBlock(ctx context.Context, sm *stmgr.StateManager, w *wallet.Wal
}
func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
var blsSigs []bls.Signature
for _, s := range sigs {
var bsig bls.Signature
copy(bsig[:], s.Data)
blsSigs = append(blsSigs, bsig)
sigsS := make([][]byte, len(sigs))
for i := 0; i < len(sigs); i++ {
sigsS[i] = sigs[i].Data
}
aggSig := bls.Aggregate(blsSigs)
if aggSig == nil {
aggregator := new(bls.AggregateSignature).AggregateCompressed(sigsS)
if aggregator == nil {
if len(sigs) > 0 {
return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs))
}
// Note: for blst this condition should not happen - nil should not be returned
return &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: new(bls.Signature)[:],
Data: new(bls.Signature).Compress(),
}, nil
}
aggSig := aggregator.ToAffine().Compress()
return &crypto.Signature{
Type: crypto.SigTypeBLS,
Data: aggSig[:],
Data: aggSig,
}, nil
}

View File

@ -23,7 +23,6 @@ import (
cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore"
@ -433,7 +432,7 @@ func (sm *StateManager) ResolveToKeyAddress(ctx context.Context, addr address.Ad
return vm.ResolveToKeyAddr(tree, cst, addr)
}
func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk bls.PublicKey, err error) {
func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Address, ts *types.TipSet) (pubk []byte, err error) {
kaddr, err := sm.ResolveToKeyAddress(ctx, addr, ts)
if err != nil {
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err)
@ -443,8 +442,7 @@ func (sm *StateManager) GetBlsPublicKey(ctx context.Context, addr address.Addres
return pubk, xerrors.Errorf("address must be BLS address to load bls public key")
}
copy(pubk[:], kaddr.Payload())
return pubk, nil
return kaddr.Payload(), nil
}
func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) {

View File

@ -25,7 +25,7 @@ import (
"go.opencensus.io/trace"
"golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi"
blst "github.com/supranational/blst/bindings/go"
"github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/sector-storage/ffiwrapper"
@ -46,6 +46,7 @@ import (
"github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/lib/sigs/bls"
"github.com/filecoin-project/lotus/metrics"
)
@ -915,7 +916,7 @@ func (syncer *Syncer) VerifyWinningPoStProof(ctx context.Context, h *types.Block
func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock, baseTs *types.TipSet) error {
{
var sigCids []cid.Cid // this is what we get for people not wanting the marshalcbor method on the cid type
var pubks []bls.PublicKey
var pubks [][]byte
for _, m := range b.BlsMessages {
sigCids = append(sigCids, m.Cid())
@ -1036,24 +1037,28 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil
}
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks []bls.PublicKey) error {
func (syncer *Syncer) verifyBlsAggregate(ctx context.Context, sig *crypto.Signature, msgs []cid.Cid, pubks [][]byte) error {
_, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
defer span.End()
span.AddAttributes(
trace.Int64Attribute("msgCount", int64(len(msgs))),
)
bmsgs := make([]bls.Message, len(msgs))
for i, m := range msgs {
bmsgs[i] = m.Bytes()
msgsS := make([]blst.Message, len(msgs))
for i := 0; i < len(msgs); i++ {
msgsS[i] = msgs[i].Bytes()
}
var bsig bls.Signature
copy(bsig[:], sig.Data)
if !bls.HashVerify(&bsig, bmsgs, pubks) {
// TODO: empty aggregates are considered valid?
if len(msgs) == 0 {
return nil
}
valid := new(bls.Signature).AggregateVerifyCompressed(sig.Data, pubks,
msgsS, []byte(bls.DST))
if !valid {
return xerrors.New("bls aggregate signature failed to verify")
}
return nil
}

1
go.mod
View File

@ -106,6 +106,7 @@ require (
github.com/opentracing/opentracing-go v1.1.0
github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.6.1
github.com/supranational/blst v0.1.1
github.com/syndtr/goleveldb v1.0.0
github.com/urfave/cli/v2 v2.2.0
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba

4
go.sum
View File

@ -1316,6 +1316,10 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/supranational/blst v0.1.0 h1:2LzeBbOidhTD87UezqGvIffWZAd3FOCfhi2b7IbJCMc=
github.com/supranational/blst v0.1.0/go.mod h1:Z70pOaiBHpXP+JFNOwIyCHKjec/He56CC5UdLaYpuzY=
github.com/supranational/blst v0.1.1 h1:GsK4oq7QZ7yfHI6dCh2NQsUe4imjlFwm5NXF5PWAWoo=
github.com/supranational/blst v0.1.1/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw=
github.com/syndtr/goleveldb v1.0.0 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=

View File

@ -1,51 +1,57 @@
package bls
import (
"crypto/rand"
"fmt"
"github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto"
ffi "github.com/filecoin-project/filecoin-ffi"
blst "github.com/supranational/blst/bindings/go"
"github.com/filecoin-project/lotus/lib/sigs"
)
const DST = string("BLS_SIG_BLS12381G2_XMD:SHA-256_SSWU_RO_NUL_")
type SecretKey = blst.SecretKey
type PublicKey = blst.P1Affine
type Signature = blst.P2Affine
type AggregateSignature = blst.P2Aggregate
type blsSigner struct{}
func (blsSigner) GenPrivate() ([]byte, error) {
pk := ffi.PrivateKeyGenerate()
return pk[:], nil
// Generate 32 bytes of randomness
var ikm [32]byte
_, err := rand.Read(ikm[:])
if err != nil {
return nil, fmt.Errorf("bls signature error generating random data")
}
pk := blst.KeyGen(ikm[:]).Serialize()
return pk, nil
}
func (blsSigner) ToPublic(priv []byte) ([]byte, error) {
var pk ffi.PrivateKey
copy(pk[:], priv)
pub := ffi.PrivateKeyPublicKey(pk)
return pub[:], nil
pk := new(SecretKey).Deserialize(priv)
if pk == nil {
return nil, fmt.Errorf("bls signature invalid private key")
}
return new(PublicKey).From(pk).Compress(), nil
}
func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) {
var pk ffi.PrivateKey
copy(pk[:], p)
sig := ffi.PrivateKeySign(pk, msg)
return sig[:], nil
pk := new(SecretKey).Deserialize(p)
if pk == nil {
return nil, fmt.Errorf("bls signature invalid private key")
}
return new(Signature).Sign(pk, msg, []byte(DST)).Compress(), nil
}
func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error {
var pubk ffi.PublicKey
copy(pubk[:], a.Payload())
pubkeys := []ffi.PublicKey{pubk}
digests := []ffi.Message{msg}
var s ffi.Signature
copy(s[:], sig)
if !ffi.HashVerify(&s, digests, pubkeys) {
if !new(Signature).VerifyCompressed(sig, a.Payload()[:], msg, []byte(DST)) {
return fmt.Errorf("bls signature failed to verify")
}
return nil
}