github.com/cosmos/cosmos-sdk@v0.50.1/crypto/keyring/keyring.go (about)

     1  package keyring
     2  
     3  import (
     4  	"bufio"
     5  	"encoding/hex"
     6  	"fmt"
     7  	"io"
     8  	"os"
     9  	"path/filepath"
    10  	"sort"
    11  	"strings"
    12  
    13  	"github.com/99designs/keyring"
    14  	"github.com/cockroachdb/errors"
    15  	"github.com/cosmos/go-bip39"
    16  	"golang.org/x/crypto/bcrypt"
    17  
    18  	errorsmod "cosmossdk.io/errors"
    19  
    20  	"github.com/cosmos/cosmos-sdk/client/input"
    21  	"github.com/cosmos/cosmos-sdk/codec"
    22  	"github.com/cosmos/cosmos-sdk/crypto"
    23  	"github.com/cosmos/cosmos-sdk/crypto/hd"
    24  	"github.com/cosmos/cosmos-sdk/crypto/ledger"
    25  	"github.com/cosmos/cosmos-sdk/crypto/types"
    26  	sdk "github.com/cosmos/cosmos-sdk/types"
    27  	sdkerrors "github.com/cosmos/cosmos-sdk/types/errors"
    28  	"github.com/cosmos/cosmos-sdk/types/tx/signing"
    29  )
    30  
    31  // Backend options for Keyring
    32  const (
    33  	BackendFile    = "file"
    34  	BackendOS      = "os"
    35  	BackendKWallet = "kwallet"
    36  	BackendPass    = "pass"
    37  	BackendTest    = "test"
    38  	BackendMemory  = "memory"
    39  )
    40  
    41  const (
    42  	keyringFileDirName = "keyring-file"
    43  	keyringTestDirName = "keyring-test"
    44  	passKeyringPrefix  = "keyring-%s"
    45  
    46  	// temporary pass phrase for exporting a key during a key rename
    47  	passPhrase = "temp"
    48  	// prefix for exported hex private keys
    49  	hexPrefix = "0x"
    50  )
    51  
    52  var (
    53  	_                          Keyring = &keystore{}
    54  	maxPassphraseEntryAttempts         = 3
    55  )
    56  
    57  // Keyring exposes operations over a backend supported by github.com/99designs/keyring.
    58  type Keyring interface {
    59  	// Get the backend type used in the keyring config: "file", "os", "kwallet", "pass", "test", "memory".
    60  	Backend() string
    61  	// List all keys.
    62  	List() ([]*Record, error)
    63  
    64  	// Supported signing algorithms for Keyring and Ledger respectively.
    65  	SupportedAlgorithms() (SigningAlgoList, SigningAlgoList)
    66  
    67  	// Key and KeyByAddress return keys by uid and address respectively.
    68  	Key(uid string) (*Record, error)
    69  	KeyByAddress(address sdk.Address) (*Record, error)
    70  
    71  	// Delete and DeleteByAddress remove keys from the keyring.
    72  	Delete(uid string) error
    73  	DeleteByAddress(address sdk.Address) error
    74  
    75  	// Rename an existing key from the Keyring
    76  	Rename(from, to string) error
    77  
    78  	// NewMnemonic generates a new mnemonic, derives a hierarchical deterministic key from it, and
    79  	// persists the key to storage. Returns the generated mnemonic and the key Info.
    80  	// It returns an error if it fails to generate a key for the given algo type, or if
    81  	// another key is already stored under the same name or address.
    82  	//
    83  	// A passphrase set to the empty string will set the passphrase to the DefaultBIP39Passphrase value.
    84  	NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (*Record, string, error)
    85  
    86  	// NewAccount converts a mnemonic to a private key and BIP-39 HD Path and persists it.
    87  	// It fails if there is an existing key Info with the same address.
    88  	NewAccount(uid, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (*Record, error)
    89  
    90  	// SaveLedgerKey retrieves a public key reference from a Ledger device and persists it.
    91  	SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (*Record, error)
    92  
    93  	// SaveOfflineKey stores a public key and returns the persisted Info structure.
    94  	SaveOfflineKey(uid string, pubkey types.PubKey) (*Record, error)
    95  
    96  	// SaveMultisig stores and returns a new multsig (offline) key reference.
    97  	SaveMultisig(uid string, pubkey types.PubKey) (*Record, error)
    98  
    99  	Signer
   100  
   101  	Importer
   102  	Exporter
   103  
   104  	Migrator
   105  }
   106  
   107  // Signer is implemented by key stores that want to provide signing capabilities.
   108  type Signer interface {
   109  	// Sign sign byte messages with a user key.
   110  	Sign(uid string, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error)
   111  
   112  	// SignByAddress sign byte messages with a user key providing the address.
   113  	SignByAddress(address sdk.Address, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error)
   114  }
   115  
   116  // Importer is implemented by key stores that support import of public and private keys.
   117  type Importer interface {
   118  	// ImportPrivKey imports ASCII armored passphrase-encrypted private keys.
   119  	ImportPrivKey(uid, armor, passphrase string) error
   120  	// ImportPrivKeyHex imports hex encoded keys.
   121  	ImportPrivKeyHex(uid, privKey, algoStr string) error
   122  	// ImportPubKey imports ASCII armored public keys.
   123  	ImportPubKey(uid, armor string) error
   124  }
   125  
   126  // Migrator is implemented by key stores and enables migration of keys from amino to proto
   127  type Migrator interface {
   128  	MigrateAll() ([]*Record, error)
   129  }
   130  
   131  // Exporter is implemented by key stores that support export of public and private keys.
   132  type Exporter interface {
   133  	// Export public key
   134  	ExportPubKeyArmor(uid string) (string, error)
   135  	ExportPubKeyArmorByAddress(address sdk.Address) (string, error)
   136  
   137  	// ExportPrivKeyArmor returns a private key in ASCII armored format.
   138  	// It returns an error if the key does not exist or a wrong encryption passphrase is supplied.
   139  	ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error)
   140  	ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error)
   141  }
   142  
   143  // Option overrides keyring configuration options.
   144  type Option func(options *Options)
   145  
   146  // Options define the options of the Keyring.
   147  type Options struct {
   148  	// supported signing algorithms for keyring
   149  	SupportedAlgos SigningAlgoList
   150  	// supported signing algorithms for Ledger
   151  	SupportedAlgosLedger SigningAlgoList
   152  	// define Ledger Derivation function
   153  	LedgerDerivation func() (ledger.SECP256K1, error)
   154  	// define Ledger key generation function
   155  	LedgerCreateKey func([]byte) types.PubKey
   156  	// define Ledger app name
   157  	LedgerAppName string
   158  	// indicate whether Ledger should skip DER Conversion on signature,
   159  	// depending on which format (DER or BER) the Ledger app returns signatures
   160  	LedgerSigSkipDERConv bool
   161  }
   162  
   163  // NewInMemory creates a transient keyring useful for testing
   164  // purposes and on-the-fly key generation.
   165  // Keybase options can be applied when generating this new Keybase.
   166  func NewInMemory(cdc codec.Codec, opts ...Option) Keyring {
   167  	return NewInMemoryWithKeyring(keyring.NewArrayKeyring(nil), cdc, opts...)
   168  }
   169  
   170  // NewInMemoryWithKeyring returns an in memory keyring using the specified keyring.Keyring
   171  // as the backing keyring.
   172  func NewInMemoryWithKeyring(kr keyring.Keyring, cdc codec.Codec, opts ...Option) Keyring {
   173  	return newKeystore(kr, cdc, BackendMemory, opts...)
   174  }
   175  
   176  // New creates a new instance of a keyring.
   177  // Keyring options can be applied when generating the new instance.
   178  // Available backends are "os", "file", "kwallet", "memory", "pass", "test".
   179  func New(
   180  	appName, backend, rootDir string, userInput io.Reader, cdc codec.Codec, opts ...Option,
   181  ) (Keyring, error) {
   182  	var (
   183  		db  keyring.Keyring
   184  		err error
   185  	)
   186  
   187  	switch backend {
   188  	case BackendMemory:
   189  		return NewInMemory(cdc, opts...), err
   190  	case BackendTest:
   191  		db, err = keyring.Open(newTestBackendKeyringConfig(appName, rootDir))
   192  	case BackendFile:
   193  		db, err = keyring.Open(newFileBackendKeyringConfig(appName, rootDir, userInput))
   194  	case BackendOS:
   195  		db, err = keyring.Open(newOSBackendKeyringConfig(appName, rootDir, userInput))
   196  	case BackendKWallet:
   197  		db, err = keyring.Open(newKWalletBackendKeyringConfig(appName, rootDir, userInput))
   198  	case BackendPass:
   199  		db, err = keyring.Open(newPassBackendKeyringConfig(appName, rootDir, userInput))
   200  	default:
   201  		return nil, errorsmod.Wrap(ErrUnknownBacked, backend)
   202  	}
   203  
   204  	if err != nil {
   205  		return nil, err
   206  	}
   207  
   208  	return newKeystore(db, cdc, backend, opts...), nil
   209  }
   210  
   211  type keystore struct {
   212  	db      keyring.Keyring
   213  	cdc     codec.Codec
   214  	backend string
   215  	options Options
   216  }
   217  
   218  func newKeystore(kr keyring.Keyring, cdc codec.Codec, backend string, opts ...Option) keystore {
   219  	// Default options for keybase, these can be overwritten using the
   220  	// Option function
   221  	options := Options{
   222  		SupportedAlgos:       SigningAlgoList{hd.Secp256k1},
   223  		SupportedAlgosLedger: SigningAlgoList{hd.Secp256k1},
   224  	}
   225  
   226  	for _, optionFn := range opts {
   227  		optionFn(&options)
   228  	}
   229  
   230  	if options.LedgerDerivation != nil {
   231  		ledger.SetDiscoverLedger(options.LedgerDerivation)
   232  	}
   233  
   234  	if options.LedgerCreateKey != nil {
   235  		ledger.SetCreatePubkey(options.LedgerCreateKey)
   236  	}
   237  
   238  	if options.LedgerAppName != "" {
   239  		ledger.SetAppName(options.LedgerAppName)
   240  	}
   241  
   242  	if options.LedgerSigSkipDERConv {
   243  		ledger.SetSkipDERConversion()
   244  	}
   245  
   246  	return keystore{
   247  		db:      kr,
   248  		cdc:     cdc,
   249  		backend: backend,
   250  		options: options,
   251  	}
   252  }
   253  
   254  // Backend returns the keyring backend option used in the config
   255  func (ks keystore) Backend() string {
   256  	return ks.backend
   257  }
   258  
   259  func (ks keystore) ExportPubKeyArmor(uid string) (string, error) {
   260  	k, err := ks.Key(uid)
   261  	if err != nil {
   262  		return "", err
   263  	}
   264  
   265  	key, err := k.GetPubKey()
   266  	if err != nil {
   267  		return "", err
   268  	}
   269  
   270  	bz, err := ks.cdc.MarshalInterface(key)
   271  	if err != nil {
   272  		return "", err
   273  	}
   274  
   275  	return crypto.ArmorPubKeyBytes(bz, key.Type()), nil
   276  }
   277  
   278  func (ks keystore) ExportPubKeyArmorByAddress(address sdk.Address) (string, error) {
   279  	k, err := ks.KeyByAddress(address)
   280  	if err != nil {
   281  		return "", err
   282  	}
   283  
   284  	return ks.ExportPubKeyArmor(k.Name)
   285  }
   286  
   287  // ExportPrivKeyArmor exports encrypted privKey
   288  func (ks keystore) ExportPrivKeyArmor(uid, encryptPassphrase string) (armor string, err error) {
   289  	priv, err := ks.ExportPrivateKeyObject(uid)
   290  	if err != nil {
   291  		return "", err
   292  	}
   293  
   294  	return crypto.EncryptArmorPrivKey(priv, encryptPassphrase, priv.Type()), nil
   295  }
   296  
   297  // ExportPrivateKeyObject exports an armored private key object.
   298  func (ks keystore) ExportPrivateKeyObject(uid string) (types.PrivKey, error) {
   299  	k, err := ks.Key(uid)
   300  	if err != nil {
   301  		return nil, err
   302  	}
   303  
   304  	priv, err := extractPrivKeyFromRecord(k)
   305  	if err != nil {
   306  		return nil, err
   307  	}
   308  
   309  	return priv, err
   310  }
   311  
   312  func (ks keystore) ExportPrivKeyArmorByAddress(address sdk.Address, encryptPassphrase string) (armor string, err error) {
   313  	k, err := ks.KeyByAddress(address)
   314  	if err != nil {
   315  		return "", err
   316  	}
   317  
   318  	return ks.ExportPrivKeyArmor(k.Name, encryptPassphrase)
   319  }
   320  
   321  func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error {
   322  	if k, err := ks.Key(uid); err == nil {
   323  		if uid == k.Name {
   324  			return errorsmod.Wrap(ErrOverwriteKey, uid)
   325  		}
   326  	}
   327  
   328  	privKey, _, err := crypto.UnarmorDecryptPrivKey(armor, passphrase)
   329  	if err != nil {
   330  		return errorsmod.Wrap(err, "failed to decrypt private key")
   331  	}
   332  
   333  	_, err = ks.writeLocalKey(uid, privKey)
   334  	if err != nil {
   335  		return err
   336  	}
   337  
   338  	return nil
   339  }
   340  
   341  func (ks keystore) ImportPrivKeyHex(uid, privKey, algoStr string) error {
   342  	if _, err := ks.Key(uid); err == nil {
   343  		return errorsmod.Wrap(ErrOverwriteKey, uid)
   344  	}
   345  	if privKey[:2] == hexPrefix {
   346  		privKey = privKey[2:]
   347  	}
   348  	decodedPriv, err := hex.DecodeString(privKey)
   349  	if err != nil {
   350  		return err
   351  	}
   352  	algo, err := NewSigningAlgoFromString(algoStr, ks.options.SupportedAlgos)
   353  	if err != nil {
   354  		return err
   355  	}
   356  	priv := algo.Generate()(decodedPriv)
   357  	_, err = ks.writeLocalKey(uid, priv)
   358  	if err != nil {
   359  		return err
   360  	}
   361  	return nil
   362  }
   363  
   364  func (ks keystore) ImportPubKey(uid, armor string) error {
   365  	if _, err := ks.Key(uid); err == nil {
   366  		return errorsmod.Wrap(ErrOverwriteKey, uid)
   367  	}
   368  
   369  	pubBytes, _, err := crypto.UnarmorPubKeyBytes(armor)
   370  	if err != nil {
   371  		return err
   372  	}
   373  
   374  	var pubKey types.PubKey
   375  	if err := ks.cdc.UnmarshalInterface(pubBytes, &pubKey); err != nil {
   376  		return err
   377  	}
   378  
   379  	_, err = ks.writeOfflineKey(uid, pubKey)
   380  	if err != nil {
   381  		return err
   382  	}
   383  
   384  	return nil
   385  }
   386  
   387  func (ks keystore) Sign(uid string, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) {
   388  	k, err := ks.Key(uid)
   389  	if err != nil {
   390  		return nil, nil, err
   391  	}
   392  
   393  	switch {
   394  	case k.GetLocal() != nil:
   395  		priv, err := extractPrivKeyFromLocal(k.GetLocal())
   396  		if err != nil {
   397  			return nil, nil, err
   398  		}
   399  
   400  		sig, err := priv.Sign(msg)
   401  		if err != nil {
   402  			return nil, nil, err
   403  		}
   404  
   405  		return sig, priv.PubKey(), nil
   406  
   407  	case k.GetLedger() != nil:
   408  		return SignWithLedger(k, msg, signMode)
   409  
   410  		// multi or offline record
   411  	default:
   412  		pub, err := k.GetPubKey()
   413  		if err != nil {
   414  			return nil, nil, err
   415  		}
   416  		return nil, pub, ErrOfflineSign
   417  	}
   418  }
   419  
   420  func (ks keystore) SignByAddress(address sdk.Address, msg []byte, signMode signing.SignMode) ([]byte, types.PubKey, error) {
   421  	k, err := ks.KeyByAddress(address)
   422  	if err != nil {
   423  		return nil, nil, err
   424  	}
   425  
   426  	return ks.Sign(k.Name, msg, signMode)
   427  }
   428  
   429  func (ks keystore) SaveLedgerKey(uid string, algo SignatureAlgo, hrp string, coinType, account, index uint32) (*Record, error) {
   430  	if !ks.options.SupportedAlgosLedger.Contains(algo) {
   431  		return nil, errorsmod.Wrap(ErrUnsupportedSigningAlgo, fmt.Sprintf("signature algo %s is not defined in the keyring options", algo.Name()))
   432  	}
   433  
   434  	hdPath := hd.NewFundraiserParams(account, coinType, index)
   435  
   436  	priv, _, err := ledger.NewPrivKeySecp256k1(*hdPath, hrp)
   437  	if err != nil {
   438  		return nil, errors.CombineErrors(ErrLedgerGenerateKey, err)
   439  	}
   440  
   441  	return ks.writeLedgerKey(uid, priv.PubKey(), hdPath)
   442  }
   443  
   444  func (ks keystore) writeLedgerKey(name string, pk types.PubKey, path *hd.BIP44Params) (*Record, error) {
   445  	k, err := NewLedgerRecord(name, pk, path)
   446  	if err != nil {
   447  		return nil, err
   448  	}
   449  
   450  	return k, ks.writeRecord(k)
   451  }
   452  
   453  func (ks keystore) SaveMultisig(uid string, pubkey types.PubKey) (*Record, error) {
   454  	return ks.writeMultisigKey(uid, pubkey)
   455  }
   456  
   457  func (ks keystore) SaveOfflineKey(uid string, pubkey types.PubKey) (*Record, error) {
   458  	return ks.writeOfflineKey(uid, pubkey)
   459  }
   460  
   461  func (ks keystore) DeleteByAddress(address sdk.Address) error {
   462  	k, err := ks.KeyByAddress(address)
   463  	if err != nil {
   464  		return err
   465  	}
   466  
   467  	err = ks.Delete(k.Name)
   468  	if err != nil {
   469  		return err
   470  	}
   471  
   472  	return nil
   473  }
   474  
   475  func (ks keystore) Rename(oldName, newName string) error {
   476  	_, err := ks.Key(newName)
   477  	if err == nil {
   478  		return errorsmod.Wrap(ErrKeyAlreadyExists, fmt.Sprintf("rename failed, %s", newName))
   479  	}
   480  
   481  	armor, err := ks.ExportPrivKeyArmor(oldName, passPhrase)
   482  	if err != nil {
   483  		return err
   484  	}
   485  
   486  	if err := ks.Delete(oldName); err != nil {
   487  		return err
   488  	}
   489  
   490  	if err := ks.ImportPrivKey(newName, armor, passPhrase); err != nil {
   491  		return err
   492  	}
   493  
   494  	return nil
   495  }
   496  
   497  // Delete deletes a key in the keyring. `uid` represents the key name, without
   498  // the `.info` suffix.
   499  func (ks keystore) Delete(uid string) error {
   500  	k, err := ks.Key(uid)
   501  	if err != nil {
   502  		return err
   503  	}
   504  
   505  	addr, err := k.GetAddress()
   506  	if err != nil {
   507  		return err
   508  	}
   509  
   510  	err = ks.db.Remove(addrHexKeyAsString(addr))
   511  	if err != nil {
   512  		return err
   513  	}
   514  
   515  	err = ks.db.Remove(infoKey(uid))
   516  	if err != nil {
   517  		return err
   518  	}
   519  
   520  	return nil
   521  }
   522  
   523  func (ks keystore) KeyByAddress(address sdk.Address) (*Record, error) {
   524  	ik, err := ks.db.Get(addrHexKeyAsString(address))
   525  	if err != nil {
   526  		return nil, wrapKeyNotFound(err, fmt.Sprintf("key with address %s not found", address.String()))
   527  	}
   528  
   529  	if len(ik.Data) == 0 {
   530  		return nil, wrapKeyNotFound(err, fmt.Sprintf("key with address %s not found", address.String()))
   531  	}
   532  
   533  	return ks.Key(string(ik.Data))
   534  }
   535  
   536  func wrapKeyNotFound(err error, msg string) error {
   537  	if err == keyring.ErrKeyNotFound {
   538  		return errorsmod.Wrap(sdkerrors.ErrKeyNotFound, msg)
   539  	}
   540  	return err
   541  }
   542  
   543  func (ks keystore) List() ([]*Record, error) {
   544  	return ks.MigrateAll()
   545  }
   546  
   547  func (ks keystore) NewMnemonic(uid string, language Language, hdPath, bip39Passphrase string, algo SignatureAlgo) (*Record, string, error) {
   548  	if language != English {
   549  		return nil, "", ErrUnsupportedLanguage
   550  	}
   551  
   552  	if !ks.isSupportedSigningAlgo(algo) {
   553  		return nil, "", ErrUnsupportedSigningAlgo
   554  	}
   555  
   556  	// Default number of words (24): This generates a mnemonic directly from the
   557  	// number of words by reading system entropy.
   558  	entropy, err := bip39.NewEntropy(defaultEntropySize)
   559  	if err != nil {
   560  		return nil, "", err
   561  	}
   562  
   563  	mnemonic, err := bip39.NewMnemonic(entropy)
   564  	if err != nil {
   565  		return nil, "", err
   566  	}
   567  
   568  	if bip39Passphrase == "" {
   569  		bip39Passphrase = DefaultBIP39Passphrase
   570  	}
   571  
   572  	k, err := ks.NewAccount(uid, mnemonic, bip39Passphrase, hdPath, algo)
   573  	if err != nil {
   574  		return nil, "", err
   575  	}
   576  
   577  	return k, mnemonic, nil
   578  }
   579  
   580  func (ks keystore) NewAccount(name, mnemonic, bip39Passphrase, hdPath string, algo SignatureAlgo) (*Record, error) {
   581  	if !ks.isSupportedSigningAlgo(algo) {
   582  		return nil, ErrUnsupportedSigningAlgo
   583  	}
   584  
   585  	// create master key and derive first key for keyring
   586  	derivedPriv, err := algo.Derive()(mnemonic, bip39Passphrase, hdPath)
   587  	if err != nil {
   588  		return nil, err
   589  	}
   590  
   591  	privKey := algo.Generate()(derivedPriv)
   592  
   593  	// check if the key already exists with the same address and return an error
   594  	// if found
   595  	address := sdk.AccAddress(privKey.PubKey().Address())
   596  	if _, err := ks.KeyByAddress(address); err == nil {
   597  		return nil, ErrDuplicatedAddress
   598  	}
   599  
   600  	return ks.writeLocalKey(name, privKey)
   601  }
   602  
   603  func (ks keystore) isSupportedSigningAlgo(algo SignatureAlgo) bool {
   604  	return ks.options.SupportedAlgos.Contains(algo)
   605  }
   606  
   607  func (ks keystore) Key(uid string) (*Record, error) {
   608  	k, err := ks.migrate(uid)
   609  	if err != nil {
   610  		return nil, err
   611  	}
   612  
   613  	return k, nil
   614  }
   615  
   616  // SupportedAlgorithms returns the keystore Options' supported signing algorithm.
   617  // for the keyring and Ledger.
   618  func (ks keystore) SupportedAlgorithms() (SigningAlgoList, SigningAlgoList) {
   619  	return ks.options.SupportedAlgos, ks.options.SupportedAlgosLedger
   620  }
   621  
   622  // SignWithLedger signs a binary message with the ledger device referenced by an Info object
   623  // and returns the signed bytes and the public key. It returns an error if the device could
   624  // not be queried or it returned an error.
   625  func SignWithLedger(k *Record, msg []byte, signMode signing.SignMode) (sig []byte, pub types.PubKey, err error) {
   626  	ledgerInfo := k.GetLedger()
   627  	if ledgerInfo == nil {
   628  		return nil, nil, ErrNotLedgerObj
   629  	}
   630  
   631  	path := ledgerInfo.GetPath()
   632  
   633  	priv, err := ledger.NewPrivKeySecp256k1Unsafe(*path)
   634  	if err != nil {
   635  		return
   636  	}
   637  
   638  	switch signMode {
   639  	case signing.SignMode_SIGN_MODE_TEXTUAL:
   640  		sig, err = priv.Sign(msg)
   641  		if err != nil {
   642  			return nil, nil, err
   643  		}
   644  	case signing.SignMode_SIGN_MODE_LEGACY_AMINO_JSON:
   645  		sig, err = priv.SignLedgerAminoJSON(msg)
   646  		if err != nil {
   647  			return nil, nil, err
   648  		}
   649  	default:
   650  		return nil, nil, errorsmod.Wrap(ErrInvalidSignMode, fmt.Sprintf("%v", signMode))
   651  	}
   652  
   653  	if !priv.PubKey().VerifySignature(msg, sig) {
   654  		return nil, nil, ErrLedgerInvalidSignature
   655  	}
   656  
   657  	return sig, priv.PubKey(), nil
   658  }
   659  
   660  func newOSBackendKeyringConfig(appName, dir string, buf io.Reader) keyring.Config {
   661  	return keyring.Config{
   662  		ServiceName:              appName,
   663  		FileDir:                  dir,
   664  		KeychainTrustApplication: true,
   665  		FilePasswordFunc:         newRealPrompt(dir, buf),
   666  	}
   667  }
   668  
   669  func newTestBackendKeyringConfig(appName, dir string) keyring.Config {
   670  	return keyring.Config{
   671  		AllowedBackends: []keyring.BackendType{keyring.FileBackend},
   672  		ServiceName:     appName,
   673  		FileDir:         filepath.Join(dir, keyringTestDirName),
   674  		FilePasswordFunc: func(_ string) (string, error) {
   675  			return "test", nil
   676  		},
   677  	}
   678  }
   679  
   680  func newKWalletBackendKeyringConfig(appName, _ string, _ io.Reader) keyring.Config {
   681  	return keyring.Config{
   682  		AllowedBackends: []keyring.BackendType{keyring.KWalletBackend},
   683  		ServiceName:     "kdewallet",
   684  		KWalletAppID:    appName,
   685  		KWalletFolder:   "",
   686  	}
   687  }
   688  
   689  func newPassBackendKeyringConfig(appName, _ string, _ io.Reader) keyring.Config {
   690  	prefix := fmt.Sprintf(passKeyringPrefix, appName)
   691  
   692  	return keyring.Config{
   693  		AllowedBackends: []keyring.BackendType{keyring.PassBackend},
   694  		ServiceName:     appName,
   695  		PassPrefix:      prefix,
   696  	}
   697  }
   698  
   699  func newFileBackendKeyringConfig(name, dir string, buf io.Reader) keyring.Config {
   700  	fileDir := filepath.Join(dir, keyringFileDirName)
   701  
   702  	return keyring.Config{
   703  		AllowedBackends:  []keyring.BackendType{keyring.FileBackend},
   704  		ServiceName:      name,
   705  		FileDir:          fileDir,
   706  		FilePasswordFunc: newRealPrompt(fileDir, buf),
   707  	}
   708  }
   709  
   710  func newRealPrompt(dir string, buf io.Reader) func(string) (string, error) {
   711  	return func(prompt string) (string, error) {
   712  		keyhashStored := false
   713  		keyhashFilePath := filepath.Join(dir, "keyhash")
   714  
   715  		var keyhash []byte
   716  
   717  		_, err := os.Stat(keyhashFilePath)
   718  
   719  		switch {
   720  		case err == nil:
   721  			keyhash, err = os.ReadFile(keyhashFilePath)
   722  			if err != nil {
   723  				return "", errorsmod.Wrap(err, fmt.Sprintf("failed to read %s", keyhashFilePath))
   724  			}
   725  
   726  			keyhashStored = true
   727  
   728  		case os.IsNotExist(err):
   729  			keyhashStored = false
   730  
   731  		default:
   732  			return "", errorsmod.Wrap(err, fmt.Sprintf("failed to open %s", keyhashFilePath))
   733  		}
   734  
   735  		failureCounter := 0
   736  
   737  		for {
   738  			failureCounter++
   739  			if failureCounter > maxPassphraseEntryAttempts {
   740  				return "", ErrMaxPassPhraseAttempts
   741  			}
   742  
   743  			buf := bufio.NewReader(buf)
   744  			pass, err := input.GetPassword(fmt.Sprintf("Enter keyring passphrase (attempt %d/%d):", failureCounter, maxPassphraseEntryAttempts), buf)
   745  			if err != nil {
   746  				// NOTE: LGTM.io reports a false positive alert that states we are printing the password,
   747  				// but we only log the error.
   748  				//
   749  				// lgtm [go/clear-text-logging]
   750  				fmt.Fprintln(os.Stderr, err)
   751  				continue
   752  			}
   753  
   754  			if keyhashStored {
   755  				if err := bcrypt.CompareHashAndPassword(keyhash, []byte(pass)); err != nil {
   756  					fmt.Fprintln(os.Stderr, "incorrect passphrase")
   757  					continue
   758  				}
   759  
   760  				return pass, nil
   761  			}
   762  
   763  			reEnteredPass, err := input.GetPassword("Re-enter keyring passphrase:", buf)
   764  			if err != nil {
   765  				// NOTE: LGTM.io reports a false positive alert that states we are printing the password,
   766  				// but we only log the error.
   767  				//
   768  				// lgtm [go/clear-text-logging]
   769  				fmt.Fprintln(os.Stderr, err)
   770  				continue
   771  			}
   772  
   773  			if pass != reEnteredPass {
   774  				fmt.Fprintln(os.Stderr, "passphrase do not match")
   775  				continue
   776  			}
   777  
   778  			passwordHash, err := bcrypt.GenerateFromPassword([]byte(pass), 2)
   779  			if err != nil {
   780  				fmt.Fprintln(os.Stderr, err)
   781  				continue
   782  			}
   783  
   784  			if err := os.WriteFile(keyhashFilePath, passwordHash, 0o600); err != nil {
   785  				return "", err
   786  			}
   787  
   788  			return pass, nil
   789  		}
   790  	}
   791  }
   792  
   793  func (ks keystore) writeLocalKey(name string, privKey types.PrivKey) (*Record, error) {
   794  	k, err := NewLocalRecord(name, privKey, privKey.PubKey())
   795  	if err != nil {
   796  		return nil, err
   797  	}
   798  
   799  	return k, ks.writeRecord(k)
   800  }
   801  
   802  // writeRecord persists a keyring item in keystore if it does not exist there.
   803  // For each key record, we actually write 2 items:
   804  // - one with key `<uid>.info`, with Data = the serialized protobuf key
   805  // - another with key `<addr_as_hex>.address`, with Data = the uid (i.e. the key name)
   806  // This is to be able to query keys both by name and by address.
   807  func (ks keystore) writeRecord(k *Record) error {
   808  	addr, err := k.GetAddress()
   809  	if err != nil {
   810  		return err
   811  	}
   812  
   813  	key := infoKey(k.Name)
   814  
   815  	exists, err := ks.existsInDb(addr, key)
   816  	if err != nil {
   817  		return err
   818  	}
   819  	if exists {
   820  		return errorsmod.Wrap(ErrKeyAlreadyExists, key)
   821  	}
   822  
   823  	serializedRecord, err := ks.cdc.Marshal(k)
   824  	if err != nil {
   825  		return errors.CombineErrors(ErrUnableToSerialize, err)
   826  	}
   827  
   828  	item := keyring.Item{
   829  		Key:  key,
   830  		Data: serializedRecord,
   831  	}
   832  
   833  	if err := ks.SetItem(item); err != nil {
   834  		return err
   835  	}
   836  
   837  	item = keyring.Item{
   838  		Key:  addrHexKeyAsString(addr),
   839  		Data: []byte(key),
   840  	}
   841  
   842  	if err := ks.SetItem(item); err != nil {
   843  		return err
   844  	}
   845  
   846  	return nil
   847  }
   848  
   849  // existsInDb returns (true, nil) if either addr or name exist is in keystore DB.
   850  // On the other hand, it returns (false, error) if Get method returns error different from keyring.ErrKeyNotFound
   851  // In case of inconsistent keyring, it recovers it automatically.
   852  func (ks keystore) existsInDb(addr sdk.Address, name string) (bool, error) {
   853  	_, errAddr := ks.db.Get(addrHexKeyAsString(addr))
   854  	if errAddr != nil && !errors.Is(errAddr, keyring.ErrKeyNotFound) {
   855  		return false, errAddr
   856  	}
   857  
   858  	_, errInfo := ks.db.Get(infoKey(name))
   859  	if errInfo == nil {
   860  		return true, nil // uid lookup succeeds - info exists
   861  	} else if !errors.Is(errInfo, keyring.ErrKeyNotFound) {
   862  		return false, errInfo // received unexpected error - returns
   863  	}
   864  
   865  	// looking for an issue, record with meta (getByAddress) exists, but record with public key itself does not
   866  	if errAddr == nil && errors.Is(errInfo, keyring.ErrKeyNotFound) {
   867  		fmt.Fprintf(os.Stderr, "address \"%s\" exists but pubkey itself does not\n", hex.EncodeToString(addr.Bytes()))
   868  		fmt.Fprintln(os.Stderr, "recreating pubkey record")
   869  		err := ks.db.Remove(addrHexKeyAsString(addr))
   870  		if err != nil {
   871  			return true, err
   872  		}
   873  		return false, nil
   874  	}
   875  
   876  	// both lookups failed, info does not exist
   877  	return false, nil
   878  }
   879  
   880  func (ks keystore) writeOfflineKey(name string, pk types.PubKey) (*Record, error) {
   881  	k, err := NewOfflineRecord(name, pk)
   882  	if err != nil {
   883  		return nil, err
   884  	}
   885  
   886  	return k, ks.writeRecord(k)
   887  }
   888  
   889  // writeMultisigKey investigate where thisf function is called maybe remove it
   890  func (ks keystore) writeMultisigKey(name string, pk types.PubKey) (*Record, error) {
   891  	k, err := NewMultiRecord(name, pk)
   892  	if err != nil {
   893  		return nil, err
   894  	}
   895  
   896  	return k, ks.writeRecord(k)
   897  }
   898  
   899  func (ks keystore) MigrateAll() ([]*Record, error) {
   900  	keys, err := ks.db.Keys()
   901  	if err != nil {
   902  		return nil, err
   903  	}
   904  
   905  	if len(keys) == 0 {
   906  		return nil, nil
   907  	}
   908  
   909  	sort.Strings(keys)
   910  	var recs []*Record
   911  	for _, key := range keys {
   912  		// The keyring items only with `.info` consists the key info.
   913  		if !strings.HasSuffix(key, infoSuffix) {
   914  			continue
   915  		}
   916  
   917  		rec, err := ks.migrate(key)
   918  		if err != nil {
   919  			fmt.Printf("migrate err for key %s: %q\n", key, err)
   920  			continue
   921  		}
   922  
   923  		recs = append(recs, rec)
   924  	}
   925  
   926  	return recs, nil
   927  }
   928  
   929  // migrate converts keyring.Item from amino to proto serialization format.
   930  // the `key` argument can be a key uid (e.g. "alice") or with the '.info'
   931  // suffix (e.g. "alice.info").
   932  //
   933  // It operates as follows:
   934  // 1. retrieve any key
   935  // 2. try to decode it using protobuf
   936  // 3. if ok, then return the key, do nothing else
   937  // 4. if it fails, then try to decode it using amino
   938  // 5. convert from the amino struct to the protobuf struct
   939  // 6. write the proto-encoded key back to the keyring
   940  func (ks keystore) migrate(key string) (*Record, error) {
   941  	if !strings.HasSuffix(key, infoSuffix) {
   942  		key = infoKey(key)
   943  	}
   944  
   945  	// 1. get the key.
   946  	item, err := ks.db.Get(key)
   947  	if err != nil {
   948  		return nil, wrapKeyNotFound(err, key)
   949  	}
   950  
   951  	if len(item.Data) == 0 {
   952  		return nil, errorsmod.Wrap(sdkerrors.ErrKeyNotFound, key)
   953  	}
   954  
   955  	// 2. Try to deserialize using proto
   956  	k, err := ks.protoUnmarshalRecord(item.Data)
   957  	// 3. If ok then return the key
   958  	if err == nil {
   959  		return k, nil
   960  	}
   961  
   962  	// 4. Try to decode with amino
   963  	legacyInfo, err := unMarshalLegacyInfo(item.Data)
   964  	if err != nil {
   965  		return nil, errorsmod.Wrap(err, "unable to unmarshal item.Data")
   966  	}
   967  
   968  	// 5. Convert and serialize info using proto
   969  	k, err = ks.convertFromLegacyInfo(legacyInfo)
   970  	if err != nil {
   971  		return nil, errorsmod.Wrap(err, "convertFromLegacyInfo")
   972  	}
   973  
   974  	serializedRecord, err := ks.cdc.Marshal(k)
   975  	if err != nil {
   976  		return nil, errors.CombineErrors(ErrUnableToSerialize, err)
   977  	}
   978  
   979  	item = keyring.Item{
   980  		Key:  key,
   981  		Data: serializedRecord,
   982  	}
   983  
   984  	// 6. Overwrite the keyring entry with the new proto-encoded key.
   985  	if err := ks.SetItem(item); err != nil {
   986  		return nil, errorsmod.Wrap(err, "unable to set keyring.Item")
   987  	}
   988  
   989  	fmt.Printf("Successfully migrated key %s.\n", key)
   990  
   991  	return k, nil
   992  }
   993  
   994  func (ks keystore) protoUnmarshalRecord(bz []byte) (*Record, error) {
   995  	k := new(Record)
   996  	if err := ks.cdc.Unmarshal(bz, k); err != nil {
   997  		return nil, err
   998  	}
   999  
  1000  	return k, nil
  1001  }
  1002  
  1003  func (ks keystore) SetItem(item keyring.Item) error {
  1004  	return ks.db.Set(item)
  1005  }
  1006  
  1007  func (ks keystore) convertFromLegacyInfo(info LegacyInfo) (*Record, error) {
  1008  	if info == nil {
  1009  		return nil, errorsmod.Wrap(ErrLegacyToRecord, "info is nil")
  1010  	}
  1011  
  1012  	name := info.GetName()
  1013  	pk := info.GetPubKey()
  1014  
  1015  	switch info.GetType() {
  1016  	case TypeLocal:
  1017  		priv, err := privKeyFromLegacyInfo(info)
  1018  		if err != nil {
  1019  			return nil, err
  1020  		}
  1021  
  1022  		return NewLocalRecord(name, priv, pk)
  1023  	case TypeOffline:
  1024  		return NewOfflineRecord(name, pk)
  1025  	case TypeMulti:
  1026  		return NewMultiRecord(name, pk)
  1027  	case TypeLedger:
  1028  		path, err := info.GetPath()
  1029  		if err != nil {
  1030  			return nil, err
  1031  		}
  1032  
  1033  		return NewLedgerRecord(name, pk, path)
  1034  	default:
  1035  		return nil, ErrUnknownLegacyType
  1036  
  1037  	}
  1038  }
  1039  
  1040  func addrHexKeyAsString(address sdk.Address) string {
  1041  	return fmt.Sprintf("%s.%s", hex.EncodeToString(address.Bytes()), addressSuffix)
  1042  }