github.com/mit-dci/lit@v0.0.0-20221102210550-8c3d3b49f2ce/wallit/keyderiv.go (about) 1 package wallit 2 3 import ( 4 "github.com/mit-dci/lit/btcutil" 5 "github.com/mit-dci/lit/crypto/koblitz" 6 "github.com/mit-dci/lit/logging" 7 "github.com/mit-dci/lit/portxo" 8 ) 9 10 /* 11 Key derivation for a TxStore has 3 levels: use case, peer index, and keyindex. 12 Regular wallet addresses are use 0, peer 0, and then a linear index. 13 The identity key is use 11, peer 0, index 0. 14 Channel multisig keys are use 2, peer and index per peer and channel. 15 Channel refund keys are use 3, peer and index per peer / channel. 16 */ 17 18 // ===================================================================== 19 // OK only use these now 20 21 // PathPrivkey returns a private key by descending the given path 22 // Returns nil if there's an error. 23 func (w *Wallit) PathPrivkey(kg portxo.KeyGen) *koblitz.PrivateKey { 24 // in uspv, we require path depth of 5 25 if kg.Depth != 5 { 26 return nil 27 } 28 priv, err := kg.DerivePrivateKey(w.rootPrivKey) 29 if err != nil { 30 logging.Errorf("PathPrivkey err %s", err.Error()) 31 return nil 32 } 33 return priv 34 } 35 36 // PathPubkey returns a public key by descending the given path. 37 // Returns nil if there's an error. 38 func (w *Wallit) PathPubkey(kg portxo.KeyGen) *koblitz.PublicKey { 39 priv := w.PathPrivkey(kg) 40 if priv == nil { 41 return nil 42 } 43 return w.PathPrivkey(kg).PubKey() 44 } 45 46 // PathPubHash160 returns a 20 byte pubkey hash for the given path 47 // It'll always return 20 bytes, or a nil if there's an error. 48 func (w *Wallit) PathPubHash160(kg portxo.KeyGen) [20]byte { 49 var pkh [20]byte 50 pub := w.PathPubkey(kg) 51 if pub == nil { 52 return pkh 53 } 54 copy(pkh[:], btcutil.Hash160(pub.SerializeCompressed())) 55 56 return pkh 57 } 58 59 // ------------- end of 2 main key deriv functions 60 61 // get a private key from the regular wallet 62 func (w *Wallit) GetWalletPrivkey(idx uint32) *koblitz.PrivateKey { 63 var kg portxo.KeyGen 64 kg.Depth = 5 65 kg.Step[0] = 44 | 1<<31 66 kg.Step[1] = w.Param.HDCoinType | 1<<31 67 kg.Step[2] = 0 | 1<<31 68 kg.Step[3] = 0 | 1<<31 69 kg.Step[4] = idx | 1<<31 70 return w.PathPrivkey(kg) 71 } 72 73 // GetWalletKeygen returns the keygen for a standard wallet address 74 func GetWalletKeygen(idx, cointype uint32) portxo.KeyGen { 75 var kg portxo.KeyGen 76 kg.Depth = 5 77 kg.Step[0] = 44 | 1<<31 78 kg.Step[1] = cointype | 1<<31 79 kg.Step[2] = 0 | 1<<31 80 kg.Step[3] = 0 | 1<<31 81 kg.Step[4] = idx | 1<<31 82 return kg 83 } 84 85 // GetUsePrive generates a private key for the given use case & keypath 86 func (w *Wallit) GetUsePriv(kg portxo.KeyGen, use uint32) *koblitz.PrivateKey { 87 kg.Step[2] = use 88 return w.PathPrivkey(kg) 89 } 90 91 // GetUsePub generates a pubkey for the given use case & keypath 92 func (w *Wallit) GetUsePub(kg portxo.KeyGen, use uint32) [33]byte { 93 var b [33]byte 94 pub := w.GetUsePriv(kg, use).PubKey() 95 if pub != nil { 96 copy(b[:], pub.SerializeCompressed()) 97 } 98 return b 99 }