Browse Source

cmd/ethkey: add command to change key passphrase (#16516)

This change introduces 

    ethkey changepassphrase <keyfile>

to change the passphrase of a key file.
Steven Roose 7 years ago
parent
commit
13af276418
6 changed files with 100 additions and 19 deletions
  1. 72 0
      cmd/ethkey/changepassphrase.go
  2. 1 1
      cmd/ethkey/generate.go
  3. 1 1
      cmd/ethkey/inspect.go
  4. 1 0
      cmd/ethkey/main.go
  5. 1 1
      cmd/ethkey/message.go
  6. 24 16
      cmd/ethkey/utils.go

+ 72 - 0
cmd/ethkey/changepassphrase.go

@@ -0,0 +1,72 @@
+package main
+
+import (
+	"fmt"
+	"io/ioutil"
+	"strings"
+
+	"github.com/ethereum/go-ethereum/accounts/keystore"
+	"github.com/ethereum/go-ethereum/cmd/utils"
+	"gopkg.in/urfave/cli.v1"
+)
+
+var newPassphraseFlag = cli.StringFlag{
+	Name:  "newpasswordfile",
+	Usage: "the file that contains the new passphrase for the keyfile",
+}
+
+var commandChangePassphrase = cli.Command{
+	Name:      "changepassphrase",
+	Usage:     "change the passphrase on a keyfile",
+	ArgsUsage: "<keyfile>",
+	Description: `
+Change the passphrase of a keyfile.`,
+	Flags: []cli.Flag{
+		passphraseFlag,
+		newPassphraseFlag,
+	},
+	Action: func(ctx *cli.Context) error {
+		keyfilepath := ctx.Args().First()
+
+		// Read key from file.
+		keyjson, err := ioutil.ReadFile(keyfilepath)
+		if err != nil {
+			utils.Fatalf("Failed to read the keyfile at '%s': %v", keyfilepath, err)
+		}
+
+		// Decrypt key with passphrase.
+		passphrase := getPassphrase(ctx)
+		key, err := keystore.DecryptKey(keyjson, passphrase)
+		if err != nil {
+			utils.Fatalf("Error decrypting key: %v", err)
+		}
+
+		// Get a new passphrase.
+		fmt.Println("Please provide a new passphrase")
+		var newPhrase string
+		if passFile := ctx.String(newPassphraseFlag.Name); passFile != "" {
+			content, err := ioutil.ReadFile(passFile)
+			if err != nil {
+				utils.Fatalf("Failed to read new passphrase file '%s': %v", passFile, err)
+			}
+			newPhrase = strings.TrimRight(string(content), "\r\n")
+		} else {
+			newPhrase = promptPassphrase(true)
+		}
+
+		// Encrypt the key with the new passphrase.
+		newJson, err := keystore.EncryptKey(key, newPhrase, keystore.StandardScryptN, keystore.StandardScryptP)
+		if err != nil {
+			utils.Fatalf("Error encrypting with new passphrase: %v", err)
+		}
+
+		// Then write the new keyfile in place of the old one.
+		if err := ioutil.WriteFile(keyfilepath, newJson, 600); err != nil {
+			utils.Fatalf("Error writing new keyfile to disk: %v", err)
+		}
+
+		// Don't print anything.  Just return successfully,
+		// producing a positive exit code.
+		return nil
+	},
+}

+ 1 - 1
cmd/ethkey/generate.go

@@ -90,7 +90,7 @@ If you want to encrypt an existing private key, it can be specified by setting
 		}
 		}
 
 
 		// Encrypt key with passphrase.
 		// Encrypt key with passphrase.
-		passphrase := getPassPhrase(ctx, true)
+		passphrase := promptPassphrase(true)
 		keyjson, err := keystore.EncryptKey(key, passphrase, keystore.StandardScryptN, keystore.StandardScryptP)
 		keyjson, err := keystore.EncryptKey(key, passphrase, keystore.StandardScryptN, keystore.StandardScryptP)
 		if err != nil {
 		if err != nil {
 			utils.Fatalf("Error encrypting key: %v", err)
 			utils.Fatalf("Error encrypting key: %v", err)

+ 1 - 1
cmd/ethkey/inspect.go

@@ -60,7 +60,7 @@ make sure to use this feature with great caution!`,
 		}
 		}
 
 
 		// Decrypt key with passphrase.
 		// Decrypt key with passphrase.
-		passphrase := getPassPhrase(ctx, false)
+		passphrase := getPassphrase(ctx)
 		key, err := keystore.DecryptKey(keyjson, passphrase)
 		key, err := keystore.DecryptKey(keyjson, passphrase)
 		if err != nil {
 		if err != nil {
 			utils.Fatalf("Error decrypting key: %v", err)
 			utils.Fatalf("Error decrypting key: %v", err)

+ 1 - 0
cmd/ethkey/main.go

@@ -38,6 +38,7 @@ func init() {
 	app.Commands = []cli.Command{
 	app.Commands = []cli.Command{
 		commandGenerate,
 		commandGenerate,
 		commandInspect,
 		commandInspect,
+		commandChangePassphrase,
 		commandSignMessage,
 		commandSignMessage,
 		commandVerifyMessage,
 		commandVerifyMessage,
 	}
 	}

+ 1 - 1
cmd/ethkey/message.go

@@ -62,7 +62,7 @@ To sign a message contained in a file, use the --msgfile flag.
 		}
 		}
 
 
 		// Decrypt key with passphrase.
 		// Decrypt key with passphrase.
-		passphrase := getPassPhrase(ctx, false)
+		passphrase := getPassphrase(ctx)
 		key, err := keystore.DecryptKey(keyjson, passphrase)
 		key, err := keystore.DecryptKey(keyjson, passphrase)
 		if err != nil {
 		if err != nil {
 			utils.Fatalf("Error decrypting key: %v", err)
 			utils.Fatalf("Error decrypting key: %v", err)

+ 24 - 16
cmd/ethkey/utils.go

@@ -28,26 +28,14 @@ import (
 	"gopkg.in/urfave/cli.v1"
 	"gopkg.in/urfave/cli.v1"
 )
 )
 
 
-// getPassPhrase obtains a passphrase given by the user.  It first checks the
-// --passphrase command line flag and ultimately prompts the user for a
-// passphrase.
-func getPassPhrase(ctx *cli.Context, confirmation bool) string {
-	// Look for the --passphrase flag.
-	passphraseFile := ctx.String(passphraseFlag.Name)
-	if passphraseFile != "" {
-		content, err := ioutil.ReadFile(passphraseFile)
-		if err != nil {
-			utils.Fatalf("Failed to read passphrase file '%s': %v",
-				passphraseFile, err)
-		}
-		return strings.TrimRight(string(content), "\r\n")
-	}
-
-	// Otherwise prompt the user for the passphrase.
+// promptPassphrase prompts the user for a passphrase.  Set confirmation to true
+// to require the user to confirm the passphrase.
+func promptPassphrase(confirmation bool) string {
 	passphrase, err := console.Stdin.PromptPassword("Passphrase: ")
 	passphrase, err := console.Stdin.PromptPassword("Passphrase: ")
 	if err != nil {
 	if err != nil {
 		utils.Fatalf("Failed to read passphrase: %v", err)
 		utils.Fatalf("Failed to read passphrase: %v", err)
 	}
 	}
+
 	if confirmation {
 	if confirmation {
 		confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ")
 		confirm, err := console.Stdin.PromptPassword("Repeat passphrase: ")
 		if err != nil {
 		if err != nil {
@@ -57,9 +45,29 @@ func getPassPhrase(ctx *cli.Context, confirmation bool) string {
 			utils.Fatalf("Passphrases do not match")
 			utils.Fatalf("Passphrases do not match")
 		}
 		}
 	}
 	}
+
 	return passphrase
 	return passphrase
 }
 }
 
 
+// getPassphrase obtains a passphrase given by the user.  It first checks the
+// --passfile command line flag and ultimately prompts the user for a
+// passphrase.
+func getPassphrase(ctx *cli.Context) string {
+	// Look for the --passwordfile flag.
+	passphraseFile := ctx.String(passphraseFlag.Name)
+	if passphraseFile != "" {
+		content, err := ioutil.ReadFile(passphraseFile)
+		if err != nil {
+			utils.Fatalf("Failed to read passphrase file '%s': %v",
+				passphraseFile, err)
+		}
+		return strings.TrimRight(string(content), "\r\n")
+	}
+
+	// Otherwise prompt the user for the passphrase.
+	return promptPassphrase(false)
+}
+
 // signHash is a helper function that calculates a hash for the given message
 // signHash is a helper function that calculates a hash for the given message
 // that can be safely used to calculate a signature from.
 // that can be safely used to calculate a signature from.
 //
 //