mirror of https://github.com/status-im/op-geth.git
max paranoia mode to UNsupport unencrypted keys entirely
- remove account export functionality from CLI - remove accountExport method, - remove unencrypted-keys flag from everywhere - improve documentation
This commit is contained in:
parent
abbdf41560
commit
7577d12614
|
@ -208,6 +208,8 @@ func zeroKey(k *ecdsa.PrivateKey) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// USE WITH CAUTION = this will save an unencrypted private key on disk
|
||||||
|
// no cli or js interface
|
||||||
func (am *Manager) Export(path string, addr []byte, keyAuth string) error {
|
func (am *Manager) Export(path string, addr []byte, keyAuth string) error {
|
||||||
key, err := am.keyStore.GetKey(addr, keyAuth)
|
key, err := am.keyStore.GetKey(addr, keyAuth)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -77,9 +77,8 @@ The output of this command is supposed to be machine-readable.
|
||||||
},
|
},
|
||||||
|
|
||||||
{
|
{
|
||||||
Action: accountList,
|
Name: "wallet",
|
||||||
Name: "wallet",
|
Usage: "ethereum presale wallet",
|
||||||
Usage: "ethereum presale wallet",
|
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
{
|
{
|
||||||
Action: importWallet,
|
Action: importWallet,
|
||||||
|
@ -92,6 +91,28 @@ The output of this command is supposed to be machine-readable.
|
||||||
Action: accountList,
|
Action: accountList,
|
||||||
Name: "account",
|
Name: "account",
|
||||||
Usage: "manage accounts",
|
Usage: "manage accounts",
|
||||||
|
Description: `
|
||||||
|
|
||||||
|
Manage accounts lets you create new accounts, list all existing accounts,
|
||||||
|
import a private key into a new account.
|
||||||
|
|
||||||
|
It supports interactive mode, when you are prompted for password as well as
|
||||||
|
non-interactive mode where passwords are supplied via a given password file.
|
||||||
|
Non-interactive mode is only meant for scripted use on test networks or known
|
||||||
|
safe environments.
|
||||||
|
|
||||||
|
Make sure you remember the password you gave when creating a new account (with
|
||||||
|
either new or import). Without it you are not able to unlock your account.
|
||||||
|
|
||||||
|
Note that exporting your key in unencrypted format is NOT supported.
|
||||||
|
|
||||||
|
Keys are stored under <DATADIR>/keys.
|
||||||
|
It is safe to transfer the entire directory or the individual keys therein
|
||||||
|
between ethereum nodes.
|
||||||
|
Make sure you backup your keys regularly.
|
||||||
|
|
||||||
|
And finally. DO NOT FORGET YOUR PASSWORD.
|
||||||
|
`,
|
||||||
Subcommands: []cli.Command{
|
Subcommands: []cli.Command{
|
||||||
{
|
{
|
||||||
Action: accountList,
|
Action: accountList,
|
||||||
|
@ -106,12 +127,18 @@ The output of this command is supposed to be machine-readable.
|
||||||
|
|
||||||
ethereum account new
|
ethereum account new
|
||||||
|
|
||||||
Creates a new accountThe account is saved in encrypted format, you are prompted for a passphrase.
|
Creates a new account. Prints the address.
|
||||||
You must remember this passphrase to unlock your account in future.
|
|
||||||
|
The account is saved in encrypted format, you are prompted for a passphrase.
|
||||||
|
|
||||||
|
You must remember this passphrase to unlock your account in the future.
|
||||||
|
|
||||||
For non-interactive use the passphrase can be specified with the --password flag:
|
For non-interactive use the passphrase can be specified with the --password flag:
|
||||||
|
|
||||||
ethereum --password <passwordfile> account new
|
ethereum --password <passwordfile> account new
|
||||||
|
|
||||||
|
Note, this is meant to be used for testing only, it is a bad idea to save your
|
||||||
|
password to file or expose in any other way.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -122,38 +149,23 @@ For non-interactive use the passphrase can be specified with the --password flag
|
||||||
|
|
||||||
ethereum account import <keyfile>
|
ethereum account import <keyfile>
|
||||||
|
|
||||||
Imports a private key from <keyfile> and creates a new account with the address
|
Imports an unencrypted private key from <keyfile> and creates a new account.
|
||||||
derived from the key.
|
Prints the address.
|
||||||
|
|
||||||
The keyfile is assumed to contain an unencrypted private key in canonical EC
|
The keyfile is assumed to contain an unencrypted private key in canonical EC
|
||||||
format.
|
raw bytes format.
|
||||||
|
|
||||||
The account is saved in encrypted format, you are prompted for a passphrase.
|
The account is saved in encrypted format, you are prompted for a passphrase.
|
||||||
You must remember this passphrase to unlock your account in future.
|
|
||||||
|
You must remember this passphrase to unlock your account in the future.
|
||||||
|
|
||||||
For non-interactive use the passphrase can be specified with the -password flag:
|
For non-interactive use the passphrase can be specified with the -password flag:
|
||||||
|
|
||||||
ethereum --password <passwordfile> account import <keyfile>
|
ethereum --password <passwordfile> account import <keyfile>
|
||||||
|
|
||||||
`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
Action: accountExport,
|
|
||||||
Name: "export",
|
|
||||||
Usage: "export an account into key file",
|
|
||||||
Description: `
|
|
||||||
|
|
||||||
ethereum account export <address> <keyfile>
|
|
||||||
|
|
||||||
Exports the given account's private key into keyfile using the canonical EC
|
|
||||||
format.
|
|
||||||
The account needs to be unlocked, if it is not the user is prompted for a
|
|
||||||
passphrase to unlock it.
|
|
||||||
For non-interactive use, the passphrase can be specified with the --unlock flag:
|
|
||||||
|
|
||||||
ethereum --password <passwrdfile> account export <address> <keyfile>
|
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
As you can directly copy your encrypted accounts to another ethereum instance,
|
As you can directly copy your encrypted accounts to another ethereum instance,
|
||||||
this import/export mechanism is not needed when you transfer an account between
|
this import mechanism is not needed when you transfer an account between
|
||||||
nodes.
|
nodes.
|
||||||
`,
|
`,
|
||||||
},
|
},
|
||||||
|
@ -217,7 +229,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
|
||||||
utils.RPCEnabledFlag,
|
utils.RPCEnabledFlag,
|
||||||
utils.RPCListenAddrFlag,
|
utils.RPCListenAddrFlag,
|
||||||
utils.RPCPortFlag,
|
utils.RPCPortFlag,
|
||||||
utils.UnencryptedKeysFlag,
|
|
||||||
utils.VMDebugFlag,
|
utils.VMDebugFlag,
|
||||||
utils.ProtocolVersionFlag,
|
utils.ProtocolVersionFlag,
|
||||||
utils.NetworkIdFlag,
|
utils.NetworkIdFlag,
|
||||||
|
@ -290,19 +301,17 @@ func execJSFiles(ctx *cli.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
|
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
|
||||||
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
|
var err error
|
||||||
var err error
|
// Load startup keys. XXX we are going to need a different format
|
||||||
// Load startup keys. XXX we are going to need a different format
|
// Attempt to unlock the account
|
||||||
// Attempt to unlock the account
|
passphrase = getPassPhrase(ctx, "", false)
|
||||||
passphrase = getPassPhrase(ctx, "", false)
|
accbytes := common.FromHex(account)
|
||||||
accbytes := common.FromHex(account)
|
if len(accbytes) == 0 {
|
||||||
if len(accbytes) == 0 {
|
utils.Fatalf("Invalid account address '%s'", account)
|
||||||
utils.Fatalf("Invalid account address '%s'", account)
|
}
|
||||||
}
|
err = am.Unlock(accbytes, passphrase)
|
||||||
err = am.Unlock(accbytes, passphrase)
|
if err != nil {
|
||||||
if err != nil {
|
utils.Fatalf("Unlock account failed '%v'", err)
|
||||||
utils.Fatalf("Unlock account failed '%v'", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -343,32 +352,30 @@ func accountList(ctx *cli.Context) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase string) {
|
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase string) {
|
||||||
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
|
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
|
||||||
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
|
if len(passfile) == 0 {
|
||||||
if len(passfile) == 0 {
|
fmt.Println(desc)
|
||||||
fmt.Println(desc)
|
auth, err := readPassword("Passphrase: ", true)
|
||||||
auth, err := readPassword("Passphrase: ", true)
|
if err != nil {
|
||||||
|
utils.Fatalf("%v", err)
|
||||||
|
}
|
||||||
|
if confirmation {
|
||||||
|
confirm, err := readPassword("Repeat Passphrase: ", false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
utils.Fatalf("%v", err)
|
utils.Fatalf("%v", err)
|
||||||
}
|
}
|
||||||
if confirmation {
|
if auth != confirm {
|
||||||
confirm, err := readPassword("Repeat Passphrase: ", false)
|
utils.Fatalf("Passphrases did not match.")
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("%v", err)
|
|
||||||
}
|
|
||||||
if auth != confirm {
|
|
||||||
utils.Fatalf("Passphrases did not match.")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
passphrase = auth
|
|
||||||
|
|
||||||
} else {
|
|
||||||
passbytes, err := ioutil.ReadFile(passfile)
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
|
|
||||||
}
|
|
||||||
passphrase = string(passbytes)
|
|
||||||
}
|
}
|
||||||
|
passphrase = auth
|
||||||
|
|
||||||
|
} else {
|
||||||
|
passbytes, err := ioutil.ReadFile(passfile)
|
||||||
|
if err != nil {
|
||||||
|
utils.Fatalf("Unable to read password file '%s': %v", passfile, err)
|
||||||
|
}
|
||||||
|
passphrase = string(passbytes)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -417,24 +424,6 @@ func accountImport(ctx *cli.Context) {
|
||||||
fmt.Printf("Address: %x\n", acct)
|
fmt.Printf("Address: %x\n", acct)
|
||||||
}
|
}
|
||||||
|
|
||||||
func accountExport(ctx *cli.Context) {
|
|
||||||
account := ctx.Args().First()
|
|
||||||
if len(account) == 0 {
|
|
||||||
utils.Fatalf("account address must be given as first argument")
|
|
||||||
}
|
|
||||||
keyfile := ctx.Args().Get(1)
|
|
||||||
if len(keyfile) == 0 {
|
|
||||||
utils.Fatalf("keyfile must be given as second argument")
|
|
||||||
}
|
|
||||||
am := utils.GetAccountManager(ctx)
|
|
||||||
auth := unlockAccount(ctx, am, account)
|
|
||||||
|
|
||||||
err := am.Export(keyfile, common.FromHex(account), auth)
|
|
||||||
if err != nil {
|
|
||||||
utils.Fatalf("Account export failed: %v", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func importchain(ctx *cli.Context) {
|
func importchain(ctx *cli.Context) {
|
||||||
if len(ctx.Args()) != 1 {
|
if len(ctx.Args()) != 1 {
|
||||||
utils.Fatalf("This command requires an argument.")
|
utils.Fatalf("This command requires an argument.")
|
||||||
|
|
|
@ -97,14 +97,9 @@ var (
|
||||||
Usage: "Enable mining",
|
Usage: "Enable mining",
|
||||||
}
|
}
|
||||||
|
|
||||||
// key settings
|
|
||||||
UnencryptedKeysFlag = cli.BoolFlag{
|
|
||||||
Name: "unencrypted-keys",
|
|
||||||
Usage: "disable private key disk encryption (for testing)",
|
|
||||||
}
|
|
||||||
UnlockedAccountFlag = cli.StringFlag{
|
UnlockedAccountFlag = cli.StringFlag{
|
||||||
Name: "unlock",
|
Name: "unlock",
|
||||||
Usage: "unlock the account given until this program exits (prompts for password).",
|
Usage: "unlock the account given until this program exits (prompts for password). '--unlock coinbase' unlocks the primary (coinbase) account",
|
||||||
Value: "",
|
Value: "",
|
||||||
}
|
}
|
||||||
PasswordFileFlag = cli.StringFlag{
|
PasswordFileFlag = cli.StringFlag{
|
||||||
|
@ -249,12 +244,7 @@ func GetChain(ctx *cli.Context) (*core.ChainManager, common.Database, common.Dat
|
||||||
|
|
||||||
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
|
func GetAccountManager(ctx *cli.Context) *accounts.Manager {
|
||||||
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
dataDir := ctx.GlobalString(DataDirFlag.Name)
|
||||||
var ks crypto.KeyStore2
|
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
||||||
if ctx.GlobalBool(UnencryptedKeysFlag.Name) {
|
|
||||||
ks = crypto.NewKeyStorePlain(path.Join(dataDir, "plainkeys"))
|
|
||||||
} else {
|
|
||||||
ks = crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
|
|
||||||
}
|
|
||||||
return accounts.NewManager(ks)
|
return accounts.NewManager(ks)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue