Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

R4R: PrivKeyLedgerSecp256k1: lost connection #3431

Merged
merged 20 commits into from
Feb 5, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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