From c689f38cb587be1d4681c19e7ebea7ec8e35794e Mon Sep 17 00:00:00 2001 From: Christopher Goes Date: Wed, 30 May 2018 22:07:20 +0200 Subject: [PATCH] Implement PubKeyLedgerEd25519 --- amino.go | 4 +++ ledger_ed25519.go | 2 +- ledger_pub_key.go | 68 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 73 insertions(+), 1 deletion(-) create mode 100644 ledger_pub_key.go diff --git a/amino.go b/amino.go index 2af765434..b78a15ed9 100644 --- a/amino.go +++ b/amino.go @@ -19,6 +19,8 @@ func RegisterAmino(cdc *amino.Codec) { cdc.RegisterInterface((*PubKey)(nil), nil) cdc.RegisterConcrete(PubKeyEd25519{}, "tendermint/PubKeyEd25519", nil) + cdc.RegisterConcrete(PubKeyLedgerEd25519{}, + "tendermint/PubKeyLedgerEd25519", nil) cdc.RegisterConcrete(PubKeySecp256k1{}, "tendermint/PubKeySecp256k1", nil) @@ -29,6 +31,8 @@ func RegisterAmino(cdc *amino.Codec) { "tendermint/PrivKeySecp256k1", nil) cdc.RegisterConcrete(PrivKeyLedgerSecp256k1{}, "tendermint/PrivKeyLedgerSecp256k1", nil) + cdc.RegisterConcrete(PrivKeyLedgerEd25519{}, + "tendermint/PrivKeyLedgerEd25519", nil) cdc.RegisterInterface((*Signature)(nil), nil) cdc.RegisterConcrete(SignatureEd25519{}, diff --git a/ledger_ed25519.go b/ledger_ed25519.go index 0c9cd157f..2110b8871 100644 --- a/ledger_ed25519.go +++ b/ledger_ed25519.go @@ -13,7 +13,7 @@ func pubkeyLedgerEd25519(device *ledger.Ledger, path DerivationPath) (pub PubKey if err != nil { return pub, fmt.Errorf("Error fetching public key: %v", err) } - var p PubKeyEd25519 + var p PubKeyLedgerEd25519 copy(p[:], key[0:32]) return p, err } diff --git a/ledger_pub_key.go b/ledger_pub_key.go new file mode 100644 index 000000000..0a5222577 --- /dev/null +++ b/ledger_pub_key.go @@ -0,0 +1,68 @@ +package crypto + +import ( + "bytes" + "crypto/sha512" + "fmt" + + "github.com/tendermint/ed25519" + "github.com/tendermint/ed25519/extra25519" + "golang.org/x/crypto/ripemd160" +) + +var _ PubKey = PubKeyLedgerEd25519{} + +// Implements PubKeyInner +type PubKeyLedgerEd25519 [32]byte + +func (pubKey PubKeyLedgerEd25519) Address() Address { + // append type byte + hasher := ripemd160.New() + hasher.Write(pubKey.Bytes()) // does not error + return Address(hasher.Sum(nil)) +} + +func (pubKey PubKeyLedgerEd25519) Bytes() []byte { + bz, err := cdc.MarshalBinaryBare(pubKey) + if err != nil { + panic(err) + } + return bz +} + +func (pubKey PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig_ Signature) bool { + // must verify sha512 hash of msg, no padding, for Ledger compatibility + sig, ok := sig_.(SignatureEd25519) + if !ok { + return false + } + pubKeyBytes := [32]byte(pubKey) + sigBytes := [64]byte(sig) + h := sha512.New() + h.Write(msg) + digest := h.Sum(nil) + return ed25519.Verify(&pubKeyBytes, digest, &sigBytes) +} + +// For use with golang/crypto/nacl/box +// If error, returns nil. +func (pubKey PubKeyLedgerEd25519) ToCurve25519() *[32]byte { + keyCurve25519, pubKeyBytes := new([32]byte), [32]byte(pubKey) + ok := extra25519.PublicKeyToCurve25519(keyCurve25519, &pubKeyBytes) + if !ok { + return nil + } + return keyCurve25519 +} + +func (pubKey PubKeyLedgerEd25519) String() string { + return fmt.Sprintf("PubKeyLedgerEd25519{%X}", pubKey[:]) +} + +func (pubKey PubKeyLedgerEd25519) Equals(other PubKey) bool { + if otherEd, ok := other.(PubKeyLedgerEd25519); ok { + return bytes.Equal(pubKey[:], otherEd[:]) + } else { + return false + } +}