From f6bda96d5a5d43212492757472d08bdf0019a4b3 Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 25 Feb 2020 13:35:41 -0800 Subject: [PATCH 1/2] Re: #1290: Add a lotus wallet sign CLI command - The command takes an address and a message (in hex) and prints out a signature of the msg --- cli/wallet.go | 42 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/cli/wallet.go b/cli/wallet.go index ad600eadf..40ab3a952 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -24,6 +24,7 @@ var walletCmd = &cli.Command{ walletImport, walletGetDefault, walletSetDefault, + walletSign, }, } @@ -235,3 +236,44 @@ var walletImport = &cli.Command{ return nil }, } + +var walletSign = &cli.Command{ + Name: "sign", + Usage: "sign a message", + ArgsUsage: " ", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if !cctx.Args().Present() || cctx.NArg() != 2 { + return fmt.Errorf("must specify signing address and message to sign") + } + + addr, err := address.NewFromString(cctx.Args().First()) + + if err != nil { + return err + } + + msg, err := hex.DecodeString(cctx.Args().Get(1)) + + if err != nil { + return err + } + + sig, err := api.WalletSign(ctx, addr, msg) + + if err != nil { + return err + } + + sigBytes := append([]byte{byte(sig.TypeCode())}, sig.Data...) + + fmt.Println(hex.EncodeToString(sigBytes)) + return nil + }, +} From fe8db295e761cf92d646ff7a5fc25b765d75c6bc Mon Sep 17 00:00:00 2001 From: Aayush Rajasekaran Date: Tue, 25 Feb 2020 15:17:15 -0800 Subject: [PATCH 2/2] Re: #1290: Add a lotus wallet verify API and CLI command - The command takes an address, message, and signature, and returns true if the sig is valid --- api/api_full.go | 1 + api/apistruct/struct.go | 5 ++++ cli/cmd.go | 14 +++++++++++ cli/wallet.go | 51 ++++++++++++++++++++++++++++++++++++++++ cmd/lotus/main.go | 7 +++++- node/impl/full/wallet.go | 5 ++++ 6 files changed, 82 insertions(+), 1 deletion(-) diff --git a/api/api_full.go b/api/api_full.go index ee2628806..3bb1b6ccf 100644 --- a/api/api_full.go +++ b/api/api_full.go @@ -71,6 +71,7 @@ type FullNode interface { WalletBalance(context.Context, address.Address) (types.BigInt, error) WalletSign(context.Context, address.Address, []byte) (*types.Signature, error) WalletSignMessage(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) + WalletVerify(context.Context, address.Address, []byte, *types.Signature) bool WalletDefaultAddress(context.Context) (address.Address, error) WalletSetDefault(context.Context, address.Address) error WalletExport(context.Context, address.Address) (*types.KeyInfo, error) diff --git a/api/apistruct/struct.go b/api/apistruct/struct.go index 52b862be9..e51b5f577 100644 --- a/api/apistruct/struct.go +++ b/api/apistruct/struct.go @@ -83,6 +83,7 @@ type FullNodeStruct struct { WalletBalance func(context.Context, address.Address) (types.BigInt, error) `perm:"read"` WalletSign func(context.Context, address.Address, []byte) (*types.Signature, error) `perm:"sign"` WalletSignMessage func(context.Context, address.Address, *types.Message) (*types.SignedMessage, error) `perm:"sign"` + WalletVerify func(context.Context, address.Address, []byte, *types.Signature) bool `perm:"read"` WalletDefaultAddress func(context.Context) (address.Address, error) `perm:"write"` WalletSetDefault func(context.Context, address.Address) error `perm:"admin"` WalletExport func(context.Context, address.Address) (*types.KeyInfo, error) `perm:"admin"` @@ -311,6 +312,10 @@ func (c *FullNodeStruct) WalletSignMessage(ctx context.Context, k address.Addres return c.Internal.WalletSignMessage(ctx, k, msg) } +func (c *FullNodeStruct) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *types.Signature) bool { + return c.Internal.WalletVerify(ctx, k, msg, sig) +} + func (c *FullNodeStruct) WalletDefaultAddress(ctx context.Context) (address.Address, error) { return c.Internal.WalletDefaultAddress(ctx) } diff --git a/cli/cmd.go b/cli/cmd.go index f8eefe208..ac3811d0f 100644 --- a/cli/cmd.go +++ b/cli/cmd.go @@ -28,6 +28,20 @@ const ( metadataTraceConetxt = "traceContext" ) +// custom CLI error + +type ErrCmdFailed struct { + msg string +} + +func (e *ErrCmdFailed) Error() string { + return e.msg +} + +func NewCliError(s string) error { + return &ErrCmdFailed{s} +} + // ApiConnector returns API instance type ApiConnector func() api.FullNode diff --git a/cli/wallet.go b/cli/wallet.go index 40ab3a952..dab804af8 100644 --- a/cli/wallet.go +++ b/cli/wallet.go @@ -25,6 +25,7 @@ var walletCmd = &cli.Command{ walletGetDefault, walletSetDefault, walletSign, + walletVerify, }, } @@ -277,3 +278,53 @@ var walletSign = &cli.Command{ return nil }, } + +var walletVerify = &cli.Command{ + Name: "verify", + Usage: "verify the signature of a message", + ArgsUsage: " ", + Action: func(cctx *cli.Context) error { + api, closer, err := GetFullNodeAPI(cctx) + if err != nil { + return err + } + defer closer() + ctx := ReqContext(cctx) + + if !cctx.Args().Present() || cctx.NArg() != 3 { + return fmt.Errorf("must specify signing address, message, and signature to verify") + } + + addr, err := address.NewFromString(cctx.Args().First()) + + if err != nil { + return err + } + + msg, err := hex.DecodeString(cctx.Args().Get(1)) + + if err != nil { + return err + } + + sigBytes, err := hex.DecodeString(cctx.Args().Get(2)) + + if err != nil { + return err + } + + sig, err := types.SignatureFromBytes(sigBytes) + + if err != nil { + return err + } + + if api.WalletVerify(ctx, addr, msg, &sig) { + fmt.Println("valid") + return nil + } else { + fmt.Println("invalid") + return NewCliError("CLI Verify called with invalid signature") + } + }, +} diff --git a/cmd/lotus/main.go b/cmd/lotus/main.go index e040d397e..6eeec7509 100644 --- a/cmd/lotus/main.go +++ b/cmd/lotus/main.go @@ -73,7 +73,12 @@ func main() { Code: trace.StatusCodeFailedPrecondition, Message: err.Error(), }) - log.Warnf("%+v", err) + _, ok := err.(*lcli.ErrCmdFailed) + if ok { + log.Debugf("%+v", err) + } else { + log.Warnf("%+v", err) + } os.Exit(1) } } diff --git a/node/impl/full/wallet.go b/node/impl/full/wallet.go index b30a55f38..ad5fe876c 100644 --- a/node/impl/full/wallet.go +++ b/node/impl/full/wallet.go @@ -2,6 +2,7 @@ package full import ( "context" + "github.com/filecoin-project/lotus/lib/sigs" "github.com/filecoin-project/go-address" "github.com/filecoin-project/lotus/chain/stmgr" @@ -53,6 +54,10 @@ func (a *WalletAPI) WalletSignMessage(ctx context.Context, k address.Address, ms }, nil } +func (a *WalletAPI) WalletVerify(ctx context.Context, k address.Address, msg []byte, sig *types.Signature) bool { + return sigs.Verify(sig, k, msg) == nil +} + func (a *WalletAPI) WalletDefaultAddress(ctx context.Context) (address.Address, error) { return a.Wallet.GetDefault() }