Skip to content

Commit

Permalink
Merge PR cosmos#3431: PrivKeyLedgerSecp256k1: lost connection
Browse files Browse the repository at this point in the history
  • Loading branch information
jleni authored and jackzampolin committed Feb 5, 2019
1 parent ac1d2c7 commit 174ec0c
Show file tree
Hide file tree
Showing 7 changed files with 273 additions and 121 deletions.
39 changes: 20 additions & 19 deletions Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 4 additions & 1 deletion Gopkg.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@

[[constraint]]
name = "github.com/zondax/ledger-cosmos-go"
version = "=v0.9.3"
version = "=v0.9.7"

## deps without releases:

Expand Down Expand Up @@ -84,3 +84,6 @@
[prune]
go-tests = true
unused-packages = true
[[prune.project]]
name = "github.com/zondax/hid"
unused-packages = false
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,9 @@ test: test_unit
test_cli:
@go test -p 4 `go list github.com/cosmos/cosmos-sdk/cmd/gaia/cli_test` -tags=cli_test

test_ledger:
@go test `go list github.com/cosmos/cosmos-sdk/crypto` -tags='cgo ledger test_real_ledger'

test_unit:
@VERSION=$(VERSION) go test $(PACKAGES_NOSIMULATION)

Expand Down
1 change: 1 addition & 0 deletions PENDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ BUG FIXES
- [\#3419](https://github.com/cosmos/cosmos-sdk/pull/3419) Fix `q distr slashes` panic
- [\#3453](https://github.com/cosmos/cosmos-sdk/pull/3453) The `rest-server` command didn't respect persistent flags such as `--chain-id` and `--trust-node` if they were
passed on the command line.
- [\#3441](https://github.com/cosmos/cosmos-sdk/pull/3431) Improved resource management and connection handling (ledger devices). Fixes issue with DER vs BER signatures.

* Gaia
* [\#3486](https://github.com/cosmos/cosmos-sdk/pull/3486) Use AmountOf in
Expand Down
157 changes: 157 additions & 0 deletions crypto/ledger_integration_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
// +build cgo,ledger,test_real_ledger

package crypto

import (
"fmt"
"testing"

"github.com/cosmos/cosmos-sdk/crypto/keys/hd"
sdk "github.com/cosmos/cosmos-sdk/types"
"github.com/stretchr/testify/require"
"github.com/tendermint/tendermint/crypto/encoding/amino"
ledger "github.com/zondax/ledger-cosmos-go"
)

const (
// These tests expect a ledger device initialized to the following mnemonic
testMnemonic = "equip will roof matter pink blind book anxiety banner elbow sun young"
)

func TestDiscoverDevice(t *testing.T) {
device, err := discoverLedger()
require.NoError(t, err)
require.NotNil(t, device)
defer device.Close()
}

func TestDiscoverDeviceTwice(t *testing.T) {
// We expect the second call not to find a device
device, err := discoverLedger()
require.NoError(t, err)
require.NotNil(t, device)
defer device.Close()

device2, err := discoverLedger()
require.Error(t, err)
require.Equal(t, "no ledger connected", err.Error())
require.Nil(t, device2)
}

func TestDiscoverDeviceTwiceClosing(t *testing.T) {
{
device, err := ledger.FindLedgerCosmosUserApp()
require.NoError(t, err)
require.NotNil(t, device)
require.NoError(t, device.Close())
}

device2, err := discoverLedger()
require.NoError(t, err)
require.NotNil(t, device2)
require.NoError(t, device2.Close())
}

func TestPublicKey(t *testing.T) {
path := *hd.NewFundraiserParams(0, 0)
priv, err := NewPrivKeyLedgerSecp256k1(path)
require.Nil(t, err, "%s", err)
require.NotNil(t, priv)

pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
require.NoError(t, err)
require.Equal(t, "cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0", pubKeyAddr, "Is your device using test mnemonic: %s ?", testMnemonic)
require.Equal(t, "5075624b6579536563703235366b317b303334464546394344374334433633353838443342303"+
"3464542353238314239443233324342413334443646334437314145453539323131464642464531464538377d",
fmt.Sprintf("%x", priv.PubKey()))
}

func TestPublicKeyHDPath(t *testing.T) {
expectedAnswers := []string{
"cosmospub1addwnpepqd87l8xhcnrrtzxnkql7k55ph8fr9jarf4hn6udwukfprlalu8lgw0urza0",
"cosmospub1addwnpepqfsdqjr68h7wjg5wacksmqaypasnra232fkgu5sxdlnlu8j22ztxvlqvd65",
"cosmospub1addwnpepqw3xwqun6q43vtgw6p4qspq7srvxhcmvq4jrx5j5ma6xy3r7k6dtxmrkh3d",
"cosmospub1addwnpepqvez9lrp09g8w7gkv42y4yr5p6826cu28ydrhrujv862yf4njmqyyjr4pjs",
"cosmospub1addwnpepq06hw3enfrtmq8n67teytcmtnrgcr0yntmyt25kdukfjkerdc7lqg32rcz7",
"cosmospub1addwnpepqg3trf2gd0s2940nckrxherwqhgmm6xd5h4pcnrh4x7y35h6yafmcpk5qns",
"cosmospub1addwnpepqdm6rjpx6wsref8wjn7ym6ntejet430j4szpngfgc20caz83lu545vuv8hp",
"cosmospub1addwnpepqvdhtjzy2wf44dm03jxsketxc07vzqwvt3vawqqtljgsr9s7jvydjmt66ew",
"cosmospub1addwnpepqwystfpyxwcava7v3t7ndps5xzu6s553wxcxzmmnxevlzvwrlqpzz695nw9",
"cosmospub1addwnpepqw970u6gjqkccg9u3rfj99857wupj2z9fqfzy2w7e5dd7xn7kzzgkgqch0r",
}

// Check with device
for i := uint32(0); i < 10; i++ {
path := *hd.NewFundraiserParams(0, i)
fmt.Printf("Checking keys at %v\n", path)

priv, err := NewPrivKeyLedgerSecp256k1(path)
require.Nil(t, err, "%s", err)
require.NotNil(t, priv)

pubKeyAddr, err := sdk.Bech32ifyAccPub(priv.PubKey())
require.NoError(t, err)
require.Equal(t, expectedAnswers[i], pubKeyAddr, "Is your device using test mnemonic: %s ?", testMnemonic)
}
}

func getFakeTx(accountNumber uint32) []byte {
tmp := fmt.Sprintf(
`{"account_number":"%d","chain_id":"1234","fee":{"amount":[{"amount":"150","denom":"atom"}],"gas":"5000"},"memo":"memo","msgs":[[""]],"sequence":"6"}`,
accountNumber)

return []byte(tmp)
}

func TestSignaturesHD(t *testing.T) {
for account := uint32(0); account < 100; account += 30 {
msg := getFakeTx(account)

path := *hd.NewFundraiserParams(account, account/5)
fmt.Printf("Checking signature at %v\n", path)

priv, err := NewPrivKeyLedgerSecp256k1(path)
require.Nil(t, err, "%s", err)

pub := priv.PubKey()
sig, err := priv.Sign(msg)
require.Nil(t, err)

valid := pub.VerifyBytes(msg, sig)
require.True(t, valid, "Is your device using test mnemonic: %s ?", testMnemonic)
}
}

func TestRealLedgerSecp256k1(t *testing.T) {
msg := getFakeTx(50)
path := *hd.NewFundraiserParams(0, 0)
priv, err := NewPrivKeyLedgerSecp256k1(path)
require.Nil(t, err, "%s", err)

pub := priv.PubKey()
sig, err := priv.Sign(msg)
require.Nil(t, err)

valid := pub.VerifyBytes(msg, sig)
require.True(t, valid)

// now, let's serialize the public key and make sure it still works
bs := priv.PubKey().Bytes()
pub2, err := cryptoAmino.PubKeyFromBytes(bs)
require.Nil(t, err, "%+v", err)

// make sure we get the same pubkey when we load from disk
require.Equal(t, pub, pub2)

// signing with the loaded key should match the original pubkey
sig, err = priv.Sign(msg)
require.Nil(t, err)
valid = pub.VerifyBytes(msg, sig)
require.True(t, valid)

// make sure pubkeys serialize properly as well
bs = pub.Bytes()
bpub, err := cryptoAmino.PubKeyFromBytes(bs)
require.NoError(t, err)
require.Equal(t, pub, bpub)
}
Loading

0 comments on commit 174ec0c

Please sign in to comment.