github.com/decred/dcrlnd@v0.7.6/keychain/hdkeyring.go (about) 1 package keychain 2 3 import ( 4 "crypto/sha256" 5 "errors" 6 "fmt" 7 8 "github.com/decred/dcrd/chaincfg/chainhash" 9 "github.com/decred/dcrd/dcrec/secp256k1/v4" 10 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 11 "github.com/decred/dcrd/hdkeychain/v3" 12 ) 13 14 var errPubOnlyKeyRing = errors.New("keyring configured as pubkey only") 15 16 // HDKeyRing is an implementation of both the KeyRing and SecretKeyRing 17 // interfaces backed by a root master key pair. The master extended public keys 18 // (one for each required key family) is maintained in memory at all times, 19 // while the extended private key must be produred by a function (specified 20 // during struct setup) whenever requested. 21 type HDKeyRing struct { 22 masterPubs map[KeyFamily]*hdkeychain.ExtendedKey 23 fetchMasterPriv func(KeyFamily) (*hdkeychain.ExtendedKey, error) 24 nextIndex func(KeyFamily) (uint32, error) 25 } 26 27 // Compile time type assertions to ensure HDKeyRing fulfills the desired 28 // interfaces. 29 var _ KeyRing = (*HDKeyRing)(nil) 30 var _ SecretKeyRing = (*HDKeyRing)(nil) 31 32 // NewHDKeyRing creates a new implementation of the keychain.SecretKeyRing 33 // interface backed by a set of extended HD keys. 34 // 35 // The passed fetchMasterPriv must be able to return the master private key for 36 // the keyring in a timely fashion, otherwise sign operations may be delayed. 37 // If this function is not specified, then the KeyRing cannot derive private 38 // keys. 39 // 40 // The passed nextIndex must be able to return the next (unused) index for each 41 // existing KeyFamily used in ln operations. Indication that the index was 42 // returned should be persisted in some way, such that public key reuse is 43 // minimized and the same index is not returned twice. In other words, calling 44 // nextAddrIndex twice should return different values, otherwise key derivation 45 // might hang forever. 46 // 47 // If either the set of master public keys (one for each family) or the next 48 // address index are not provided, the results from trying to use this function 49 // are undefined. 50 func NewHDKeyRing(masterPubs map[KeyFamily]*hdkeychain.ExtendedKey, 51 fetchMasterPriv func(KeyFamily) (*hdkeychain.ExtendedKey, error), 52 nextIndex func(KeyFamily) (uint32, error)) *HDKeyRing { 53 54 return &HDKeyRing{ 55 masterPubs: masterPubs, 56 fetchMasterPriv: fetchMasterPriv, 57 nextIndex: nextIndex, 58 } 59 } 60 61 // DeriveNextKey attempts to derive the *next* key within the key family 62 // (account in BIP43) specified. This method should return the next external 63 // child within this branch. 64 // 65 // NOTE: This is part of the keychain.KeyRing interface. 66 func (kr *HDKeyRing) DeriveNextKey(keyFam KeyFamily) (KeyDescriptor, error) { 67 68 masterPub := kr.masterPubs[keyFam] 69 70 if masterPub == nil { 71 return KeyDescriptor{}, fmt.Errorf("invalid key family %d", keyFam) 72 } 73 74 for { 75 // Derive the key and skip to next if invalid. 76 index, err := kr.nextIndex(keyFam) 77 if err != nil { 78 return KeyDescriptor{}, err 79 } 80 indexKey, err := masterPub.Child(index) 81 82 if err == hdkeychain.ErrInvalidChild { 83 continue 84 } 85 if err != nil { 86 return KeyDescriptor{}, err 87 } 88 89 pubkey, err := secp256k1.ParsePubKey(indexKey.SerializedPubKey()) 90 if err != nil { 91 return KeyDescriptor{}, err 92 } 93 94 return KeyDescriptor{ 95 PubKey: pubkey, 96 KeyLocator: KeyLocator{ 97 Family: keyFam, 98 Index: index, 99 }, 100 }, nil 101 } 102 } 103 104 // DeriveKey attempts to derive an arbitrary key specified by the passed 105 // KeyLocator. This may be used in several recovery scenarios, or when manually 106 // rotating something like our current default node key. 107 // 108 // NOTE: This is part of the keychain.KeyRing interface. 109 func (kr HDKeyRing) DeriveKey(keyLoc KeyLocator) (KeyDescriptor, error) { 110 masterPub := kr.masterPubs[keyLoc.Family] 111 if masterPub == nil { 112 return KeyDescriptor{}, fmt.Errorf("masterpub for keyfamily %d does not exist", keyLoc.Family) 113 } 114 key, err := masterPub.Child(keyLoc.Index) 115 if err != nil { 116 return KeyDescriptor{}, err 117 } 118 pubKey, err := secp256k1.ParsePubKey(key.SerializedPubKey()) 119 if err != nil { 120 return KeyDescriptor{}, err 121 } 122 123 return KeyDescriptor{ 124 KeyLocator: keyLoc, 125 PubKey: pubKey, 126 }, nil 127 } 128 129 // DerivePrivKey attempts to derive the private key that corresponds to the 130 // passed key descriptor. 131 // 132 // NOTE: This is part of the keychain.SecretKeyRing interface. 133 func (kr *HDKeyRing) DerivePrivKey(keyDesc KeyDescriptor) (*secp256k1.PrivateKey, error) { 134 135 if kr.fetchMasterPriv == nil { 136 return nil, errPubOnlyKeyRing 137 } 138 139 // If the public key isn't set or they have a non-zero index, 140 // then we know that the caller instead knows the derivation 141 // path for a key. 142 if keyDesc.PubKey == nil || keyDesc.Index > 0 { 143 // We'll grab the master pub key for the provided account (family) then 144 // manually derive the addresses here. 145 masterPriv, err := kr.fetchMasterPriv(keyDesc.Family) 146 if err != nil { 147 return nil, err 148 } 149 150 exPrivKey, err := masterPriv.Child(keyDesc.Index) 151 if err != nil { 152 return nil, err 153 } 154 serPrivKey, err := exPrivKey.SerializedPrivKey() 155 if err != nil { 156 return nil, err 157 } 158 return secp256k1.PrivKeyFromBytes(serPrivKey), nil 159 } 160 161 // If the request sent a nonzero keyfamily, we only check that one. 162 // Otherwise, we'll derive pubkeys for every keyfamily. 163 familyStart, familyEnd := 0, int(KeyFamilyLastKF) 164 if keyDesc.Family != 0 { 165 familyStart = int(keyDesc.Family) 166 familyEnd = familyStart 167 } 168 169 // If the public key isn't nil, then this indicates that we 170 // need to scan for the private key. 171 for family := familyStart; family <= familyEnd; family += 1 { 172 masterPriv, err := kr.fetchMasterPriv(KeyFamily(family)) 173 if err != nil { 174 return nil, err 175 } 176 177 if masterPriv == nil { 178 return nil, fmt.Errorf("masterPriv for key family %d not found", family) 179 } 180 181 for i := 0; i < MaxKeyRangeScan; i++ { 182 // Derive the next key in the range and fetch its 183 // managed address. 184 privKey, err := masterPriv.Child(uint32(i)) 185 if err == hdkeychain.ErrInvalidChild { 186 continue 187 } 188 189 if err != nil { 190 return nil, err 191 } 192 193 pubKey, err := secp256k1.ParsePubKey(privKey.SerializedPubKey()) 194 if err != nil { 195 // simply skip invalid keys here 196 continue 197 } 198 199 if keyDesc.PubKey.IsEqual(pubKey) { 200 serPriv, err := privKey.SerializedPrivKey() 201 if err != nil { 202 return nil, err 203 } 204 return secp256k1.PrivKeyFromBytes(serPriv), nil 205 } 206 } 207 } 208 209 return nil, ErrCannotDerivePrivKey 210 } 211 212 // ECDH performs a scalar multiplication (ECDH-like operation) between the 213 // target key descriptor and remote public key. The output returned will be the 214 // sha256 of the resulting shared point serialized in compressed format. If k 215 // is our private key, and P is the public key, we perform the following 216 // operation: 217 // 218 // sx := k*P 219 // s := sha256(sx.SerializeCompressed()) 220 // 221 // NOTE: This is part of the keychain.ECDHRing interface. 222 func (kr *HDKeyRing) ECDH(keyDesc KeyDescriptor, 223 pub *secp256k1.PublicKey) ([32]byte, error) { 224 225 privKey, err := kr.DerivePrivKey(keyDesc) 226 if err != nil { 227 return [32]byte{}, err 228 229 } 230 231 // Privkey to ModNScalar. 232 var privKeyModn secp256k1.ModNScalar 233 privKeyModn.SetByteSlice(privKey.Serialize()) 234 235 // Pubkey to JacobianPoint. 236 var pubJacobian, res secp256k1.JacobianPoint 237 pub.AsJacobian(&pubJacobian) 238 239 // Calculate shared point and ensure it's on the curve. 240 secp256k1.ScalarMultNonConst(&privKeyModn, &pubJacobian, &res) 241 res.ToAffine() 242 sharedPub := secp256k1.NewPublicKey(&res.X, &res.Y) 243 if !sharedPub.IsOnCurve() { 244 return [32]byte{}, fmt.Errorf("Derived ECDH point is not on the secp256k1 curve") 245 } 246 247 // Hash of the serialized point is the shared secret. 248 h := sha256.Sum256(sharedPub.SerializeCompressed()) 249 250 return h, nil 251 252 } 253 254 // SignMessage signs the given message, single or double chainhashsing it 255 // first, with the private key described in the key descriptor. 256 // 257 // NOTE: This is part of the keychain.DigestSignerRing interface. 258 func (kr *HDKeyRing) SignMessage(keyLoc KeyLocator, 259 msg []byte, doubleHash bool) (*ecdsa.Signature, error) { 260 261 privKey, err := kr.DerivePrivKey(KeyDescriptor{ 262 KeyLocator: keyLoc, 263 }) 264 if err != nil { 265 return nil, err 266 267 } 268 269 var digest []byte 270 if doubleHash { 271 return nil, fmt.Errorf("dcrlnd does not do doubleHash signing") 272 } else { 273 digest = chainhash.HashB(msg) 274 } 275 return ecdsa.Sign(privKey, digest), nil 276 } 277 278 // SignMessageCompact signs the given message, single or double chainhash hashing 279 // it first, with the private key described in the key descriptor and returns 280 // the signature in the compact, public key recoverable format. 281 // 282 // NOTE: This is part of the keychain.DigestSignerRing interface. 283 func (kr *HDKeyRing) SignMessageCompact(keyLoc KeyLocator, 284 msg []byte, doubleHash bool) ([]byte, error) { 285 286 privKey, err := kr.DerivePrivKey(KeyDescriptor{ 287 KeyLocator: keyLoc, 288 }) 289 if err != nil { 290 return nil, err 291 292 } 293 294 var digest []byte 295 if doubleHash { 296 digest1 := chainhash.HashB(msg) 297 digest = chainhash.HashB(digest1) 298 } else { 299 digest = chainhash.HashB(msg) 300 } 301 return ecdsa.SignCompact(privKey, digest[:], true), nil 302 }