From 40c64f74e61af8765d4ad1b5cf6a2d83a7f41203 Mon Sep 17 00:00:00 2001 From: Madhur Shrimal Date: Mon, 30 Jan 2023 11:58:09 -0800 Subject: [PATCH 1/3] add verify and readme --- README.md | 3 ++ cmd/README.md | 33 +++++++++++++++ cmd/{sign.go => key_sign.go} | 29 +++++++++----- cmd/key_verify.go | 69 ++++++++++++++++++++++++++++++++ cmd/root.go | 7 +++- configuration/types.go | 1 + examples/configuration/sign.json | 8 +++- 7 files changed, 136 insertions(+), 14 deletions(-) create mode 100644 cmd/README.md rename cmd/{sign.go => key_sign.go} (69%) create mode 100644 cmd/key_verify.go diff --git a/README.md b/README.md index 3451937d..01c2d69c 100644 --- a/README.md +++ b/README.md @@ -46,6 +46,9 @@ Example: To validate that the Data API implementation is correct, running the fo docker run -v "$(pwd):/data" -it [image-name] check:data --configuration-file /data/config.json ``` +## Key Sign Tool +Rosetta CLI comes with a handy key sign tool for local testing. Please refer to this [README](./cmd/README.md) on how to use it. + ## Updates and Releases We recommend that you continually update your installation to the latest release as soon as possible. The latest release notes are available in our [Community](https://community.rosetta-api.org) board under the [Release](https://community.rosetta-api.org/c/releases/13) category. diff --git a/cmd/README.md b/cmd/README.md new file mode 100644 index 00000000..877032f7 --- /dev/null +++ b/cmd/README.md @@ -0,0 +1,33 @@ +## Key Sign Tool + +Rosetta CLI has a key sign tool, which you can use to sign and verify various curves supported +by rosetta-specifications. This should only be used for local development. Never share private keys anywhere. + +### Usage +#### Sign +``` +rosetta-cli key:sign --configuration-file config.json +``` + +A sample config file is located [here](../examples/configuration/sign.json) + +Required fields includes +- `pub_key` +- `private_key` +- `signing_payload` + + +#### Verify +``` +rosetta-cli key:verify --configuration-file config.json +``` +A sample config file is located [here](../examples/configuration/sign.json) + +Required fields includes +- `pub_key` +- `signing_payload` +- `signature` + + +### Troubleshoot +- `account_identifier` field in `signing_payload` field should've a dummy address for providing valid payload. \ No newline at end of file diff --git a/cmd/sign.go b/cmd/key_sign.go similarity index 69% rename from cmd/sign.go rename to cmd/key_sign.go index 4bb7cd85..41a114fa 100644 --- a/cmd/sign.go +++ b/cmd/key_sign.go @@ -17,7 +17,6 @@ package cmd import ( "encoding/hex" "errors" - "fmt" "github.com/coinbase/rosetta-sdk-go/keys" "github.com/fatih/color" @@ -25,35 +24,43 @@ import ( ) var ( - signCmd = &cobra.Command{ - Use: "sign", + keySignCmd = &cobra.Command{ + Use: "key:sign", Short: "Sign an unsigned payload with given private key", Long: `Sign an unsigned payload with given private key - It supports Keypair specified by https://github.com/coinbase/rosetta-specifications`, - RunE: runSignCmd, + It supports Keypair specified by https://github.com/coinbase/rosetta-specifications + Please provide valid PrivateKey, CurveType, SignaturePayload`, + RunE: runKeySignCmd, } ) -func runSignCmd(_ *cobra.Command, _ []string) error { +func runKeySignCmd(_ *cobra.Command, _ []string) error { if Config.Sign == nil { return errors.New("sign configuration is missing") } + if len(Config.Sign.PrivateKey) == 0 || + Config.Sign.PubKey.CurveType == "" || + Config.Sign.SigningPayload == nil || + Config.Sign.SigningPayload.SignatureType == "" { + color.Red("invalid sign input") + } + keyPair, err := keys.ImportPrivateKey(Config.Sign.PrivateKey, Config.Sign.PubKey.CurveType) if err != nil { - fmt.Println(fmt.Errorf("unable to import private keys %#v", err)) + color.Red("unable to import private keys %#v", err) return err } err = keyPair.IsValid() if err != nil { - fmt.Println(fmt.Errorf("keypair invalid with err %#v", err)) + color.Red("keypair invalid with err %#v", err) return err } signer, err := keyPair.Signer() if err != nil { - fmt.Println(fmt.Errorf("signer invalid with err %#v", err)) + color.Red("signer invalid with err %#v", err) return err } @@ -62,11 +69,11 @@ func runSignCmd(_ *cobra.Command, _ []string) error { sign, err := signer.Sign(signingPayload, signatureType) if err != nil { - fmt.Println(fmt.Errorf("unable to sign with err %#v", err)) + color.Red("unable to sign with err %#v", err) return err } hexSig := hex.EncodeToString(sign.Bytes) - color.Blue(hexSig) + color.Green("Signature: %s", hexSig) return nil } diff --git a/cmd/key_verify.go b/cmd/key_verify.go new file mode 100644 index 00000000..838228fd --- /dev/null +++ b/cmd/key_verify.go @@ -0,0 +1,69 @@ +// Copyright 2023 Coinbase, Inc. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "errors" + "github.com/coinbase/rosetta-sdk-go/keys" + "github.com/fatih/color" + "github.com/spf13/cobra" +) + +var ( + keyVerifyCmd = &cobra.Command{ + Use: "key:verify", + Short: "Verify the signature using the public key", + Long: `Verify the signature using the public key + It supports Keypair specified by https://github.com/coinbase/rosetta-specifications`, + RunE: runKeyVerifyCmd, + } +) + +func runKeyVerifyCmd(_ *cobra.Command, _ []string) error { + if Config.Sign == nil { + return errors.New("sign configuration is missing") + } + + if len(Config.Sign.Signature.Bytes) == 0 || + Config.Sign.SigningPayload == nil || + Config.Sign.SigningPayload.SignatureType == "" || + Config.Sign.PubKey == nil { + color.Red("invalid verify input") + } + + keyPair := keys.KeyPair{ + PublicKey: Config.Sign.PubKey, + } + + signer, err := keyPair.Signer() + if err != nil { + color.Red("signer invalid with err %#v", err) + return err + } + + signature := Config.Sign.Signature + signature.SignatureType = Config.Sign.SigningPayload.SignatureType + signature.SigningPayload = Config.Sign.SigningPayload + signature.PublicKey = Config.Sign.PubKey + + err = signer.Verify(signature) + if err != nil { + color.Red("invalid signature with err %#v", err) + return err + } + + color.Green("Signature Verified.") + return nil +} diff --git a/cmd/root.go b/cmd/root.go index 92bb8b2e..40b930eb 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -376,8 +376,11 @@ default values.`, ) rootCmd.AddCommand(checkSpecCmd) - // Sign command - rootCmd.AddCommand(signCmd) + // Key Sign command + rootCmd.AddCommand(keySignCmd) + + // Key Verify command + rootCmd.AddCommand(keyVerifyCmd) } func initConfig() { diff --git a/configuration/types.go b/configuration/types.go index 8ad3a8f7..02f05956 100644 --- a/configuration/types.go +++ b/configuration/types.go @@ -482,6 +482,7 @@ type SignConfiguration struct { PubKey *types.PublicKey `json:"pub_key"` PrivateKey string `json:"private_key"` SigningPayload *types.SigningPayload `json:"signing_payload"` + Signature *types.Signature `json:"signature,omitempty"` } // CheckPerfConfiguration configuration for check perf diff --git a/examples/configuration/sign.json b/examples/configuration/sign.json index c79d1f87..f3c371e9 100644 --- a/examples/configuration/sign.json +++ b/examples/configuration/sign.json @@ -7,7 +7,13 @@ "private_key": "", "signing_payload": { "hex_bytes": "370e74254e8cbaa343af3564901456082ec7af967e45ff24ba061233b1a1b04f", - "signature_type": "ecdsa" + "signature_type": "ecdsa", + "account_identifier": { + "address": "dummy" + } + }, + "signature": { + "hex_bytes": "c80547470b7e4d3fc17c988b2244dfebc909b3e9f7fd0c1387763263cc70d16d24f326b9c12ba2ea278164c0b30f128a809585fc503eda43de429aadb9f893ef" } } } \ No newline at end of file From fc40cb271a065cb339d4a9d18bed547aec101831 Mon Sep 17 00:00:00 2001 From: Madhur Shrimal Date: Mon, 30 Jan 2023 11:59:01 -0800 Subject: [PATCH 2/3] format --- configuration/types.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configuration/types.go b/configuration/types.go index 02f05956..f8b2da48 100644 --- a/configuration/types.go +++ b/configuration/types.go @@ -482,7 +482,7 @@ type SignConfiguration struct { PubKey *types.PublicKey `json:"pub_key"` PrivateKey string `json:"private_key"` SigningPayload *types.SigningPayload `json:"signing_payload"` - Signature *types.Signature `json:"signature,omitempty"` + Signature *types.Signature `json:"signature,omitempty"` } // CheckPerfConfiguration configuration for check perf From 96fee30132e974cf75914e8786fd4e47798e0c22 Mon Sep 17 00:00:00 2001 From: Madhur Shrimal Date: Mon, 30 Jan 2023 12:30:57 -0800 Subject: [PATCH 3/3] verifu json example --- cmd/README.md | 4 ++-- examples/configuration/sign.json | 3 --- examples/configuration/verify.json | 18 ++++++++++++++++++ 3 files changed, 20 insertions(+), 5 deletions(-) create mode 100644 examples/configuration/verify.json diff --git a/cmd/README.md b/cmd/README.md index 877032f7..01297daf 100644 --- a/cmd/README.md +++ b/cmd/README.md @@ -19,9 +19,9 @@ Required fields includes #### Verify ``` -rosetta-cli key:verify --configuration-file config.json +rosetta-cli key:verify --configuration-file verify.json ``` -A sample config file is located [here](../examples/configuration/sign.json) +A sample config file is located [here](../examples/configuration/verify.json) Required fields includes - `pub_key` diff --git a/examples/configuration/sign.json b/examples/configuration/sign.json index f3c371e9..def4ebbe 100644 --- a/examples/configuration/sign.json +++ b/examples/configuration/sign.json @@ -11,9 +11,6 @@ "account_identifier": { "address": "dummy" } - }, - "signature": { - "hex_bytes": "c80547470b7e4d3fc17c988b2244dfebc909b3e9f7fd0c1387763263cc70d16d24f326b9c12ba2ea278164c0b30f128a809585fc503eda43de429aadb9f893ef" } } } \ No newline at end of file diff --git a/examples/configuration/verify.json b/examples/configuration/verify.json new file mode 100644 index 00000000..9554d13c --- /dev/null +++ b/examples/configuration/verify.json @@ -0,0 +1,18 @@ +{ + "sign": { + "pub_key": { + "curve_type": "secp256k1", + "hex_bytes": "03c7e625aa08cad8f257d9ee2b9b7a0214f19f981afd5b498c728ad7ed6c0c3df6" + }, + "signing_payload": { + "hex_bytes": "370e74254e8cbaa343af3564901456082ec7af967e45ff24ba061233b1a1b04f", + "signature_type": "ecdsa", + "account_identifier": { + "address": "dummy" + } + }, + "signature": { + "hex_bytes": "c80547470b7e4d3fc17c988b2244dfebc909b3e9f7fd0c1387763263cc70d16d24f326b9c12ba2ea278164c0b30f128a809585fc503eda43de429aadb9f893ef" + } + } +} \ No newline at end of file