Skip to content
Merged
Changes from 1 commit
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
49 changes: 49 additions & 0 deletions crypto.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,55 @@ const (
// the output of a SHA256 hash.
type Hash256 [sha256.Size]byte

// SingleKeyECDH is an abstraction interface that hides the implementation of an
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wondering still if SingleKeyECDH is the right name. It also suggests some fancy algorithm in which you exchange keys with yourself. Thinking about alternatives. Maybe ExternalECDH or just Signer (even though it isn't really signing)

// ECDH operation against a specific private key. We use this abstraction for
// the long term keys which we eventually want to be able to keep in a hardware
// wallet or HSM.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out of curiosity, which hardware wallets currently support ECDH?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have no idea, to be honest. HW wallets are my blind spot. But I imagine implementing that is pretty easy as it's not much different from signing a message.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Roasbeef do they exist?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ledger and trezor have support in their APIs which can be leveraged by custom applications. With this though, I think we're more so targeting remote/restricted signers which can emulate these calls by using the existing lnd gRPC interface and sub-servers, or something else entirely.

type SingleKeyECDH interface {
// PubKey returns the public key of the private key that is abstracted
// away by the interface.
PubKey() *btcec.PublicKey

// ECDH performs a scalar multiplication (ECDH-like operation) between
// the abstracted private key and a remote public key. The output
// returned will be the sha256 of the resulting shared point serialized
// in compressed format.
ECDH(pubKey *btcec.PublicKey) ([32]byte, error)
}

// PrivKeyECDH is an implementation of the SingleKeyECDH in which we do have the
// full private key. This can be used to wrap a temporary key to conform to the
// SingleKeyECDH interface.
type PrivKeyECDH struct {
// PrivKey is the private key that is used for the ECDH operation.
PrivKey *btcec.PrivateKey
}

// PubKey returns the public key of the private key that is abstracted away by
// the interface.
//
// NOTE: This is part of the SingleKeyECDH interface.
func (p *PrivKeyECDH) PubKey() *btcec.PublicKey {
return p.PrivKey.PubKey()
}

// ECDH performs a scalar multiplication (ECDH-like operation) between the
// abstracted private key and a remote public key. The output returned will be
// the sha256 of the resulting shared point serialized in compressed format. If
// k is our private key, and P is the public key, we perform the following
// operation:
//
// sx := k*P
// s := sha256(sx.SerializeCompressed())
//
// NOTE: This is part of the SingleKeyECDH interface.
func (p *PrivKeyECDH) ECDH(pub *btcec.PublicKey) ([32]byte, error) {
s := &btcec.PublicKey{}
s.X, s.Y = btcec.S256().ScalarMult(pub.X, pub.Y, p.PrivKey.D.Bytes())

return sha256.Sum256(s.SerializeCompressed()), nil
}

// DecryptedError contains the decrypted error message and its sender.
type DecryptedError struct {
// Sender is the node that sent the error. Note that a node may occur in
Expand Down