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 }