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  }