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:
zelig 2015-03-26 18:55:39 +00:00
parent abbdf41560
commit 7577d12614
3 changed files with 74 additions and 93 deletions

@ -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 {
key, err := am.keyStore.GetKey(addr, keyAuth)
if err != nil {

@ -77,9 +77,8 @@ The output of this command is supposed to be machine-readable.
},
{
Action: accountList,
Name: "wallet",
Usage: "ethereum presale wallet",
Name: "wallet",
Usage: "ethereum presale wallet",
Subcommands: []cli.Command{
{
Action: importWallet,
@ -92,6 +91,28 @@ The output of this command is supposed to be machine-readable.
Action: accountList,
Name: "account",
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{
{
Action: accountList,
@ -106,12 +127,18 @@ The output of this command is supposed to be machine-readable.
ethereum account new
Creates a new accountThe account is saved in encrypted format, you are prompted for a passphrase.
You must remember this passphrase to unlock your account in future.
Creates a new account. Prints the address.
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:
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>
Imports a private key from <keyfile> and creates a new account with the address
derived from the key.
Imports an unencrypted private key from <keyfile> and creates a new account.
Prints the address.
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.
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:
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:
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.
`,
},
@ -217,7 +229,6 @@ JavaScript API. See https://github.com/ethereum/go-ethereum/wiki/Javascipt-Conso
utils.RPCEnabledFlag,
utils.RPCListenAddrFlag,
utils.RPCPortFlag,
utils.UnencryptedKeysFlag,
utils.VMDebugFlag,
utils.ProtocolVersionFlag,
utils.NetworkIdFlag,
@ -290,19 +301,17 @@ func execJSFiles(ctx *cli.Context) {
}
func unlockAccount(ctx *cli.Context, am *accounts.Manager, account string) (passphrase string) {
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
var err error
// Load startup keys. XXX we are going to need a different format
// Attempt to unlock the account
passphrase = getPassPhrase(ctx, "", false)
accbytes := common.FromHex(account)
if len(accbytes) == 0 {
utils.Fatalf("Invalid account address '%s'", account)
}
err = am.Unlock(accbytes, passphrase)
if err != nil {
utils.Fatalf("Unlock account failed '%v'", err)
}
var err error
// Load startup keys. XXX we are going to need a different format
// Attempt to unlock the account
passphrase = getPassPhrase(ctx, "", false)
accbytes := common.FromHex(account)
if len(accbytes) == 0 {
utils.Fatalf("Invalid account address '%s'", account)
}
err = am.Unlock(accbytes, passphrase)
if err != nil {
utils.Fatalf("Unlock account failed '%v'", err)
}
return
}
@ -343,32 +352,30 @@ func accountList(ctx *cli.Context) {
}
func getPassPhrase(ctx *cli.Context, desc string, confirmation bool) (passphrase string) {
if !ctx.GlobalBool(utils.UnencryptedKeysFlag.Name) {
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
if len(passfile) == 0 {
fmt.Println(desc)
auth, err := readPassword("Passphrase: ", true)
passfile := ctx.GlobalString(utils.PasswordFileFlag.Name)
if len(passfile) == 0 {
fmt.Println(desc)
auth, err := readPassword("Passphrase: ", true)
if err != nil {
utils.Fatalf("%v", err)
}
if confirmation {
confirm, err := readPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
if confirmation {
confirm, err := readPassword("Repeat Passphrase: ", false)
if err != nil {
utils.Fatalf("%v", err)
}
if auth != confirm {
utils.Fatalf("Passphrases did not match.")
}
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
}
@ -417,24 +424,6 @@ func accountImport(ctx *cli.Context) {
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) {
if len(ctx.Args()) != 1 {
utils.Fatalf("This command requires an argument.")

@ -97,14 +97,9 @@ var (
Usage: "Enable mining",
}
// key settings
UnencryptedKeysFlag = cli.BoolFlag{
Name: "unencrypted-keys",
Usage: "disable private key disk encryption (for testing)",
}
UnlockedAccountFlag = cli.StringFlag{
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: "",
}
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 {
dataDir := ctx.GlobalString(DataDirFlag.Name)
var ks crypto.KeyStore2
if ctx.GlobalBool(UnencryptedKeysFlag.Name) {
ks = crypto.NewKeyStorePlain(path.Join(dataDir, "plainkeys"))
} else {
ks = crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
}
ks := crypto.NewKeyStorePassphrase(path.Join(dataDir, "keys"))
return accounts.NewManager(ks)
}