Skip to content

Commit

Permalink
Add signature verification tool in rosetta-cli (#387)
Browse files Browse the repository at this point in the history
* add verify and readme

* format

* verify json example
  • Loading branch information
shrimalmadhur authored Jan 30, 2023
1 parent 1188c48 commit 679464c
Show file tree
Hide file tree
Showing 8 changed files with 151 additions and 14 deletions.
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
33 changes: 33 additions & 0 deletions cmd/README.md
Original file line number Diff line number Diff line change
@@ -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 verify.json
```
A sample config file is located [here](../examples/configuration/verify.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.
29 changes: 18 additions & 11 deletions cmd/sign.go → cmd/key_sign.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,43 +17,50 @@ package cmd
import (
"encoding/hex"
"errors"
"fmt"

"github.com/coinbase/rosetta-sdk-go/keys"
"github.com/fatih/color"
"github.com/spf13/cobra"
)

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
}

Expand All @@ -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
}
69 changes: 69 additions & 0 deletions cmd/key_verify.go
Original file line number Diff line number Diff line change
@@ -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
}
7 changes: 5 additions & 2 deletions cmd/root.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {
Expand Down
1 change: 1 addition & 0 deletions configuration/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 4 additions & 1 deletion examples/configuration/sign.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@
"private_key": "",
"signing_payload": {
"hex_bytes": "370e74254e8cbaa343af3564901456082ec7af967e45ff24ba061233b1a1b04f",
"signature_type": "ecdsa"
"signature_type": "ecdsa",
"account_identifier": {
"address": "dummy"
}
}
}
}
18 changes: 18 additions & 0 deletions examples/configuration/verify.json
Original file line number Diff line number Diff line change
@@ -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"
}
}
}

0 comments on commit 679464c

Please sign in to comment.