|
|
@ -14,7 +14,7 @@ import ( |
|
|
|
|
|
|
|
//nolint
|
|
|
|
const ( |
|
|
|
NameLedgerEd25519 = "ledger" |
|
|
|
NameLedgerEd25519 = "ledger-ed25519" |
|
|
|
TypeLedgerEd25519 = 0x10 |
|
|
|
) |
|
|
|
|
|
|
@ -48,22 +48,22 @@ func signLedger(device *ledger.Ledger, msg []byte) (pk crypto.PubKey, sig crypto |
|
|
|
|
|
|
|
var b [32]byte |
|
|
|
copy(b[:], key) |
|
|
|
return PubKeyLedgerFromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil |
|
|
|
return PubKeyLedgerEd25519FromBytes(b), crypto.SignatureEd25519FromBytes(bsig), nil |
|
|
|
} |
|
|
|
|
|
|
|
// PrivKeyLedger implements PrivKey, calling the ledger nano
|
|
|
|
// PrivKeyLedgerEd25519 implements PrivKey, calling the ledger nano
|
|
|
|
// we cache the PubKey from the first call to use it later
|
|
|
|
type PrivKeyLedger struct { |
|
|
|
type PrivKeyLedgerEd25519 struct { |
|
|
|
// PubKey should be private, but we want to encode it via go-wire
|
|
|
|
// so we can view the address later, even without having the ledger
|
|
|
|
// attached
|
|
|
|
CachedPubKey crypto.PubKey |
|
|
|
} |
|
|
|
|
|
|
|
// NewPrivKeyLedger will generate a new key and store the
|
|
|
|
// NewPrivKeyLedgerEd25519Ed25519 will generate a new key and store the
|
|
|
|
// public key for later use.
|
|
|
|
func NewPrivKeyLedger() (crypto.PrivKey, error) { |
|
|
|
var pk PrivKeyLedger |
|
|
|
func NewPrivKeyLedgerEd25519Ed25519() (crypto.PrivKey, error) { |
|
|
|
var pk PrivKeyLedgerEd25519 |
|
|
|
// getPubKey will cache the pubkey for later use,
|
|
|
|
// this allows us to return an error early if the ledger
|
|
|
|
// is not plugged in
|
|
|
@ -73,7 +73,7 @@ func NewPrivKeyLedger() (crypto.PrivKey, error) { |
|
|
|
|
|
|
|
// ValidateKey allows us to verify the sanity of a key
|
|
|
|
// after loading it from disk
|
|
|
|
func (pk *PrivKeyLedger) ValidateKey() error { |
|
|
|
func (pk *PrivKeyLedgerEd25519) ValidateKey() error { |
|
|
|
// getPubKey will return an error if the ledger is not
|
|
|
|
// properly set up...
|
|
|
|
pub, err := pk.forceGetPubKey() |
|
|
@ -88,15 +88,15 @@ func (pk *PrivKeyLedger) ValidateKey() error { |
|
|
|
} |
|
|
|
|
|
|
|
// AssertIsPrivKeyInner fulfils PrivKey Interface
|
|
|
|
func (pk *PrivKeyLedger) AssertIsPrivKeyInner() {} |
|
|
|
func (pk *PrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} |
|
|
|
|
|
|
|
// Bytes fulfils pk Interface - no data, just type info
|
|
|
|
func (pk *PrivKeyLedger) Bytes() []byte { |
|
|
|
func (pk *PrivKeyLedgerEd25519) Bytes() []byte { |
|
|
|
return wire.BinaryBytes(pk.Wrap()) |
|
|
|
} |
|
|
|
|
|
|
|
// Sign calls the ledger and stores the pk for future use
|
|
|
|
func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { |
|
|
|
func (pk *PrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { |
|
|
|
// oh, I wish there was better error handling
|
|
|
|
dev, err := getLedger() |
|
|
|
if err != nil { |
|
|
@ -119,7 +119,7 @@ func (pk *PrivKeyLedger) Sign(msg []byte) crypto.Signature { |
|
|
|
|
|
|
|
// PubKey returns the stored PubKey
|
|
|
|
// TODO: query the ledger if not there, once it is not volatile
|
|
|
|
func (pk *PrivKeyLedger) PubKey() crypto.PubKey { |
|
|
|
func (pk *PrivKeyLedgerEd25519) PubKey() crypto.PubKey { |
|
|
|
key, err := pk.getPubKey() |
|
|
|
if err != nil { |
|
|
|
panic(err) |
|
|
@ -130,7 +130,7 @@ func (pk *PrivKeyLedger) PubKey() crypto.PubKey { |
|
|
|
// getPubKey reads the pubkey from cache or from the ledger itself
|
|
|
|
// since this involves IO, it may return an error, which is not exposed
|
|
|
|
// in the PubKey interface, so this function allows better error handling
|
|
|
|
func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { |
|
|
|
func (pk *PrivKeyLedgerEd25519) getPubKey() (key crypto.PubKey, err error) { |
|
|
|
// if we have no pubkey, set it
|
|
|
|
if pk.CachedPubKey.Empty() { |
|
|
|
pk.CachedPubKey, err = pk.forceGetPubKey() |
|
|
@ -140,7 +140,7 @@ func (pk *PrivKeyLedger) getPubKey() (key crypto.PubKey, err error) { |
|
|
|
|
|
|
|
// forceGetPubKey is like getPubKey but ignores any cached key
|
|
|
|
// and ensures we get it from the ledger itself.
|
|
|
|
func (pk *PrivKeyLedger) forceGetPubKey() (key crypto.PubKey, err error) { |
|
|
|
func (pk *PrivKeyLedgerEd25519) forceGetPubKey() (key crypto.PubKey, err error) { |
|
|
|
dev, err := getLedger() |
|
|
|
if err != nil { |
|
|
|
return key, errors.New("Can't connect to ledger device") |
|
|
@ -154,23 +154,23 @@ func (pk *PrivKeyLedger) forceGetPubKey() (key crypto.PubKey, err error) { |
|
|
|
|
|
|
|
// Equals fulfils PrivKey Interface
|
|
|
|
// TODO: needs to be fixed
|
|
|
|
func (pk *PrivKeyLedger) Equals(other crypto.PrivKey) bool { |
|
|
|
if _, ok := other.Unwrap().(*PrivKeyLedger); ok { |
|
|
|
func (pk *PrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { |
|
|
|
if _, ok := other.Unwrap().(*PrivKeyLedgerEd25519); ok { |
|
|
|
return true |
|
|
|
} |
|
|
|
return false |
|
|
|
} |
|
|
|
|
|
|
|
// MockPrivKeyLedger behaves as the ledger, but stores a pre-packaged call-response
|
|
|
|
// MockPrivKeyLedgerEd25519 behaves as the ledger, but stores a pre-packaged call-response
|
|
|
|
// for use in test cases
|
|
|
|
type MockPrivKeyLedger struct { |
|
|
|
type MockPrivKeyLedgerEd25519 struct { |
|
|
|
Msg []byte |
|
|
|
Pub [KeyLength]byte |
|
|
|
Sig [SigLength]byte |
|
|
|
} |
|
|
|
|
|
|
|
// NewMockKey returns
|
|
|
|
func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedger) { |
|
|
|
func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedgerEd25519) { |
|
|
|
var err error |
|
|
|
pk.Msg, err = hex.DecodeString(msg) |
|
|
|
if err != nil { |
|
|
@ -191,32 +191,32 @@ func NewMockKey(msg, pubkey, sig string) (pk MockPrivKeyLedger) { |
|
|
|
return pk |
|
|
|
} |
|
|
|
|
|
|
|
var _ crypto.PrivKeyInner = MockPrivKeyLedger{} |
|
|
|
var _ crypto.PrivKeyInner = MockPrivKeyLedgerEd25519{} |
|
|
|
|
|
|
|
// AssertIsPrivKeyInner fulfils PrivKey Interface
|
|
|
|
func (pk MockPrivKeyLedger) AssertIsPrivKeyInner() {} |
|
|
|
func (pk MockPrivKeyLedgerEd25519) AssertIsPrivKeyInner() {} |
|
|
|
|
|
|
|
// Bytes fulfils PrivKey Interface - not supported
|
|
|
|
func (pk MockPrivKeyLedger) Bytes() []byte { |
|
|
|
func (pk MockPrivKeyLedgerEd25519) Bytes() []byte { |
|
|
|
return nil |
|
|
|
} |
|
|
|
|
|
|
|
// Sign returns a real SignatureLedger, if the msg matches what we expect
|
|
|
|
func (pk MockPrivKeyLedger) Sign(msg []byte) crypto.Signature { |
|
|
|
func (pk MockPrivKeyLedgerEd25519) Sign(msg []byte) crypto.Signature { |
|
|
|
if !bytes.Equal(pk.Msg, msg) { |
|
|
|
panic("Mock key is for different msg") |
|
|
|
} |
|
|
|
return crypto.SignatureEd25519(pk.Sig).Wrap() |
|
|
|
} |
|
|
|
|
|
|
|
// PubKey returns a real PubKeyLedger, that will verify this signature
|
|
|
|
func (pk MockPrivKeyLedger) PubKey() crypto.PubKey { |
|
|
|
return PubKeyLedgerFromBytes(pk.Pub) |
|
|
|
// PubKey returns a real PubKeyLedgerEd25519, that will verify this signature
|
|
|
|
func (pk MockPrivKeyLedgerEd25519) PubKey() crypto.PubKey { |
|
|
|
return PubKeyLedgerEd25519FromBytes(pk.Pub) |
|
|
|
} |
|
|
|
|
|
|
|
// Equals compares that two Mocks have the same data
|
|
|
|
func (pk MockPrivKeyLedger) Equals(other crypto.PrivKey) bool { |
|
|
|
if mock, ok := other.Unwrap().(MockPrivKeyLedger); ok { |
|
|
|
func (pk MockPrivKeyLedgerEd25519) Equals(other crypto.PrivKey) bool { |
|
|
|
if mock, ok := other.Unwrap().(MockPrivKeyLedgerEd25519); ok { |
|
|
|
return bytes.Equal(mock.Pub[:], pk.Pub[:]) && |
|
|
|
bytes.Equal(mock.Sig[:], pk.Sig[:]) && |
|
|
|
bytes.Equal(mock.Msg, pk.Msg) |
|
|
@ -227,30 +227,30 @@ func (pk MockPrivKeyLedger) Equals(other crypto.PrivKey) bool { |
|
|
|
////////////////////////////////////////////
|
|
|
|
// pubkey
|
|
|
|
|
|
|
|
// PubKeyLedger works like a normal Ed25519 except a hash before the verify bytes
|
|
|
|
type PubKeyLedger struct { |
|
|
|
// PubKeyLedgerEd25519 works like a normal Ed25519 except a hash before the verify bytes
|
|
|
|
type PubKeyLedgerEd25519 struct { |
|
|
|
crypto.PubKeyEd25519 |
|
|
|
} |
|
|
|
|
|
|
|
// PubKeyLedgerFromBytes creates a PubKey from the raw bytes
|
|
|
|
func PubKeyLedgerFromBytes(key [32]byte) crypto.PubKey { |
|
|
|
return PubKeyLedger{crypto.PubKeyEd25519(key)}.Wrap() |
|
|
|
// PubKeyLedgerEd25519FromBytes creates a PubKey from the raw bytes
|
|
|
|
func PubKeyLedgerEd25519FromBytes(key [32]byte) crypto.PubKey { |
|
|
|
return PubKeyLedgerEd25519{crypto.PubKeyEd25519(key)}.Wrap() |
|
|
|
} |
|
|
|
|
|
|
|
// Bytes fulfils pk Interface - no data, just type info
|
|
|
|
func (pk PubKeyLedger) Bytes() []byte { |
|
|
|
func (pk PubKeyLedgerEd25519) Bytes() []byte { |
|
|
|
return wire.BinaryBytes(pk.Wrap()) |
|
|
|
} |
|
|
|
|
|
|
|
// VerifyBytes uses the normal Ed25519 algorithm but a sha512 hash beforehand
|
|
|
|
func (pk PubKeyLedger) VerifyBytes(msg []byte, sig crypto.Signature) bool { |
|
|
|
func (pk PubKeyLedgerEd25519) VerifyBytes(msg []byte, sig crypto.Signature) bool { |
|
|
|
hmsg := hashMsg(msg) |
|
|
|
return pk.PubKeyEd25519.VerifyBytes(hmsg, sig) |
|
|
|
} |
|
|
|
|
|
|
|
// Equals implements PubKey interface
|
|
|
|
func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { |
|
|
|
if ledger, ok := other.Unwrap().(PubKeyLedger); ok { |
|
|
|
func (pk PubKeyLedgerEd25519) Equals(other crypto.PubKey) bool { |
|
|
|
if ledger, ok := other.Unwrap().(PubKeyLedgerEd25519); ok { |
|
|
|
return bytes.Equal(pk.PubKeyEd25519[:], ledger.PubKeyEd25519[:]) |
|
|
|
} |
|
|
|
return false |
|
|
@ -260,24 +260,24 @@ func (pk PubKeyLedger) Equals(other crypto.PubKey) bool { |
|
|
|
|
|
|
|
func init() { |
|
|
|
crypto.PrivKeyMapper. |
|
|
|
RegisterImplementation(&PrivKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519). |
|
|
|
RegisterImplementation(MockPrivKeyLedger{}, "mock-ledger", 0x11) |
|
|
|
RegisterImplementation(&PrivKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519). |
|
|
|
RegisterImplementation(MockPrivKeyLedgerEd25519{}, "mock-ledger", 0x11) |
|
|
|
|
|
|
|
crypto.PubKeyMapper. |
|
|
|
RegisterImplementation(PubKeyLedger{}, NameLedgerEd25519, TypeLedgerEd25519) |
|
|
|
RegisterImplementation(PubKeyLedgerEd25519{}, NameLedgerEd25519, TypeLedgerEd25519) |
|
|
|
} |
|
|
|
|
|
|
|
// Wrap fulfils interface for PrivKey struct
|
|
|
|
func (pk *PrivKeyLedger) Wrap() crypto.PrivKey { |
|
|
|
func (pk *PrivKeyLedgerEd25519) Wrap() crypto.PrivKey { |
|
|
|
return crypto.PrivKey{pk} |
|
|
|
} |
|
|
|
|
|
|
|
// Wrap fulfils interface for PrivKey struct
|
|
|
|
func (pk MockPrivKeyLedger) Wrap() crypto.PrivKey { |
|
|
|
func (pk MockPrivKeyLedgerEd25519) Wrap() crypto.PrivKey { |
|
|
|
return crypto.PrivKey{pk} |
|
|
|
} |
|
|
|
|
|
|
|
// Wrap fulfils interface for PubKey struct
|
|
|
|
func (pk PubKeyLedger) Wrap() crypto.PubKey { |
|
|
|
func (pk PubKeyLedgerEd25519) Wrap() crypto.PubKey { |
|
|
|
return crypto.PubKey{pk} |
|
|
|
} |