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