diff --git a/crypto/keys/keybase.go b/crypto/keys/keybase.go index 8f65fb3615c2..38dd705e922c 100644 --- a/crypto/keys/keybase.go +++ b/crypto/keys/keybase.go @@ -2,6 +2,7 @@ package keys import ( "bufio" + "encoding/hex" "fmt" "os" "reflect" @@ -132,6 +133,11 @@ func (kb dbKeybase) CreateAccount(name, mnemonic, bip39Passwd, encryptPasswd str } func (kb dbKeybase) Derive(name, mnemonic, bip39Passphrase, encryptPasswd string, params hd.BIP44Params) (info Info, err error) { + if !strings.Contains(mnemonic, " ") { + info, err = kb.persistDerivedKeyByPrivKey(mnemonic, encryptPasswd, name) + return + } + seed, err := bip39.NewSeedWithErrorChecking(mnemonic, bip39Passphrase) if err != nil { return @@ -505,3 +511,52 @@ func addrKey(address types.AccAddress) []byte { func infoKey(name string) []byte { return []byte(fmt.Sprintf("%s.%s", name, infoSuffix)) } + + +func encode(derivedPriv [32]byte) string { + src := make([]byte, len(derivedPriv)) + for idx, m := range derivedPriv { + src[idx] = m + } + dst := make([]byte, hex.EncodedLen(len(src))) + hex.Encode(dst, src) + return string(dst) +} + +func decode(key string) [32]byte { + src := []byte(key) + dst := make([]byte, hex.DecodedLen(len(src))) + n, err := hex.Decode(dst, src) + if err != nil { + panic(err) + } + + if n != 32 { + panic("invalid input!") + } + + var res [32]byte + for idx, m := range dst { + res[idx] = m + } + + return res +} + +func (kb *dbKeybase) persistDerivedKeyByPrivKey(privKey string, passwd, name string) (info Info, err error) { + + derivedPriv := decode(privKey) + keyStr := encode(derivedPriv) + if privKey != keyStr { + panic("invalid private key") + } + // if we have a password, use it to encrypt the private key and store it + // else store the public key only + if passwd != "" { + info = kb.writeLocalKey(name, secp256k1.PrivKeySecp256k1(derivedPriv), passwd) + } else { + pubk := secp256k1.PrivKeySecp256k1(derivedPriv).PubKey() + info = kb.writeOfflineKey(name, pubk) + } + return +} \ No newline at end of file