watchtower: extend and rename SecretKeyRing

This commit is contained in:
Oliver Gugger 2020-04-28 10:06:25 +02:00
parent b0cb110e86
commit 6f702a43aa
No known key found for this signature in database
GPG Key ID: 8E4256593F177720
5 changed files with 68 additions and 6 deletions

@ -132,7 +132,7 @@ type Config struct {
// SecretKeyRing is used to derive the session keys used to communicate
// with the tower. The client only stores the KeyLocators internally so
// that we never store private keys on disk.
SecretKeyRing SecretKeyRing
SecretKeyRing ECDHKeyRing
// Dial connects to an addr using the specified net and returns the
// connection object.

@ -12,7 +12,7 @@ import (
// derivation path of:
//
// * m/1017'/coinType'/8/0/index
func DeriveSessionKey(keyRing SecretKeyRing,
func DeriveSessionKey(keyRing ECDHKeyRing,
index uint32) (*btcec.PrivateKey, error) {
return keyRing.DerivePrivKey(keychain.KeyDescriptor{

@ -112,10 +112,18 @@ func AuthDial(localPriv *btcec.PrivateKey, netAddr *lnwire.NetAddress,
return brontide.Dial(localPriv, netAddr, dialer)
}
// SecretKeyRing abstracts the ability to derive HD private keys given a
// description of the derivation path.
type SecretKeyRing interface {
// ECDHKeyRing abstracts the ability to derive shared ECDH keys given a
// description of the derivation path of a private key.
type ECDHKeyRing interface {
keychain.ECDHRing
// DerivePrivKey derives the private key from the root seed using a
// key descriptor specifying the key's derivation path.
DerivePrivKey(loc keychain.KeyDescriptor) (*btcec.PrivateKey, error)
// DeriveKey attempts to derive an arbitrary key specified by the
// passed KeyLocator. This may be used in several recovery scenarios,
// or when manually rotating something like our current default node
// key.
DeriveKey(keyLoc keychain.KeyLocator) (keychain.KeyDescriptor, error)
}

@ -44,7 +44,7 @@ type NegotiatorConfig struct {
// SecretKeyRing allows the client to derive new session private keys
// when attempting to negotiate session with a tower.
SecretKeyRing SecretKeyRing
SecretKeyRing ECDHKeyRing
// Candidates is an abstract set of tower candidates that the negotiator
// will traverse serially when attempting to negotiate a new session.

@ -42,3 +42,57 @@ func (m *SecretKeyRing) DerivePrivKey(
return privKey, nil
}
// DeriveKey attempts to derive an arbitrary key specified by the
// passed KeyLocator. This may be used in several recovery scenarios,
// or when manually rotating something like our current default node
// key.
//
// NOTE: This is part of the wtclient.ECDHKeyRing interface.
func (m *SecretKeyRing) DeriveKey(
keyLoc keychain.KeyLocator) (keychain.KeyDescriptor, error) {
m.mu.Lock()
defer m.mu.Unlock()
if key, ok := m.keys[keyLoc]; ok {
return keychain.KeyDescriptor{
KeyLocator: keyLoc,
PubKey: key.PubKey(),
}, nil
}
privKey, err := btcec.NewPrivateKey(btcec.S256())
if err != nil {
return keychain.KeyDescriptor{}, err
}
m.keys[keyLoc] = privKey
return keychain.KeyDescriptor{
KeyLocator: keyLoc,
PubKey: privKey.PubKey(),
}, nil
}
// ECDH performs a scalar multiplication (ECDH-like operation) between the
// target key descriptor and 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 wtclient.ECDHKeyRing interface.
func (m *SecretKeyRing) ECDH(keyDesc keychain.KeyDescriptor,
pub *btcec.PublicKey) ([32]byte, error) {
_, err := m.DeriveKey(keyDesc.KeyLocator)
if err != nil {
return [32]byte{}, err
}
privKey := m.keys[keyDesc.KeyLocator]
ecdh := &keychain.PrivKeyECDH{PrivKey: privKey}
return ecdh.ECDH(pub)
}