package sigs import ( "context" "fmt" "github.com/filecoin-project/go-address" "github.com/filecoin-project/specs-actors/actors/crypto" "go.opencensus.io/trace" "golang.org/x/xerrors" "github.com/filecoin-project/lotus/chain/types" ) // Sign takes in signature type, private key and message. Returns a signature for that message. // Valid sigTypes are: "secp256k1" and "bls" func Sign(sigType crypto.SigType, privkey []byte, msg []byte) (*crypto.Signature, error) { sv, ok := sigs[sigType] if !ok { return nil, fmt.Errorf("cannot sign message with signature of unsupported type: %v", sigType) } sb, err := sv.Sign(privkey, msg) if err != nil { return nil, err } return &crypto.Signature{ Type: sigType, Data: sb, }, nil } // Verify verifies signatures func Verify(sig *crypto.Signature, addr address.Address, msg []byte) error { 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 { return fmt.Errorf("cannot verify signature of unsupported type: %v", sig.Type) } return sv.Verify(sig.Data, addr, msg) } // Generate generates private key of given type func Generate(sigType crypto.SigType) ([]byte, error) { sv, ok := sigs[sigType] if !ok { return nil, fmt.Errorf("cannot generate private key of unsupported type: %v", sigType) } return sv.GenPrivate() } // ToPublic converts private key to public key func ToPublic(sigType crypto.SigType, pk []byte) ([]byte, error) { sv, ok := sigs[sigType] if !ok { return nil, fmt.Errorf("cannot generate public key of unsupported type: %v", sigType) } return sv.ToPublic(pk) } func CheckBlockSignature(blk *types.BlockHeader, ctx context.Context, worker address.Address) error { _, span := trace.StartSpan(ctx, "checkBlockSignature") defer span.End() if blk.IsValidated() { return nil } 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) } err = Verify(blk.BlockSig, worker, sigb) if err == nil { blk.SetValidated() } return err } // 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 } var sigs map[crypto.SigType]SigShim // RegisterSig should be only used during init func RegisterSignature(typ crypto.SigType, vs SigShim) { if sigs == nil { sigs = make(map[crypto.SigType]SigShim) } sigs[typ] = vs }