github.com/iotexproject/iotex-core@v1.14.1-rc1/ioctl/newcmd/account/accountupdate.go (about) 1 // Copyright (c) 2019 IoTeX Foundation 2 // This source code is provided 'as is' and no warranties are given as to title or non-infringement, merchantability 3 // or fitness for purpose and, to the extent permitted by law, all liability for your use of the code is disclaimed. 4 // This source code is governed by Apache License 2.0 that can be found in the LICENSE file. 5 6 package account 7 8 import ( 9 "bytes" 10 "fmt" 11 12 "github.com/iotexproject/go-pkgs/crypto" 13 "github.com/iotexproject/go-pkgs/hash" 14 "github.com/iotexproject/iotex-address/address" 15 "github.com/pkg/errors" 16 "github.com/spf13/cobra" 17 18 "github.com/iotexproject/iotex-core/ioctl" 19 "github.com/iotexproject/iotex-core/ioctl/config" 20 ) 21 22 // Multi-language support 23 var ( 24 _updateCmdShorts = map[config.Language]string{ 25 config.English: "Update password for IoTeX account", 26 config.Chinese: "为IoTeX账户更新密码", 27 } 28 _updateCmdUses = map[config.Language]string{ 29 config.English: "update [ALIAS|ADDRESS]", 30 config.Chinese: "update [别名|地址]", 31 } 32 ) 33 34 // NewAccountUpdate represents the account update command 35 func NewAccountUpdate(client ioctl.Client) *cobra.Command { 36 use, _ := client.SelectTranslation(_updateCmdUses) 37 short, _ := client.SelectTranslation(_updateCmdShorts) 38 39 return &cobra.Command{ 40 Use: use, 41 Short: short, 42 Args: cobra.RangeArgs(0, 1), 43 RunE: func(cmd *cobra.Command, args []string) error { 44 cmd.SilenceUsage = true 45 arg := "" 46 if len(args) == 1 { 47 arg = args[0] 48 } 49 50 acc, err := client.AddressWithDefaultIfNotExist(arg) 51 if err != nil { 52 return err 53 } 54 addr, err := address.FromString(acc) 55 if err != nil { 56 return errors.Wrap(err, "failed to convert string into addr") 57 } 58 59 if client.IsCryptoSm2() { 60 // find the pem file and update 61 filePath, err := findSm2PemFile(client, addr) 62 if err != nil { 63 return errors.Wrapf(err, "crypto file of account #%s not found", addr) 64 } 65 if err = readSecretAndUpdate(client, cmd, acc, 66 func(currentPassword string) error { 67 _, err = crypto.ReadPrivateKeyFromPem(filePath, currentPassword) 68 if err != nil { 69 return errors.Wrap(err, "error occurs when checking current password") 70 } 71 return nil 72 }, 73 func(currentPassword, newPassword string) error { 74 if err := crypto.UpdatePrivateKeyPasswordToPem(filePath, currentPassword, newPassword); err != nil { 75 return errors.Wrap(err, "failed to update pem file") 76 } 77 return nil 78 }, 79 ); err != nil { 80 return err 81 } 82 } else { 83 // find the keystore and update 84 ks := client.NewKeyStore() 85 for _, v := range ks.Accounts() { 86 if bytes.Equal(addr.Bytes(), v.Address.Bytes()) { 87 if err = readSecretAndUpdate(client, cmd, acc, 88 func(currentPassword string) error { 89 _, err = ks.SignHashWithPassphrase(v, currentPassword, hash.ZeroHash256[:]) 90 if err != nil { 91 return errors.Wrap(err, "error occurs when checking current password") 92 } 93 return nil 94 }, 95 func(currentPassword, newPassword string) error { 96 if err := ks.Update(v, currentPassword, newPassword); err != nil { 97 return errors.Wrap(err, "failed to update keystore") 98 } 99 return nil 100 }, 101 ); err != nil { 102 return err 103 } 104 } 105 } 106 } 107 cmd.Println(fmt.Sprintf("Account #%s has been updated.", acc)) 108 return nil 109 }, 110 } 111 } 112 113 func readSecretAndUpdate(client ioctl.Client, cmd *cobra.Command, acc string, 114 checkPwdFunc func(currentPassword string) error, 115 updatePwdFunc func(currentPassword, newPassword string) error) error { 116 cmd.Println(fmt.Sprintf("#%s: Enter current password\n", acc)) 117 currentPassword, err := client.ReadSecret() 118 if err != nil { 119 return errors.Wrap(err, "failed to get current password") 120 } 121 if err = checkPwdFunc(currentPassword); err != nil { 122 return err 123 } 124 cmd.Println(fmt.Sprintf("#%s: Enter new password\n", acc)) 125 newPassword, err := client.ReadSecret() 126 if err != nil { 127 return errors.Wrap(err, "failed to get new password") 128 } 129 cmd.Println(fmt.Sprintf("#%s: Enter new password again\n", acc)) 130 newPasswordAgain, err := client.ReadSecret() 131 if err != nil { 132 return errors.Wrap(err, "failed to get new password") 133 } 134 if newPassword != newPasswordAgain { 135 return ErrPasswdNotMatch 136 } 137 return updatePwdFunc(currentPassword, newPassword) 138 }