2020-01-30 23:48:25 +00:00
|
|
|
package sigs
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
|
|
|
|
"github.com/filecoin-project/go-address"
|
2020-09-07 03:49:10 +00:00
|
|
|
"github.com/filecoin-project/go-state-types/crypto"
|
2020-01-30 23:48:25 +00:00
|
|
|
"go.opencensus.io/trace"
|
|
|
|
"golang.org/x/xerrors"
|
2020-02-14 14:14:39 +00:00
|
|
|
|
|
|
|
"github.com/filecoin-project/lotus/chain/types"
|
2020-01-30 23:48:25 +00:00
|
|
|
)
|
|
|
|
|
2020-02-04 06:24:25 +00:00
|
|
|
// Sign takes in signature type, private key and message. Returns a signature for that message.
|
|
|
|
// Valid sigTypes are: "secp256k1" and "bls"
|
2020-02-12 23:52:36 +00:00
|
|
|
func Sign(sigType crypto.SigType, privkey []byte, msg []byte) (*crypto.Signature, error) {
|
2020-01-30 23:48:25 +00:00
|
|
|
sv, ok := sigs[sigType]
|
|
|
|
if !ok {
|
2020-02-21 19:28:01 +00:00
|
|
|
return nil, fmt.Errorf("cannot sign message with signature of unsupported type: %v", sigType)
|
2020-01-30 23:48:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
sb, err := sv.Sign(privkey, msg)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
2020-02-12 23:52:36 +00:00
|
|
|
return &crypto.Signature{
|
2020-01-30 23:48:25 +00:00
|
|
|
Type: sigType,
|
|
|
|
Data: sb,
|
|
|
|
}, nil
|
|
|
|
}
|
|
|
|
|
2020-02-04 06:24:25 +00:00
|
|
|
// Verify verifies signatures
|
2020-02-12 23:52:36 +00:00
|
|
|
func Verify(sig *crypto.Signature, addr address.Address, msg []byte) error {
|
2020-01-30 23:48:25 +00:00
|
|
|
if sig == nil {
|
|
|
|
return xerrors.Errorf("signature is nil")
|
|
|
|
}
|
|
|
|
|
|
|
|
if addr.Protocol() == address.ID {
|
|
|
|
return fmt.Errorf("must resolve ID addresses before using them to verify a signature")
|
|
|
|
}
|
|
|
|
|
|
|
|
sv, ok := sigs[sig.Type]
|
|
|
|
if !ok {
|
2020-02-21 19:28:01 +00:00
|
|
|
return fmt.Errorf("cannot verify signature of unsupported type: %v", sig.Type)
|
2020-01-30 23:48:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sv.Verify(sig.Data, addr, msg)
|
|
|
|
}
|
|
|
|
|
2020-02-04 06:24:25 +00:00
|
|
|
// Generate generates private key of given type
|
2020-02-12 23:52:36 +00:00
|
|
|
func Generate(sigType crypto.SigType) ([]byte, error) {
|
2020-01-30 23:48:25 +00:00
|
|
|
sv, ok := sigs[sigType]
|
|
|
|
if !ok {
|
2020-02-21 19:28:01 +00:00
|
|
|
return nil, fmt.Errorf("cannot generate private key of unsupported type: %v", sigType)
|
2020-01-30 23:48:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sv.GenPrivate()
|
|
|
|
}
|
|
|
|
|
2020-02-04 06:24:25 +00:00
|
|
|
// ToPublic converts private key to public key
|
2020-02-12 23:52:36 +00:00
|
|
|
func ToPublic(sigType crypto.SigType, pk []byte) ([]byte, error) {
|
2020-01-30 23:48:25 +00:00
|
|
|
sv, ok := sigs[sigType]
|
|
|
|
if !ok {
|
2020-02-21 19:28:01 +00:00
|
|
|
return nil, fmt.Errorf("cannot generate public key of unsupported type: %v", sigType)
|
2020-01-30 23:48:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
return sv.ToPublic(pk)
|
|
|
|
}
|
|
|
|
|
2020-06-02 14:29:39 +00:00
|
|
|
func CheckBlockSignature(ctx context.Context, blk *types.BlockHeader, worker address.Address) error {
|
2020-01-30 23:48:25 +00:00
|
|
|
_, span := trace.StartSpan(ctx, "checkBlockSignature")
|
|
|
|
defer span.End()
|
|
|
|
|
2020-05-14 16:41:10 +00:00
|
|
|
if blk.IsValidated() {
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
2020-01-30 23:48:25 +00:00
|
|
|
if blk.BlockSig == nil {
|
|
|
|
return xerrors.New("block signature not present")
|
|
|
|
}
|
|
|
|
|
|
|
|
sigb, err := blk.SigningBytes()
|
|
|
|
if err != nil {
|
|
|
|
return xerrors.Errorf("failed to get block signing bytes: %w", err)
|
|
|
|
}
|
|
|
|
|
2020-05-14 16:41:10 +00:00
|
|
|
err = Verify(blk.BlockSig, worker, sigb)
|
|
|
|
if err == nil {
|
|
|
|
blk.SetValidated()
|
|
|
|
}
|
|
|
|
|
|
|
|
return err
|
2020-02-04 06:24:25 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
// SigShim is used for introducing signature functions
|
|
|
|
type SigShim interface {
|
|
|
|
GenPrivate() ([]byte, error)
|
|
|
|
ToPublic(pk []byte) ([]byte, error)
|
|
|
|
Sign(pk []byte, msg []byte) ([]byte, error)
|
|
|
|
Verify(sig []byte, a address.Address, msg []byte) error
|
|
|
|
}
|
|
|
|
|
2020-02-12 23:52:36 +00:00
|
|
|
var sigs map[crypto.SigType]SigShim
|
2020-02-04 06:24:25 +00:00
|
|
|
|
2020-06-02 14:29:39 +00:00
|
|
|
// RegisterSignature should be only used during init
|
2020-02-12 23:52:36 +00:00
|
|
|
func RegisterSignature(typ crypto.SigType, vs SigShim) {
|
2020-02-04 06:24:25 +00:00
|
|
|
if sigs == nil {
|
2020-02-12 23:52:36 +00:00
|
|
|
sigs = make(map[crypto.SigType]SigShim)
|
2020-02-04 06:24:25 +00:00
|
|
|
}
|
2020-02-12 23:52:36 +00:00
|
|
|
sigs[typ] = vs
|
2020-01-30 23:48:25 +00:00
|
|
|
}
|