You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
10 KiB
250 lines
10 KiB
package keychain |
|
|
|
import ( |
|
"fmt" |
|
|
|
"github.com/btcsuite/btcd/btcec" |
|
) |
|
|
|
const ( |
|
// KeyDerivationVersion is the version of the key derivation schema |
|
// defined below. We use a version as this means that we'll be able to |
|
// accept new seed in the future and be able to discern if the software |
|
// is compatible with the version of the seed. |
|
KeyDerivationVersion = 0 |
|
|
|
// BIP0043Purpose is the "purpose" value that we'll use for the first |
|
// version or our key derivation scheme. All keys are expected to be |
|
// derived from this purpose, then the particular coin type of the |
|
// chain where the keys are to be used. Slightly adhering to BIP0043 |
|
// allows us to not deviate too far from a widely used standard, and |
|
// also fits into existing implementations of the BIP's template. |
|
// |
|
// NOTE: BRICK SQUUUUUAD. |
|
BIP0043Purpose = 1017 |
|
) |
|
|
|
var ( |
|
// MaxKeyRangeScan is the maximum number of keys that we'll attempt to |
|
// scan with if a caller knows the public key, but not the KeyLocator |
|
// and wishes to derive a private key. |
|
MaxKeyRangeScan = 100000 |
|
|
|
// ErrCannotDerivePrivKey is returned when DerivePrivKey is unable to |
|
// derive a private key given only the public key and target key |
|
// family. |
|
ErrCannotDerivePrivKey = fmt.Errorf("unable to derive private key") |
|
) |
|
|
|
// KeyFamily represents a "family" of keys that will be used within various |
|
// contracts created by lnd. These families are meant to be distinct branches |
|
// within the HD key chain of the backing wallet. Usage of key families within |
|
// the interface below are strict in order to promote integrability and the |
|
// ability to restore all keys given a user master seed backup. |
|
// |
|
// The key derivation in this file follows the following hierarchy based on |
|
// BIP43: |
|
// |
|
// * m/1017'/coinType'/keyFamily'/0/index |
|
type KeyFamily uint32 |
|
|
|
const ( |
|
// KeyFamilyMultiSig are keys to be used within multi-sig scripts. |
|
KeyFamilyMultiSig KeyFamily = 0 |
|
|
|
// KeyFamilyRevocationBase are keys that are used within channels to |
|
// create revocation basepoints that the remote party will use to |
|
// create revocation keys for us. |
|
KeyFamilyRevocationBase KeyFamily = 1 |
|
|
|
// KeyFamilyHtlcBase are keys used within channels that will be |
|
// combined with per-state randomness to produce public keys that will |
|
// be used in HTLC scripts. |
|
KeyFamilyHtlcBase KeyFamily = 2 |
|
|
|
// KeyFamilyPaymentBase are keys used within channels that will be |
|
// combined with per-state randomness to produce public keys that will |
|
// be used in scripts that pay directly to us without any delay. |
|
KeyFamilyPaymentBase KeyFamily = 3 |
|
|
|
// KeyFamilyDelayBase are keys used within channels that will be |
|
// combined with per-state randomness to produce public keys that will |
|
// be used in scripts that pay to us, but require a CSV delay before we |
|
// can sweep the funds. |
|
KeyFamilyDelayBase KeyFamily = 4 |
|
|
|
// KeyFamilyRevocationRoot is a family of keys which will be used to |
|
// derive the root of a revocation tree for a particular channel. |
|
KeyFamilyRevocationRoot KeyFamily = 5 |
|
|
|
// KeyFamilyNodeKey is a family of keys that will be used to derive |
|
// keys that will be advertised on the network to represent our current |
|
// "identity" within the network. Peers will need our latest node key |
|
// in order to establish a transport session with us on the Lightning |
|
// p2p level (BOLT-0008). |
|
KeyFamilyNodeKey KeyFamily = 6 |
|
|
|
// KeyFamilyStaticBackup is the family of keys that will be used to |
|
// derive keys that we use to encrypt and decrypt our set of static |
|
// backups. These backups may either be stored within watch towers for |
|
// a payment, or self stored on disk in a single file containing all |
|
// the static channel backups. |
|
KeyFamilyStaticBackup KeyFamily = 7 |
|
|
|
// KeyFamilyTowerSession is the family of keys that will be used to |
|
// derive session keys when negotiating sessions with watchtowers. The |
|
// session keys are limited to the lifetime of the session and are used |
|
// to increase privacy in the watchtower protocol. |
|
KeyFamilyTowerSession KeyFamily = 8 |
|
|
|
// KeyFamilyTowerID is the family of keys used to derive the public key |
|
// of a watchtower. This made distinct from the node key to offer a form |
|
// of rudimentary whitelisting, i.e. via knowledge of the pubkey, |
|
// preventing others from having full access to the tower just as a |
|
// result of knowing the node key. |
|
KeyFamilyTowerID KeyFamily = 9 |
|
) |
|
|
|
// KeyLocator is a two-tuple that can be used to derive *any* key that has ever |
|
// been used under the key derivation mechanisms described in this file. |
|
// Version 0 of our key derivation schema uses the following BIP43-like |
|
// derivation: |
|
// |
|
// * m/1017'/coinType'/keyFamily'/0/index |
|
// |
|
// Our purpose is 1017 (chosen arbitrary for now), and the coin type will vary |
|
// based on which coin/chain the channels are being created on. The key family |
|
// are actually just individual "accounts" in the nomenclature of BIP43. By |
|
// default we assume a branch of 0 (external). Finally, the key index (which |
|
// will vary per channel and use case) is the final element which allows us to |
|
// deterministically derive keys. |
|
type KeyLocator struct { |
|
// TODO(roasbeef): add the key scope as well?? |
|
|
|
// Family is the family of key being identified. |
|
Family KeyFamily |
|
|
|
// Index is the precise index of the key being identified. |
|
Index uint32 |
|
} |
|
|
|
// IsEmpty returns true if a KeyLocator is "empty". This may be the case where |
|
// we learn of a key from a remote party for a contract, but don't know the |
|
// precise details of its derivation (as we don't know the private key!). |
|
func (k KeyLocator) IsEmpty() bool { |
|
return k.Family == 0 && k.Index == 0 |
|
} |
|
|
|
// KeyDescriptor wraps a KeyLocator and also optionally includes a public key. |
|
// Either the KeyLocator must be non-empty, or the public key pointer be |
|
// non-nil. This will be used by the KeyRing interface to lookup arbitrary |
|
// private keys, and also within the SignDescriptor struct to locate precisely |
|
// which keys should be used for signing. |
|
type KeyDescriptor struct { |
|
// KeyLocator is the internal KeyLocator of the descriptor. |
|
KeyLocator |
|
|
|
// PubKey is an optional public key that fully describes a target key. |
|
// If this is nil, the KeyLocator MUST NOT be empty. |
|
PubKey *btcec.PublicKey |
|
} |
|
|
|
// KeyRing is the primary interface that will be used to perform public |
|
// derivation of various keys used within the peer-to-peer network, and also |
|
// within any created contracts. All derivation required by the KeyRing is |
|
// based off of public derivation, so a system with only an extended public key |
|
// (for the particular purpose+family) can derive this set of keys. |
|
type KeyRing interface { |
|
// DeriveNextKey attempts to derive the *next* key within the key |
|
// family (account in BIP43) specified. This method should return the |
|
// next external child within this branch. |
|
DeriveNextKey(keyFam KeyFamily) (KeyDescriptor, 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 KeyLocator) (KeyDescriptor, error) |
|
} |
|
|
|
// SecretKeyRing is a ring similar to the regular KeyRing interface, but it is |
|
// also able to derive *private keys*. As this is a super-set of the regular |
|
// KeyRing, we also expect the SecretKeyRing to implement the fully KeyRing |
|
// interface. The methods in this struct may be used to extract the node key in |
|
// order to accept inbound network connections, or to do manual signing for |
|
// recovery purposes. |
|
type SecretKeyRing interface { |
|
KeyRing |
|
|
|
ECDHRing |
|
|
|
DigestSignerRing |
|
|
|
// DerivePrivKey attempts to derive the private key that corresponds to |
|
// the passed key descriptor. If the public key is set, then this |
|
// method will perform an in-order scan over the key set, with a max of |
|
// MaxKeyRangeScan keys. In order for this to work, the caller MUST set |
|
// the KeyFamily within the partially populated KeyLocator. |
|
DerivePrivKey(keyDesc KeyDescriptor) (*btcec.PrivateKey, error) |
|
} |
|
|
|
// DigestSignerRing is an interface that abstracts away basic low-level ECDSA |
|
// signing on keys within a key ring. |
|
type DigestSignerRing interface { |
|
// SignDigest signs the given SHA256 message digest with the private key |
|
// described in the key descriptor. |
|
SignDigest(keyDesc KeyDescriptor, digest [32]byte) (*btcec.Signature, |
|
error) |
|
|
|
// SignDigestCompact signs the given SHA256 message digest with the |
|
// private key described in the key descriptor and returns the signature |
|
// in the compact, public key recoverable format. |
|
SignDigestCompact(keyDesc KeyDescriptor, digest [32]byte) ([]byte, error) |
|
} |
|
|
|
// SingleKeyDigestSigner is an abstraction interface that hides the |
|
// implementation of the low-level ECDSA signing operations by wrapping a |
|
// single, specific private key. |
|
type SingleKeyDigestSigner interface { |
|
// PubKey returns the public key of the wrapped private key. |
|
PubKey() *btcec.PublicKey |
|
|
|
// SignDigest signs the given SHA256 message digest with the wrapped |
|
// private key. |
|
SignDigest(digest [32]byte) (*btcec.Signature, error) |
|
|
|
// SignDigestCompact signs the given SHA256 message digest with the |
|
// wrapped private key and returns the signature in the compact, public |
|
// key recoverable format. |
|
SignDigestCompact(digest [32]byte) ([]byte, error) |
|
} |
|
|
|
// ECDHRing is an interface that abstracts away basic low-level ECDH shared key |
|
// generation on keys within a key ring. |
|
type ECDHRing interface { |
|
// 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()) |
|
ECDH(keyDesc KeyDescriptor, pubKey *btcec.PublicKey) ([32]byte, error) |
|
} |
|
|
|
// SingleKeyECDH is an abstraction interface that hides the implementation of an |
|
// ECDH operation by wrapping a single, specific private key. |
|
type SingleKeyECDH interface { |
|
// PubKey returns the public key of the wrapped private key. |
|
PubKey() *btcec.PublicKey |
|
|
|
// ECDH performs a scalar multiplication (ECDH-like operation) between |
|
// the wrapped private key and 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) |
|
} |
|
|
|
// TODO(roasbeef): extend to actually support scalar mult of key? |
|
// * would allow to push in initial handshake auth into interface as well
|
|
|