github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/portxo/derive.go (about)

     1  package portxo
     2  
     3  import (
     4  	"fmt"
     5  	"math/big"
     6  
     7  	"github.com/mit-dci/lit/btcutil/hdkeychain"
     8  	"github.com/mit-dci/lit/crypto/koblitz"
     9  )
    10  
    11  // DerivePrivateKey returns the private key for a utxo based on a master key
    12  func (kg *KeyGen) DerivePrivateKey(
    13  	m *hdkeychain.ExtendedKey) (*koblitz.PrivateKey, error) {
    14  
    15  	var err error
    16  	var empty [32]byte
    17  
    18  	if m == nil {
    19  		return nil, fmt.Errorf("nil master key")
    20  	}
    21  	// there might be a private key here, but it can't be "derived"
    22  	if kg.Depth == 0 {
    23  		return nil, fmt.Errorf("no key derivation path")
    24  	}
    25  
    26  	currentKey := m
    27  	// this doesn't check for depth > 5, which is kindof invalid...
    28  	for i, step := range kg.Step {
    29  		if uint8(i) == kg.Depth {
    30  			break
    31  		}
    32  		currentKey, err = currentKey.Child(step)
    33  		if err != nil {
    34  			return nil, err
    35  		}
    36  	}
    37  
    38  	// get private key from the final derived child key
    39  	derivedPrivKey, err := currentKey.ECPrivKey()
    40  	if err != nil {
    41  		return nil, err
    42  	}
    43  
    44  	// if porTxo's private key has something in it, combine that with derived key
    45  	// using the delinearization scheme
    46  	if kg.PrivKey != empty {
    47  		PrivKeyAddBytes(derivedPrivKey, kg.PrivKey[:])
    48  	}
    49  
    50  	// done, return derived sum
    51  	return derivedPrivKey, nil
    52  }
    53  
    54  // PrivKeyAddBytes adds bytes to a private key.
    55  // NOTE that this modifies the key in place, overwriting it!!!!1
    56  // If k is nil, does nothing and doesn't error (k stays nil)
    57  func PrivKeyAddBytes(k *koblitz.PrivateKey, b []byte) {
    58  	if k == nil {
    59  		return
    60  	}
    61  	// turn arg bytes into a bigint
    62  	arg := new(big.Int).SetBytes(b)
    63  	// add private key to arg
    64  	k.D.Add(k.D, arg)
    65  	// mod 2^256ish
    66  	k.D.Mod(k.D, koblitz.S256().N)
    67  	// new key derived from this sum
    68  	// D is already modified, need to update the pubkey x and y
    69  	k.X, k.Y = koblitz.S256().ScalarBaseMult(k.D.Bytes())
    70  	return
    71  }