Co-authored-by: Julián Toledano <JulianToledano@users.noreply.github.com>
This commit is contained in:
parent
116e279e5a
commit
0fc0ed5d58
@ -40,6 +40,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
|
||||
|
||||
### Features
|
||||
|
||||
* (keyring) [#17424](https://github.com/cosmos/cosmos-sdk/pull/17424) Allows to import private keys encoded in hex.
|
||||
* (x/bank) [#16795](https://github.com/cosmos/cosmos-sdk/pull/16852) Add `DenomMetadataByQueryString` query in bank module to support metadata query by query string.
|
||||
* (baseapp) [#16239](https://github.com/cosmos/cosmos-sdk/pull/16239) Add Gas Limits to allow node operators to resource bound queries.
|
||||
* (baseapp) [#17393](https://github.com/cosmos/cosmos-sdk/pull/17394) Check BlockID Flag on Votes in `ValidateVoteExtensions`
|
||||
|
||||
@ -2,12 +2,16 @@ package keys
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/cosmos/cosmos-sdk/client"
|
||||
"github.com/cosmos/cosmos-sdk/client/flags"
|
||||
"github.com/cosmos/cosmos-sdk/client/input"
|
||||
"github.com/cosmos/cosmos-sdk/crypto/hd"
|
||||
"github.com/cosmos/cosmos-sdk/version"
|
||||
)
|
||||
|
||||
// ImportKeyCommand imports private keys from a keyfile.
|
||||
@ -38,3 +42,22 @@ func ImportKeyCommand() *cobra.Command {
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func ImportKeyHexCommand() *cobra.Command {
|
||||
cmd := &cobra.Command{
|
||||
Use: "import-hex <name> <hex>",
|
||||
Short: "Import private keys into the local keybase",
|
||||
Long: fmt.Sprintf("Import hex encoded private key into the local keybase.\nSupported key-types can be obtained with:\n%s list-key-types", version.AppName),
|
||||
Args: cobra.ExactArgs(2),
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
clientCtx, err := client.GetClientQueryContext(cmd)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
keyType, _ := cmd.Flags().GetString(flags.FlagKeyType)
|
||||
return clientCtx.Keyring.ImportPrivKeyHex(args[0], args[1], keyType)
|
||||
},
|
||||
}
|
||||
cmd.Flags().String(flags.FlagKeyType, string(hd.Secp256k1Type), "private key signing algorithm kind")
|
||||
return cmd
|
||||
}
|
||||
|
||||
@ -115,3 +115,60 @@ HbP+c6JmeJy9JXe2rbbF1QtCX1gLqGcDQPBXiCtFvP7/8wTZtVOPj8vREzhZ9ElO
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_runImportHexCmd(t *testing.T) {
|
||||
cdc := moduletestutil.MakeTestEncodingConfig().Codec
|
||||
testCases := []struct {
|
||||
name string
|
||||
keyringBackend string
|
||||
hexKey string
|
||||
keyType string
|
||||
expectError bool
|
||||
}{
|
||||
{
|
||||
name: "test backend success",
|
||||
keyringBackend: keyring.BackendTest,
|
||||
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
|
||||
keyType: "secp256k1",
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
cmd := ImportKeyHexCommand()
|
||||
cmd.Flags().AddFlagSet(Commands().PersistentFlags())
|
||||
mockIn := testutil.ApplyMockIODiscardOutErr(cmd)
|
||||
|
||||
// Now add a temporary keybase
|
||||
kbHome := t.TempDir()
|
||||
kb, err := keyring.New(sdk.KeyringServiceName(), tc.keyringBackend, kbHome, nil, cdc)
|
||||
require.NoError(t, err)
|
||||
|
||||
clientCtx := client.Context{}.
|
||||
WithKeyringDir(kbHome).
|
||||
WithKeyring(kb).
|
||||
WithInput(mockIn).
|
||||
WithCodec(cdc)
|
||||
ctx := context.WithValue(context.Background(), client.ClientContextKey, &clientCtx)
|
||||
|
||||
t.Cleanup(cleanupKeys(t, kb, "keyname1"))
|
||||
|
||||
defer func() {
|
||||
_ = os.RemoveAll(kbHome)
|
||||
}()
|
||||
|
||||
cmd.SetArgs([]string{
|
||||
"keyname1", tc.hexKey,
|
||||
fmt.Sprintf("--%s=%s", flags.FlagKeyType, tc.keyType),
|
||||
fmt.Sprintf("--%s=%s", flags.FlagKeyringBackend, tc.keyringBackend),
|
||||
})
|
||||
|
||||
err = cmd.ExecuteContext(ctx)
|
||||
if tc.expectError {
|
||||
require.Error(t, err)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@ -41,6 +41,7 @@ The pass backend requires GnuPG: https://gnupg.org/
|
||||
AddKeyCommand(),
|
||||
ExportKeyCommand(),
|
||||
ImportKeyCommand(),
|
||||
ImportKeyHexCommand(),
|
||||
ListKeysCmd(),
|
||||
ListKeyTypesCmd(),
|
||||
ShowKeysCmd(),
|
||||
|
||||
@ -11,5 +11,5 @@ func TestCommands(t *testing.T) {
|
||||
assert.Assert(t, rootCommands != nil)
|
||||
|
||||
// Commands are registered
|
||||
assert.Equal(t, 11, len(rootCommands.Commands()))
|
||||
assert.Equal(t, 12, len(rootCommands.Commands()))
|
||||
}
|
||||
|
||||
@ -45,6 +45,8 @@ const (
|
||||
|
||||
// temporary pass phrase for exporting a key during a key rename
|
||||
passPhrase = "temp"
|
||||
// prefix for exported hex private keys
|
||||
hexPrefix = "0x"
|
||||
)
|
||||
|
||||
var (
|
||||
@ -118,7 +120,8 @@ type Signer interface {
|
||||
type Importer interface {
|
||||
// ImportPrivKey imports ASCII armored passphrase-encrypted private keys.
|
||||
ImportPrivKey(uid, armor, passphrase string) error
|
||||
|
||||
// ImportPrivKeyHex imports hex encoded keys.
|
||||
ImportPrivKeyHex(uid, privKey, algoStr string) error
|
||||
// ImportPubKey imports ASCII armored public keys.
|
||||
ImportPubKey(uid, armor string) error
|
||||
}
|
||||
@ -338,6 +341,29 @@ func (ks keystore) ImportPrivKey(uid, armor, passphrase string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ks keystore) ImportPrivKeyHex(uid, privKey, algoStr string) error {
|
||||
if _, err := ks.Key(uid); err == nil {
|
||||
return errorsmod.Wrap(ErrOverwriteKey, uid)
|
||||
}
|
||||
if privKey[:2] == hexPrefix {
|
||||
privKey = privKey[2:]
|
||||
}
|
||||
decodedPriv, err := hex.DecodeString(privKey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
algo, err := NewSigningAlgoFromString(algoStr, ks.options.SupportedAlgos)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
priv := algo.Generate()(decodedPriv)
|
||||
_, err = ks.writeLocalKey(uid, priv)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (ks keystore) ImportPubKey(uid, armor string) error {
|
||||
if _, err := ks.Key(uid); err == nil {
|
||||
return errorsmod.Wrap(ErrOverwriteKey, uid)
|
||||
|
||||
@ -564,7 +564,65 @@ func TestImportPrivKey(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportPrivKey(t *testing.T) {
|
||||
func TestImportPrivKeyHex(t *testing.T) {
|
||||
cdc := getCodec()
|
||||
tests := []struct {
|
||||
name string
|
||||
uid string
|
||||
backend string
|
||||
hexKey string
|
||||
algo string
|
||||
expectedErr error
|
||||
}{
|
||||
{
|
||||
name: "correct import",
|
||||
uid: "hexImport",
|
||||
backend: BackendTest,
|
||||
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
|
||||
algo: "secp256k1",
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "correct import without prefix",
|
||||
uid: "hexImport",
|
||||
backend: BackendTest,
|
||||
hexKey: "a3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
|
||||
algo: "secp256k1",
|
||||
expectedErr: nil,
|
||||
},
|
||||
{
|
||||
name: "wrong hex length",
|
||||
uid: "hexImport",
|
||||
backend: BackendTest,
|
||||
hexKey: "0xae57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
|
||||
algo: "secp256k1",
|
||||
expectedErr: hex.ErrLength,
|
||||
},
|
||||
{
|
||||
name: "unsupported algo",
|
||||
uid: "hexImport",
|
||||
backend: BackendTest,
|
||||
hexKey: "0xa3e57952e835ed30eea86a2993ac2a61c03e74f2085b3635bd94aa4d7ae0cfdf",
|
||||
algo: "notSupportedAlgo",
|
||||
expectedErr: ErrUnsupportedSigningAlgo,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
kb, err := New("TestExport", tt.backend, t.TempDir(), nil, cdc)
|
||||
require.NoError(t, err)
|
||||
err = kb.ImportPrivKeyHex(tt.uid, tt.hexKey, tt.algo)
|
||||
if tt.expectedErr == nil {
|
||||
require.NoError(t, err)
|
||||
} else {
|
||||
require.Error(t, err)
|
||||
require.True(t, errors.Is(err, tt.expectedErr))
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestExportImportPrivKeyArmor(t *testing.T) {
|
||||
cdc := getCodec()
|
||||
tests := []struct {
|
||||
name string
|
||||
|
||||
Loading…
Reference in New Issue
Block a user