github.com/decred/dcrlnd@v0.7.6/keychain/derivation.go (about)

     1  package keychain
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/decred/dcrd/dcrec/secp256k1/v4"
     7  	"github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa"
     8  )
     9  
    10  const (
    11  	// KeyDerivationVersion is the version of the key derivation schema
    12  	// defined below. We use a version as this means that we'll be able to
    13  	// accept new seed in the future and be able to discern if the software
    14  	// is compatible with the version of the seed.
    15  	KeyDerivationVersion = 0
    16  
    17  	// BIP0043Purpose is the "purpose" value that we'll use for the first
    18  	// version or our key derivation scheme. All keys are expected to be
    19  	// derived from this purpose, then the particular coin type of the
    20  	// chain where the keys are to be used.  Slightly adhering to BIP0043
    21  	// allows us to not deviate too far from a widely used standard, and
    22  	// also fits into existing implementations of the BIP's template.
    23  	//
    24  	// NOTE: BRICK SQUUUUUAD.
    25  	BIP0043Purpose = 1017
    26  )
    27  
    28  const (
    29  	// CoinTypeDecred specifies the BIP44 coin type for Decred key
    30  	// derivation.
    31  	CoinTypeDecred uint32 = 42
    32  
    33  	// CoinTypeTestnet specifies the BIP44 coin
    34  	// type for all testnet key derivation.
    35  	CoinTypeTestnet = 1
    36  )
    37  
    38  var (
    39  	// MaxKeyRangeScan is the maximum number of keys that we'll attempt to
    40  	// scan with if a caller knows the public key, but not the KeyLocator
    41  	// and wishes to derive a private key.
    42  	MaxKeyRangeScan = 100000
    43  
    44  	// ErrCannotDerivePrivKey is returned when DerivePrivKey is unable to
    45  	// derive a private key given only the public key and target key
    46  	// family.
    47  	ErrCannotDerivePrivKey = fmt.Errorf("unable to derive private key")
    48  )
    49  
    50  // KeyFamily represents a "family" of keys that will be used within various
    51  // contracts created by lnd. These families are meant to be distinct branches
    52  // within the HD key chain of the backing wallet. Usage of key families within
    53  // the interface below are strict in order to promote integrability and the
    54  // ability to restore all keys given a user master seed backup.
    55  //
    56  // The key derivation in this file follows the following hierarchy based on
    57  // BIP43:
    58  //
    59  //   - m/1017'/coinType'/keyFamily'/0/index
    60  type KeyFamily uint32
    61  
    62  const (
    63  	// KeyFamilyMultiSig are keys to be used within multi-sig scripts.
    64  	KeyFamilyMultiSig KeyFamily = 0
    65  
    66  	// KeyFamilyRevocationBase are keys that are used within channels to
    67  	// create revocation basepoints that the remote party will use to
    68  	// create revocation keys for us.
    69  	KeyFamilyRevocationBase KeyFamily = 1
    70  
    71  	// KeyFamilyHtlcBase are keys used within channels that will be
    72  	// combined with per-state randomness to produce public keys that will
    73  	// be used in HTLC scripts.
    74  	KeyFamilyHtlcBase KeyFamily = 2
    75  
    76  	// KeyFamilyPaymentBase are keys used within channels that will be
    77  	// combined with per-state randomness to produce public keys that will
    78  	// be used in scripts that pay directly to us without any delay.
    79  	KeyFamilyPaymentBase KeyFamily = 3
    80  
    81  	// KeyFamilyDelayBase are keys used within channels that will be
    82  	// combined with per-state randomness to produce public keys that will
    83  	// be used in scripts that pay to us, but require a CSV delay before we
    84  	// can sweep the funds.
    85  	KeyFamilyDelayBase KeyFamily = 4
    86  
    87  	// KeyFamilyRevocationRoot is a family of keys which will be used to
    88  	// derive the root of a revocation tree for a particular channel.
    89  	KeyFamilyRevocationRoot KeyFamily = 5
    90  
    91  	// KeyFamilyNodeKey is a family of keys that will be used to derive
    92  	// keys that will be advertised on the network to represent our current
    93  	// "identity" within the network. Peers will need our latest node key
    94  	// in order to establish a transport session with us on the Lightning
    95  	// p2p level (BOLT-0008).
    96  	KeyFamilyNodeKey KeyFamily = 6
    97  
    98  	// KeyFamilyStaticBackup is the family of keys that will be used to
    99  	// derive keys that we use to encrypt and decrypt our set of static
   100  	// backups. These backups may either be stored within watch towers for
   101  	// a payment, or self stored on disk in a single file containing all
   102  	// the static channel backups.
   103  	KeyFamilyStaticBackup KeyFamily = 7
   104  
   105  	// KeyFamilyTowerSession is the family of keys that will be used to
   106  	// derive session keys when negotiating sessions with watchtowers. The
   107  	// session keys are limited to the lifetime of the session and are used
   108  	// to increase privacy in the watchtower protocol.
   109  	KeyFamilyTowerSession KeyFamily = 8
   110  
   111  	// KeyFamilyTowerID is the family of keys used to derive the public key
   112  	// of a watchtower. This made distinct from the node key to offer a form
   113  	// of rudimentary whitelisting, i.e. via knowledge of the pubkey,
   114  	// preventing others from having full access to the tower just as a
   115  	// result of knowing the node key.
   116  	KeyFamilyTowerID KeyFamily = 9
   117  
   118  	// KeyFamilyLastKF holds the last defined key family.
   119  	KeyFamilyLastKF = KeyFamilyTowerID
   120  )
   121  
   122  // VersionZeroKeyFamilies is a slice of all the known key families for first
   123  // version of the key derivation schema defined in this package.
   124  var VersionZeroKeyFamilies = []KeyFamily{
   125  	KeyFamilyMultiSig,
   126  	KeyFamilyRevocationBase,
   127  	KeyFamilyHtlcBase,
   128  	KeyFamilyPaymentBase,
   129  	KeyFamilyDelayBase,
   130  	KeyFamilyRevocationRoot,
   131  	KeyFamilyNodeKey,
   132  	KeyFamilyStaticBackup,
   133  	KeyFamilyTowerSession,
   134  	KeyFamilyTowerID,
   135  }
   136  
   137  // KeyLocator is a two-tuple that can be used to derive *any* key that has ever
   138  // been used under the key derivation mechanisms described in this file.
   139  // Version 0 of our key derivation schema uses the following BIP43-like
   140  // derivation:
   141  //
   142  //   - m/1017'/coinType'/keyFamily'/0/index
   143  //
   144  // Our purpose is 1017 (chosen arbitrary for now), and the coin type will vary
   145  // based on which coin/chain the channels are being created on. The key family
   146  // are actually just individual "accounts" in the nomenclature of BIP43. By
   147  // default we assume a branch of 0 (external). Finally, the key index (which
   148  // will vary per channel and use case) is the final element which allows us to
   149  // deterministically derive keys.
   150  type KeyLocator struct {
   151  	// TODO(roasbeef): add the key scope as well??
   152  
   153  	// Family is the family of key being identified.
   154  	Family KeyFamily
   155  
   156  	// Index is the precise index of the key being identified.
   157  	Index uint32
   158  }
   159  
   160  // IsEmpty returns true if a KeyLocator is "empty". This may be the case where
   161  // we learn of a key from a remote party for a contract, but don't know the
   162  // precise details of its derivation (as we don't know the private key!).
   163  func (k KeyLocator) IsEmpty() bool {
   164  	return k.Family == 0 && k.Index == 0
   165  }
   166  
   167  // KeyDescriptor wraps a KeyLocator and also optionally includes a public key.
   168  // Either the KeyLocator must be non-empty, or the public key pointer be
   169  // non-nil. This will be used by the KeyRing interface to lookup arbitrary
   170  // private keys, and also within the SignDescriptor struct to locate precisely
   171  // which keys should be used for signing.
   172  type KeyDescriptor struct {
   173  	// KeyLocator is the internal KeyLocator of the descriptor.
   174  	KeyLocator
   175  
   176  	// PubKey is an optional public key that fully describes a target key.
   177  	// If this is nil, the KeyLocator MUST NOT be empty.
   178  	PubKey *secp256k1.PublicKey
   179  }
   180  
   181  // KeyRing is the primary interface that will be used to perform public
   182  // derivation of various keys used within the peer-to-peer network, and also
   183  // within any created contracts. All derivation required by the KeyRing is
   184  // based off of public derivation, so a system with only an extended public key
   185  // (for the particular purpose+family) can derive this set of keys.
   186  type KeyRing interface {
   187  	// DeriveNextKey attempts to derive the *next* key within the key
   188  	// family (account in BIP43) specified. This method should return the
   189  	// next external child within this branch.
   190  	DeriveNextKey(keyFam KeyFamily) (KeyDescriptor, error)
   191  
   192  	// DeriveKey attempts to derive an arbitrary key specified by the
   193  	// passed KeyLocator. This may be used in several recovery scenarios,
   194  	// or when manually rotating something like our current default node
   195  	// key.
   196  	DeriveKey(keyLoc KeyLocator) (KeyDescriptor, error)
   197  }
   198  
   199  // SecretKeyRing is a ring similar to the regular KeyRing interface, but it is
   200  // also able to derive *private keys*. As this is a super-set of the regular
   201  // KeyRing, we also expect the SecretKeyRing to implement the fully KeyRing
   202  // interface. The methods in this struct may be used to extract the node key in
   203  // order to accept inbound network connections, or to do manual signing for
   204  // recovery purposes.
   205  type SecretKeyRing interface {
   206  	KeyRing
   207  
   208  	ECDHRing
   209  
   210  	MessageSignerRing
   211  
   212  	// DerivePrivKey attempts to derive the private key that corresponds to
   213  	// the passed key descriptor.  If the public key is set, then this
   214  	// method will perform an in-order scan over the key set, with a max of
   215  	// MaxKeyRangeScan keys. In order for this to work, the caller MUST set
   216  	// the KeyFamily within the partially populated KeyLocator.
   217  	DerivePrivKey(keyDesc KeyDescriptor) (*secp256k1.PrivateKey, error)
   218  }
   219  
   220  // MessageSignerRing is an interface that abstracts away basic low-level ECDSA
   221  // signing on keys within a key ring.
   222  type MessageSignerRing interface {
   223  	// SignMessage signs the given message, single or double SHA256 hashing
   224  	// it first, with the private key described in the key locator.
   225  	SignMessage(keyLoc KeyLocator, msg []byte,
   226  		doubleHash bool) (*ecdsa.Signature, error)
   227  
   228  	// SignMessageCompact signs the given message, single or double SHA256
   229  	// hashing it first, with the private key described in the key locator
   230  	// and returns the signature in the compact, public key recoverable
   231  	// format.
   232  	SignMessageCompact(keyLoc KeyLocator, msg []byte,
   233  		doubleHash bool) ([]byte, error)
   234  }
   235  
   236  // SingleKeyMessageSigner is an abstraction interface that hides the
   237  // implementation of the low-level ECDSA signing operations by wrapping a
   238  // single, specific private key.
   239  type SingleKeyMessageSigner interface {
   240  	// PubKey returns the public key of the wrapped private key.
   241  	PubKey() *secp256k1.PublicKey
   242  
   243  	// KeyLocator returns the locator that describes the wrapped private
   244  	// key.
   245  	KeyLocator() KeyLocator
   246  
   247  	// SignMessage signs the given message, single or double SHA256 hashing
   248  	// it first, with the wrapped private key.
   249  	SignMessage(message []byte, doubleHash bool) (*ecdsa.Signature, error)
   250  
   251  	// SignMessageCompact signs the given message, single or double SHA256
   252  	// hashing it first, with the wrapped private key and returns the
   253  	// signature in the compact, public key recoverable format.
   254  	SignMessageCompact(message []byte, doubleHash bool) ([]byte, error)
   255  }
   256  
   257  // ECDHRing is an interface that abstracts away basic low-level ECDH shared key
   258  // generation on keys within a key ring.
   259  type ECDHRing interface {
   260  	// ECDH performs a scalar multiplication (ECDH-like operation) between
   261  	// the target key descriptor and remote public key. The output
   262  	// returned will be the sha256 of the resulting shared point serialized
   263  	// in compressed format. If k is our private key, and P is the public
   264  	// key, we perform the following operation:
   265  	//
   266  	//  sx := k*P
   267  	//  s := sha256(sx.SerializeCompressed())
   268  	ECDH(keyDesc KeyDescriptor, pubKey *secp256k1.PublicKey) ([32]byte, error)
   269  }
   270  
   271  // SingleKeyECDH is an abstraction interface that hides the implementation of an
   272  // ECDH operation by wrapping a single, specific private key.
   273  type SingleKeyECDH interface {
   274  	// PubKey returns the public key of the wrapped private key.
   275  	PubKey() *secp256k1.PublicKey
   276  
   277  	// ECDH performs a scalar multiplication (ECDH-like operation) between
   278  	// the wrapped private key and remote public key. The output returned
   279  	// will be the sha256 of the resulting shared point serialized in
   280  	// compressed format.
   281  	ECDH(pubKey *secp256k1.PublicKey) ([32]byte, error)
   282  }
   283  
   284  // TODO(roasbeef): extend to actually support scalar mult of key?
   285  //  * would allow to push in initial handshake auth into interface as well