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 ( import (
"context" "context"
bls "github.com/filecoin-project/filecoin-ffi"
amt "github.com/filecoin-project/go-amt-ipld/v2" amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/specs-actors/actors/crypto" "github.com/filecoin-project/specs-actors/actors/crypto"
cid "github.com/ipfs/go-cid" cid "github.com/ipfs/go-cid"
@ -17,6 +16,7 @@ import (
"github.com/filecoin-project/lotus/chain/types" "github.com/filecoin-project/lotus/chain/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/chain/wallet" "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) { 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) { func aggregateSignatures(sigs []crypto.Signature) (*crypto.Signature, error) {
var blsSigs []bls.Signature sigsS := make([][]byte, len(sigs))
for _, s := range sigs { for i := 0; i < len(sigs); i++ {
var bsig bls.Signature sigsS[i] = sigs[i].Data
copy(bsig[:], s.Data)
blsSigs = append(blsSigs, bsig)
} }
aggSig := bls.Aggregate(blsSigs) aggregator := new(bls.AggregateSignature).AggregateCompressed(sigsS)
if aggSig == nil { if aggregator == nil {
if len(sigs) > 0 { if len(sigs) > 0 {
return nil, xerrors.Errorf("bls.Aggregate returned nil with %d signatures", len(sigs)) 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{ return &crypto.Signature{
Type: crypto.SigTypeBLS, Type: crypto.SigTypeBLS,
Data: new(bls.Signature)[:], Data: new(bls.Signature).Compress(),
}, nil }, nil
} }
aggSig := aggregator.ToAffine().Compress()
return &crypto.Signature{ return &crypto.Signature{
Type: crypto.SigTypeBLS, Type: crypto.SigTypeBLS,
Data: aggSig[:], Data: aggSig,
}, nil }, nil
} }

View File

@ -23,7 +23,6 @@ import (
cbg "github.com/whyrusleeping/cbor-gen" cbg "github.com/whyrusleeping/cbor-gen"
"golang.org/x/xerrors" "golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi"
"github.com/ipfs/go-cid" "github.com/ipfs/go-cid"
hamt "github.com/ipfs/go-hamt-ipld" hamt "github.com/ipfs/go-hamt-ipld"
blockstore "github.com/ipfs/go-ipfs-blockstore" 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) 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) kaddr, err := sm.ResolveToKeyAddress(ctx, addr, ts)
if err != nil { if err != nil {
return pubk, xerrors.Errorf("failed to resolve address to key address: %w", err) 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") return pubk, xerrors.Errorf("address must be BLS address to load bls public key")
} }
copy(pubk[:], kaddr.Payload()) return kaddr.Payload(), nil
return pubk, nil
} }
func (sm *StateManager) LookupID(ctx context.Context, addr address.Address, ts *types.TipSet) (address.Address, error) { 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" "go.opencensus.io/trace"
"golang.org/x/xerrors" "golang.org/x/xerrors"
bls "github.com/filecoin-project/filecoin-ffi" blst "github.com/supranational/blst/bindings/go"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
amt "github.com/filecoin-project/go-amt-ipld/v2" amt "github.com/filecoin-project/go-amt-ipld/v2"
"github.com/filecoin-project/sector-storage/ffiwrapper" "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/types"
"github.com/filecoin-project/lotus/chain/vm" "github.com/filecoin-project/lotus/chain/vm"
"github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/lotus/lib/sigs"
"github.com/filecoin-project/lotus/lib/sigs/bls"
"github.com/filecoin-project/lotus/metrics" "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 { 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 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 { for _, m := range b.BlsMessages {
sigCids = append(sigCids, m.Cid()) sigCids = append(sigCids, m.Cid())
@ -1036,24 +1037,28 @@ func (syncer *Syncer) checkBlockMessages(ctx context.Context, b *types.FullBlock
return nil 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") _, span := trace.StartSpan(ctx, "syncer.verifyBlsAggregate")
defer span.End() defer span.End()
span.AddAttributes( span.AddAttributes(
trace.Int64Attribute("msgCount", int64(len(msgs))), trace.Int64Attribute("msgCount", int64(len(msgs))),
) )
bmsgs := make([]bls.Message, len(msgs)) msgsS := make([]blst.Message, len(msgs))
for i, m := range msgs { for i := 0; i < len(msgs); i++ {
bmsgs[i] = m.Bytes() msgsS[i] = msgs[i].Bytes()
} }
var bsig bls.Signature // TODO: empty aggregates are considered valid?
copy(bsig[:], sig.Data) if len(msgs) == 0 {
if !bls.HashVerify(&bsig, bmsgs, pubks) { 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 xerrors.New("bls aggregate signature failed to verify")
} }
return nil return nil
} }

1
go.mod
View File

@ -106,6 +106,7 @@ require (
github.com/opentracing/opentracing-go v1.1.0 github.com/opentracing/opentracing-go v1.1.0
github.com/stretchr/objx v0.2.0 // indirect github.com/stretchr/objx v0.2.0 // indirect
github.com/stretchr/testify v1.6.1 github.com/stretchr/testify v1.6.1
github.com/supranational/blst v0.1.1
github.com/syndtr/goleveldb v1.0.0 github.com/syndtr/goleveldb v1.0.0
github.com/urfave/cli/v2 v2.2.0 github.com/urfave/cli/v2 v2.2.0
github.com/whyrusleeping/bencher v0.0.0-20190829221104-bb6607aa8bba 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.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.6.1 h1:hDPOHmpOpP40lSULcqw7IrRb/u7w6RpDC9399XyoNd0= 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/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 h1:fBdIW9lB4Iz0n9khmH8w27SJ3QEJ7+IgjPEwGSZiFdE=
github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ= github.com/syndtr/goleveldb v1.0.0/go.mod h1:ZVVdQEZoIme9iO1Ch2Jdy24qqXrMMOU6lpPAyBWyWuQ=
github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA= github.com/tarm/serial v0.0.0-20180830185346-98f6abe2eb07/go.mod h1:kDXzergiv9cbyO7IOYJZWg1U88JhDg3PB6klq9Hg2pA=

View File

@ -1,51 +1,57 @@
package bls package bls
import ( import (
"crypto/rand"
"fmt" "fmt"
"github.com/filecoin-project/go-address" "github.com/filecoin-project/go-address"
"github.com/filecoin-project/specs-actors/actors/crypto" "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" "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{} type blsSigner struct{}
func (blsSigner) GenPrivate() ([]byte, error) { func (blsSigner) GenPrivate() ([]byte, error) {
pk := ffi.PrivateKeyGenerate() // Generate 32 bytes of randomness
return pk[:], nil 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) { func (blsSigner) ToPublic(priv []byte) ([]byte, error) {
var pk ffi.PrivateKey pk := new(SecretKey).Deserialize(priv)
copy(pk[:], priv) if pk == nil {
pub := ffi.PrivateKeyPublicKey(pk) return nil, fmt.Errorf("bls signature invalid private key")
return pub[:], nil }
return new(PublicKey).From(pk).Compress(), nil
} }
func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) { func (blsSigner) Sign(p []byte, msg []byte) ([]byte, error) {
var pk ffi.PrivateKey pk := new(SecretKey).Deserialize(p)
copy(pk[:], p) if pk == nil {
sig := ffi.PrivateKeySign(pk, msg) return nil, fmt.Errorf("bls signature invalid private key")
return sig[:], nil }
return new(Signature).Sign(pk, msg, []byte(DST)).Compress(), nil
} }
func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error { func (blsSigner) Verify(sig []byte, a address.Address, msg []byte) error {
if !new(Signature).VerifyCompressed(sig, a.Payload()[:], msg, []byte(DST)) {
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) {
return fmt.Errorf("bls signature failed to verify") return fmt.Errorf("bls signature failed to verify")
} }
return nil return nil
} }