write code to actually call ledger app

This commit is contained in:
Ethan Frey 2017-09-12 11:40:30 +02:00
parent 265e261c63
commit 623bd803c2
3 changed files with 101 additions and 30 deletions

View File

@ -4,39 +4,91 @@ import (
"bytes" "bytes"
"encoding/hex" "encoding/hex"
ledger "github.com/ethanfrey/ledger"
crypto "github.com/tendermint/go-crypto" crypto "github.com/tendermint/go-crypto"
) )
// // Implements PrivKey, calling the ledger nano var device *ledger.Ledger
// type PrivKeyLedger struct{}
// var _ PrivKeyInner = PrivKeyLedger{} // getLedger gets a copy of the device, and caches it
func getLedger() (*ledger.Ledger, error) {
var err error
if device == nil {
device, err = ledger.FindLedger()
}
return device, err
}
// func (privKey PrivKeyLedger) AssertIsPrivKeyInner() {} func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto.Signature, err error) {
var resp []byte
// func (privKey PrivKeyLedger) Bytes() []byte { packets := generateSignRequests(msg)
// return wire.BinaryBytes(PrivKey{privKey}) for _, pack := range packets {
// } resp, err = device.Exchange(pack, 100)
if err != nil {
return pk, sig, err
}
}
// func (privKey PrivKeyLedger) Sign(msg []byte) Signature { // the last call is the result we want and needs to be parsed
// privKeyBytes := [64]byte(privKey) key, bsig, err := parseDigest(resp)
// signatureBytes := ed25519.Sign(&privKeyBytes, msg) if err != nil {
// return SignatureEd25519(*signatureBytes).Wrap() return pk, sig, err
// } }
// func (privKey PrivKeyLedger) PubKey() PubKey { var b [32]byte
// privKeyBytes := [64]byte(privKey) copy(b[:], key)
// pubBytes := *ed25519.MakePublicKey(&privKeyBytes) return PubKeyLedgerFromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil
// return PubKeyEd25519(pubBytes).Wrap() }
// }
// func (privKey PrivKeyLedger) Equals(other PrivKey) bool { // PrivKeyLedger implements PrivKey, calling the ledger nano
// if otherEd, ok := other.Unwrap().(PrivKeyLedger); ok { // we cache the PubKey from the first call to use it later
// return bytes.Equal(privKey[:], otherEd[:]) type PrivKeyLedger struct {
// } else { pubKey crypto.PubKey
// return false }
// }
// } var _ crypto.PrivKeyInner = &PrivKeyLedger{}
// AssertIsPrivKeyInner fulfils PrivKey Interface
func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {}
// Bytes fulfils pk Interface - not supported
func (pk *PrivKeyLedger) Bytes() []byte {
return nil
}
// Sign calls the ledger and stores the pk for future use
func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature {
// oh, I wish there was better error handling
dev, err := getLedger()
if err != nil {
panic(err)
}
pub, sig, err := signLedger(dev, msg)
if err != nil {
panic(err)
}
pk.pubKey = pub
return sig
}
// PubKey returns the stored PubKey
// TODO: query the ledger if not there, once it is not volatile
func (pk *PrivKeyLedger) PubKey() crypto.PubKey {
return pk.pubKey
}
// Equals fulfils PrivKey Interface
// TODO: needs to be fixed
func (pk *PrivKeyLedger) Equals(other crypto.PrivKey) bool {
if _, ok := other.Unwrap().(*PrivKeyLedger); ok {
return true
}
return false
}
// MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response // MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response
// for use in test cases // for use in test cases
@ -88,7 +140,7 @@ func (pk MockPrivKeyLedger) Sign(msg []byte) crypto.Signature {
// PubKey returns a real PubKeyLedger, that will verify this signature // PubKey returns a real PubKeyLedger, that will verify this signature
func (pk MockPrivKeyLedger) PubKey() crypto.PubKey { func (pk MockPrivKeyLedger) PubKey() crypto.PubKey {
return PubKeyLedger{crypto.PubKeyEd25519(pk.Pub)}.Wrap() return PubKeyLedgerFromBytes(pk.Pub)
} }
// Equals compares that two Mocks have the same data // Equals compares that two Mocks have the same data
@ -109,6 +161,11 @@ type PubKeyLedger struct {
crypto.PubKeyEd25519 crypto.PubKeyEd25519
} }
// PubKeyLedgerFromBytes creates a PubKey from the raw bytes
func PubKeyLedgerFromBytes(key [32]byte) crypto.PubKey {
return PubKeyLedger{crypto.PubKeyEd25519(key)}.Wrap()
}
// VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand // VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand
func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool {
hmsg := hashMsg(msg) hmsg := hashMsg(msg)
@ -127,17 +184,17 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool {
func init() { func init() {
crypto.PrivKeyMapper. crypto.PrivKeyMapper.
// RegisterImplementation(PrivKeyLedger{}, "ledger", 0x10). RegisterImplementation(&PrivKeyLedger{}, "ledger", 0x10).
RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11)
crypto.PubKeyMapper. crypto.PubKeyMapper.
RegisterImplementation(PubKeyLedger{}, "ledger", 0x10) RegisterImplementation(PubKeyLedger{}, "ledger", 0x10)
} }
// // Wrap fulfils interface for PrivKey struct // Wrap fulfils interface for PrivKey struct
// func (hi PrivKeyLedger) Wrap() crypto.PrivKey { func (pk *PrivKeyLedger) Wrap() crypto.PrivKey {
// return PrivKey{hi} return crypto.PrivKey{pk}
// } }
// Wrap fulfils interface for PrivKey struct // Wrap fulfils interface for PrivKey struct
func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey { func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey {

View File

@ -2,6 +2,7 @@ package nano
import ( import (
"encoding/hex" "encoding/hex"
"os"
"testing" "testing"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
@ -71,3 +72,10 @@ func TestLedgerKeys(t *testing.T) {
assert.Equal(tc.valid, valid, "%d", i) assert.Equal(tc.valid, valid, "%d", i)
} }
} }
func TestRealLedger(t *testing.T) {
if os.Getenv("WITH_LEDGER") == "" {
t.Skip("Set WITH_LEDGER to run code on real ledger")
}
// let's try for real....
}

View File

@ -63,6 +63,12 @@ func (sig *SignatureEd25519) UnmarshalJSON(enc []byte) error {
return err return err
} }
func SignatureEd25519FromBytes(data []byte) Signature {
var sig SignatureEd25519
copy(sig[:], data)
return sig.Wrap()
}
//------------------------------------- //-------------------------------------
var _ SignatureInner = SignatureSecp256k1{} var _ SignatureInner = SignatureSecp256k1{}