Skip to content

Commit

Permalink
feat(client/keys): support display discreetly for keys export (cosmos…
Browse files Browse the repository at this point in the history
  • Loading branch information
Halimao authored Dec 12, 2023
1 parent f84a123 commit 043f8f4
Show file tree
Hide file tree
Showing 3 changed files with 37 additions and 18 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ Ref: https://keepachangelog.com/en/1.0.0/
* (x/staking) [#18636](https://github.com/cosmos/cosmos-sdk/pull/18636) `IterateBondedValidatorsByPower`, `GetDelegatorBonded`, `Delegate`, `Unbond`, `Slash`, `Jail`, `SlashRedelegation`, `ApplyAndReturnValidatorSetUpdates` methods no longer panics on any kind of errors but instead returns appropriate errors.
* Usage of `Must...` kind of functions are avoided in keeper methods.
* (client/keys) [#18687](https://github.com/cosmos/cosmos-sdk/pull/18687) Improve `<appd> keys mnemonic` by displaying mnemonic discreetly on an alternate screen and adding `--indiscreet` option to disable it.
* (client/keys) [#18684](https://github.com/cosmos/cosmos-sdk/pull/18684) Improve `<appd> keys export` by displaying unarmored hex private key discreetly on an alternate screen and adding `--indiscreet` option to disable it.
* (client/keys) [#18663](https://github.com/cosmos/cosmos-sdk/pull/18663) Improve `<appd> keys add` by displaying mnemonic discreetly on an alternate screen and adding `--indiscreet` option to disable it.
* (types) [#18440](https://github.com/cosmos/cosmos-sdk/pull/18440) Add `AmountOfNoValidation` to `sdk.DecCoins`.
* (client) [#17503](https://github.com/cosmos/cosmos-sdk/pull/17503) Add `client.Context{}.WithAddressCodec`, `WithValidatorAddressCodec`, `WithConsensusAddressCodec` to provide address codecs to the client context. See the [UPGRADING.md](./UPGRADING.md) for more details.
Expand Down
21 changes: 13 additions & 8 deletions client/keys/export.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/cosmos/cosmos-sdk/client"
"github.com/cosmos/cosmos-sdk/client/input"
"github.com/cosmos/cosmos-sdk/crypto/keyring"
"github.com/cosmos/cosmos-sdk/crypto/types"
)

Expand Down Expand Up @@ -42,7 +41,7 @@ and export your keys in ASCII-armored encrypted format.`,
unsafe, _ := cmd.Flags().GetBool(flagUnsafe)

if unarmored && unsafe {
return exportUnsafeUnarmored(cmd, args[0], buf, clientCtx.Keyring)
return exportUnsafeUnarmored(clientCtx, cmd, args[0], buf)
} else if unarmored || unsafe {
return fmt.Errorf("the flags %s and %s must be used together", flagUnsafe, flagUnarmoredHex)
}
Expand All @@ -65,25 +64,31 @@ and export your keys in ASCII-armored encrypted format.`,

cmd.Flags().Bool(flagUnarmoredHex, false, "Export unarmored hex privkey. Requires --unsafe.")
cmd.Flags().Bool(flagUnsafe, false, "Enable unsafe operations. This flag must be switched on along with all unsafe operation-specific options.")
cmd.Flags().Bool(flagIndiscreet, false, "Print unarmored hex privkey directly on current terminal (only valid when --unarmored-hex is true)")

return cmd
}

func exportUnsafeUnarmored(cmd *cobra.Command, uid string, buf *bufio.Reader, kr keyring.Keyring) error {
// confirm deletion, unless -y is passed
func exportUnsafeUnarmored(ctx client.Context, cmd *cobra.Command, uid string, buf *bufio.Reader) error {
if yes, err := input.GetConfirmation("WARNING: The private key will be exported as an unarmored hexadecimal string. USE AT YOUR OWN RISK. Continue?", buf, cmd.ErrOrStderr()); err != nil {
return err
} else if !yes {
return nil
}

hexPrivKey, err := unsafeExportPrivKeyHex(kr.(unsafeExporter), uid)
hexPrivKey, err := unsafeExportPrivKeyHex(ctx.Keyring.(unsafeExporter), uid)
if err != nil {
return err
}

cmd.Println(hexPrivKey)

indiscreet, _ := cmd.Flags().GetBool(flagIndiscreet)
if indiscreet {
cmd.Println(hexPrivKey)
return nil
}
if err = printDiscreetly(ctx, cmd.ErrOrStderr(), "**Important** Do not share this private key.", hexPrivKey); err != nil {
return fmt.Errorf("failed to print private key: %w", err)
}
cmd.Println("Export private key successfully")
return nil
}

Expand Down
33 changes: 23 additions & 10 deletions client/keys/export_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,12 +21,13 @@ import (
func Test_runExportCmd(t *testing.T) {
cdc := moduletestutil.MakeTestEncodingConfig().Codec
testCases := []struct {
name string
keyringBackend string
extraArgs []string
userInput string
mustFail bool
expectedOutput string
name string
keyringBackend string
extraArgs []string
userInput string
mustFail bool
expectedOutput string
expectedOutputContain string // only valid when expectedOutput is empty
}{
{
name: "--unsafe only must fail",
Expand All @@ -49,17 +50,25 @@ func Test_runExportCmd(t *testing.T) {
expectedOutput: "",
},
{
name: "--unsafe --unarmored-hex succeed",
name: "--unsafe --unarmored-hex success",
keyringBackend: keyring.BackendTest,
extraArgs: []string{"--unsafe", "--unarmored-hex"},
userInput: "y\n",
mustFail: false,
expectedOutputContain: "2485e33678db4175dc0ecef2d6e1fc493d4a0d7f7ce83324b6ed70afe77f3485\n",
},
{
name: "--unsafe --unarmored-hex --indiscreet success",
keyringBackend: keyring.BackendTest,
extraArgs: []string{"--unsafe", "--unarmored-hex"},
extraArgs: []string{"--unsafe", "--unarmored-hex", "--indiscreet"},
userInput: "y\n",
mustFail: false,
expectedOutput: "2485e33678db4175dc0ecef2d6e1fc493d4a0d7f7ce83324b6ed70afe77f3485\n",
},
{
name: "file keyring backend properly read password and user confirmation",
keyringBackend: keyring.BackendFile,
extraArgs: []string{"--unsafe", "--unarmored-hex"},
extraArgs: []string{"--unsafe", "--unarmored-hex", "--indiscreet"},
// first 2 pass for creating the key, then unsafe export confirmation, then unlock keyring pass
userInput: "12345678\n12345678\ny\n12345678\n",
mustFail: false,
Expand Down Expand Up @@ -106,7 +115,11 @@ func Test_runExportCmd(t *testing.T) {
require.Error(t, err)
} else {
require.NoError(t, err)
require.Equal(t, tc.expectedOutput, mockOut.String())
if tc.expectedOutput != "" {
require.Equal(t, tc.expectedOutput, mockOut.String())
} else if tc.expectedOutputContain != "" {
require.Contains(t, mockOut.String(), tc.expectedOutputContain)
}
}
})
}
Expand Down

0 comments on commit 043f8f4

Please sign in to comment.