Skip to content

Commit

Permalink
remove the need to provide private key on command line
Browse files Browse the repository at this point in the history
  • Loading branch information
robdefeo committed Jul 12, 2019
1 parent 4584a79 commit b33cd38
Show file tree
Hide file tree
Showing 16 changed files with 489 additions and 124 deletions.
70 changes: 33 additions & 37 deletions cmd/mailchain/commands/account.go
Expand Up @@ -18,19 +18,19 @@ import (
"encoding/hex"
"fmt"

"github.com/mailchain/mailchain/cmd/mailchain/internal/config"
"github.com/mailchain/mailchain/cmd/mailchain/internal/prompts"
"github.com/mailchain/mailchain/cmd/mailchain/internal/settings"
"github.com/mailchain/mailchain/crypto/multikey"
"github.com/mailchain/mailchain/internal/keystore"
"github.com/mailchain/mailchain/internal/keystore/kdf/multi"
"github.com/mailchain/mailchain/internal/keystore/kdf/scrypt"
"github.com/pkg/errors"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"github.com/ttacon/chalk"
)

// account represents the say command
func accountCmd(v *viper.Viper) (*cobra.Command, error) {
func accountCmd(config *settings.Base) (*cobra.Command, error) {
cmd := &cobra.Command{
Use: "account",
Short: "Manage Accounts",
Expand All @@ -44,51 +44,58 @@ It is safe to transfer the entire directory or the individual keys therein
between ethereum nodes by simply copying.
Make sure you backup your keys regularly.`,
// PersistentPreRunE: preRun,
}
cmd.PersistentFlags().StringP("key-type", "", "", "Select the chain [secp256k1]")
ks, err := config.Keystore.Produce()
if err != nil {
return nil, errors.WithMessage(err, "could not create `keystore`")
}

cmd.AddCommand(accountAddCmd(v))
cmd.AddCommand(accountListCmd(v))
cmd.PersistentFlags().StringP("key-type", "", "", "Select the chain [secp256k1]")
cmd.AddCommand(accountAddCmd(ks, prompts.Secret, prompts.Secret))
cmd.AddCommand(accountListCmd(ks))

return cmd, nil
}

func accountAddCmd(v *viper.Viper) *cobra.Command {
func accountAddCmd(ks keystore.Store,
passphrasePrompt, privateKeyPrompt func(suppliedSecret string, prePromptNote string, promptLabel string, allowEmpty bool, confirmPrompt bool) (string, error),
) *cobra.Command {
cmd := &cobra.Command{
Use: "add",
Short: "Add private key",
RunE: func(cmd *cobra.Command, args []string) error {
s := settings.New(v)
keytype, err := getKeyType(cmd)
if err != nil {
return errors.WithMessage(err, "could not determine `key-type`")
}
privateKey, err := cmd.Flags().GetString("private-key")
cmdPK, _ := cmd.Flags().GetString("private-key")
privateKey, err := privateKeyPrompt(cmdPK,
"",
"Private Key",
false,
false,
)
if err != nil {
return errors.WithMessage(err, "could not get `private-key`")
}
if privateKey == "" {
return errors.Errorf("private key must be specified")
return errors.WithMessage(err, "could not get private key")
}
pk, err := multikey.PrivateKeyFromHex(privateKey, keytype)
if err != nil {
return errors.WithMessage(err, "`private-key` could not be decoded")
}

passphrase, err := config.Passphrase(cmd)
cmdPassphrase, _ := cmd.Flags().GetString("passphrase")
passphrase, err := passphrasePrompt(cmdPassphrase,
fmt.Sprint(chalk.Yellow, "Note: To derive a storage key passphrase is required. The passphrase must be secure and not guessable."),
"Passphrase",
false,
true,
)
if err != nil {
return errors.WithMessage(err, "could not get `passphrase`")
}
randomSalt, err := scrypt.RandomSalt()
if err != nil {
return errors.WithMessage(err, "could not create `random salt`")
}
// TODO: currently this only does scrypt need flag + config etc
ks, err := s.Keystore.Produce()
if err != nil {
return errors.WithMessage(err, "could not create `keystore`")
}
address, err := ks.Store(pk, keytype,
multi.OptionsBuilders{
Scrypt: []scrypt.DeriveOptionsBuilder{
Expand All @@ -106,48 +113,37 @@ func accountAddCmd(v *viper.Viper) *cobra.Command {
},
}

cmd.Flags().StringP("key-type", "", "", "Select the key type [secp256k1]")
cmd.Flags().StringP("chain", "C", "", "Select the chain [ethereum]")
cmd.Flags().StringP("private-key", "K", "", "Specify the private key to store")
_ = cmd.MarkFlagRequired("private-key")
cmd.Flags().String("passphrase", "", "Passphrase to encrypt/decrypt key with")

return cmd
}

func accountListCmd(v *viper.Viper) *cobra.Command {
func accountListCmd(ks keystore.Store) *cobra.Command {
return &cobra.Command{
Use: "list",
Short: "List accounts",
RunE: func(cmd *cobra.Command, args []string) error {
s := settings.New(v)
ks, err := s.Keystore.Produce()
if err != nil {
return errors.WithMessage(err, "could not create `keystore`")
}
addresses, err := ks.GetAddresses()
if err != nil {
return errors.WithMessage(err, "could not get addresses")
}
for _, x := range addresses {
fmt.Println(hex.EncodeToString(x))
cmd.Println(hex.EncodeToString(x))
}
return nil
},
}
}

func getKeyType(cmd *cobra.Command) (string, error) {
keyType, err := cmd.Flags().GetString("key-type")
if err != nil {
return "", errors.WithMessage(err, "failed to get `key-type`")
}
keyType, _ := cmd.Flags().GetString("key-type")
if keyType != "" {
return keyType, nil
}
chain, err := cmd.Flags().GetString("chain")
if err != nil {
return "", errors.WithMessage(err, "failed to get `chain`")
}
chain, _ := cmd.Flags().GetString("chain")
if chain == "" {
return "", errors.Errorf("either `key-type` or `chain` must be specified")
}
Expand Down

0 comments on commit b33cd38

Please sign in to comment.