Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd/ethkey: new tool for key files #15438

Merged
merged 1 commit into from
Dec 21, 2017
Merged

cmd/ethkey: new tool for key files #15438

merged 1 commit into from
Dec 21, 2017

Conversation

stevenroose
Copy link
Contributor

Since I failed building Parity's similar ethkey command line tool, I implemented this one in Go.

It is based entirely on functionality in the codebase, just interfaces them easily through a CLI.

There is currently one issue: v1.20.0 from urfave/cli breaks the --help flag on commands. I created upstream issue urfave/cli#678 to track this and will add a commit updating the cli dependency when it is resolved.

@GitCop
Copy link

GitCop commented Nov 8, 2017

Thank you for your contribution! Your commits seem to not adhere to the repository coding standards

  • Commit: 74ba4982442e1a8f85b1c92787b366b131d1a6f6

  • Commits must be prefixed with the package(s) they modify

  • Commit: 234744a16adbb3793d3a4ea5ae430c68e7c9cd31

  • Commits must be prefixed with the package(s) they modify

Please check the contribution guidelines for more details.


This message was auto-generated by https://gitcop.com

@GitCop
Copy link

GitCop commented Nov 8, 2017

Thank you for your contribution! Your commits seem to not adhere to the repository coding standards

  • Commit: b75596104fba3e7a66c5ad471ce175b9f9529339

  • Commits must be prefixed with the package(s) they modify

  • Commit: 3e38d0a88c040eb2d5d752e6898ca69236a2fe5e

  • Commits must be prefixed with the package(s) they modify

Please check the contribution guidelines for more details.


This message was auto-generated by https://gitcop.com

@holiman
Copy link
Contributor

holiman commented Nov 9, 2017

Have you seen https://github.com/bas-vk/ethsign ? Is there anythiing which differs in the functionality between ethsign (https://github.com/bas-vk/ethsign) and your proposed utility?

Because I'd rather get the code into ethsign and then (perhaps) merge that into a standalone binary. ethsign relies on the account storage, which can either be raw keys, but also other things, such as hardware wallets.

@stevenroose
Copy link
Contributor Author

stevenroose commented Nov 9, 2017 via email

Makefile Outdated
@@ -21,6 +21,11 @@ swarm:
@echo "Done building."
@echo "Run \"$(GOBIN)/swarm\" to launch swarm."

ethkey:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is no need to add this command to Makefile. It can be built using make all.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I removed it.

)

var ( // Commonly used command line flags.
passphraseFlag = cli.StringFlag{
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a dangerous flag because it encourages setting the flag on the command line, where it might end up in history. Command line arguments are visible to any user. Please remove the flag.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well, it's one in three ways. For testing or for the large quantities of files with an empty passphrase, I think it's worth it. I just made a change that makes --passphrase "" work for files with empty passphrases. I think it's easier than touch tempfile; ethkey --passphrasefile tempfile :D

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You can always pipe empty strings into the interactive password input to do stuff like that.

@@ -0,0 +1,322 @@
package main
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

New files in cmd/ need the GPLv3 header. Please copy it from cmd/geth/main.go.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.


// Configure the app instance.
func init() {
app = cli.NewApp()
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use utils.NewApp, which sets version automatically. For its gitCommit, define a global variable called gitCommit. It will be filled in by the linker.

Please don't set app.Copyright.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason why I avoided that is because utils.NewApp sets the version to the geth version. That might be misleading since geth versions might change while the functionality of this CLI will remain the same. (That's actually very likely given the simplicity of this tool.)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

All tools including rlpdump, evm, swarm use the same version. Releases in this repo are go-ethereum releases, not just geth releases.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's fair enough.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

keyfilepath = defaultKeyfilePath
}
var err error
keyfilepath, err = filepath.Abs(keyfilepath)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need the absolute path?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

os.Stat was failing for some reason while I was testing. I tried without and it works fine, so I remove all the filepath.Abs calls. Thanks for the critical suggestion :)

@fjl
Copy link
Contributor

fjl commented Nov 9, 2017

Thank you for this PR! It's a good addition to the toolchain.

@stevenroose stevenroose force-pushed the ethkey branch 2 times, most recently from 8a9db48 to 4418c15 Compare November 10, 2017 10:13

# Usage

## generate
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use full command as heading, e.g.

## `ethkey generate`

Generates a new keyfile.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. Not sure how well that would work with the longer arguments in sign and verify, though. Let me check how GitHub renders it here :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't look that nice. I'll probably change that to regular text

*`ethkey generate`*

@fjl fjl changed the title Add ethkey command line tool cmd/ethkey: new tool for key files Nov 10, 2017
@stevenroose
Copy link
Contributor Author

I'm also thinking about a --json flag that prints results in json so that it is machine-usable. F.e. you could store the private key of a keyfile using the following command:

ethkey inspect --passphrase "" myfile.json --json | jq '.privateKey' > myfile.key

@GitCop
Copy link

GitCop commented Nov 10, 2017

Thank you for your contribution! Your commits seem to not adhere to the repository coding standards

  • Commit: 28077828f3f82fb0532e37865438352c3512e306
  • Commits must be prefixed with the package(s) they modify

Please check the contribution guidelines for more details.


This message was auto-generated by https://gitcop.com

@stevenroose
Copy link
Contributor Author

One extra thing I'd like to add before having this merged is creating a keyfile from a raw private key.

@fjl fjl added this to the 1.8.0 milestone Nov 13, 2017
@holiman
Copy link
Contributor

holiman commented Nov 29, 2017

I am not overly fond of making it so easy to extract the raw private keys. I mean, sure, it should be possible , but I think it's good that it's not easy. People are, today, not exporting and importing raw private keys, and I think that's a good thing.

By releasing this, we're enabling people to handle raw privkeys on usb-sticks between their computers. And I'm not sure that's a net benefit.

@stevenroose
Copy link
Contributor Author

@holiman The reason why I created this for myself in the first place was to be able to extract the raw private keys. I agree that it should be hard, but it should be possible without having to write your own tool.. There is really not a single other way to get the raw private key than to create something like this yourself.

It doesn't have to be advertised. I could also f.e. have inspect only print public info and have inspect -p print the private info (to not accidentally have your private key in stdout).

@holiman
Copy link
Contributor

holiman commented Nov 29, 2017

@stevenroose exporting the raw private key should, imo, at least involve being shown a very explicit warning about the operation, and having to enter some text to confirm - maybe random text, e.g. "Do you want to proceed? Enter 93281 to confirm".

@fjl
Copy link
Contributor

fjl commented Nov 29, 2017

I'm super happy about this PR and want to see ethkey in the next release. There's only a few remaining concerns that I have with this PR:

Should the tool handle transaction signing? I think yes, but we can add that in a subsequent PR.

Argument handling is complicated:

  • Users can pass the private key as a hex string or a file.
  • Users can pass the message to sign as a file or string.
  • There are too many ways to input the password (flag, file, terminal input).

I'll think about a good proposal for the latter issue.

@stevenroose
Copy link
Contributor Author

Yeah that's always concerns for those kind of utilities. Too many ways to input data.

I will rename sign to signmessage to make sure it uses the Ethereum signed message: %s way for signing so it cannot be used for raw data.

Input is very welcome for the way we handle input data.

@fjl what is your opinion about outputting private keys? I'm personally against some random input like @holiman proposed. But I'd be ok with moving it to a --private flag. I just want to make sure the CLI stays usable by machines using the --json output.

@stevenroose
Copy link
Contributor Author

stevenroose commented Nov 29, 2017

On an extra note: most of those "too many options to input data" comes to making the code messy and harder to maintain. So I believe a great deal can be done code-wise to make it acceptable. Having a ton of flags is not necessarily a problem, most users will just look for the one they need, find it, and use it.

So if we can keep it clean code-wise, I think it should be acceptable.

EDIT: Next to that, intuitive defaults are also key. Extra functionality can confuse users, but having a very simple default functionality can resolve that for a big part.

@fjl
Copy link
Contributor

fjl commented Dec 1, 2017

Not sure about inputting random text. I can see both sides. My own view is that users already need to enter the password to dump the key so maybe that's good enough. Other ideas:

  • Give an unwieldy name to the subcommand that does this, e.g. ethkey export-private-key
  • Do not provide a way to dump into a file from the command itself, output the raw private key bytes to stdout so they can be copied/pasted without hitting disk. Users can still use shell redirection if they absolutely want it in a file.

About "too many ways to input data":

ethkey should be a sharp, focused tool.

There should be one way to provide the private key. IMHO that way should be "encrypted key file". All subcommands should take a key path as the (required) first argument, pointing to a JSON file on disk. That's sufficient for the beginning. We can expand this at some point if lots of people see the need to deal with keys in a different way.

Likewise, we should reduce the number of ways to input the passphrase. My suggestion is to only accept it via stdin because it is the most secure/private way to pass data to another program. Users can always script themselves out of this by piping it in.

There is a conflict for the signing commands: we can't read passphrase and message from the same stdin stream. IMHO these commands should accept the unsigned tx/message as the second argument (because unsigned tx/message needs less security than the passphrase). There can be a local flag (e.g. -f) to read it from a file instead.

For output, I'm fine with having a human-readable and machine-readable (JSON) version.

@holiman
Copy link
Contributor

holiman commented Dec 1, 2017

I agree with the points @fjl made. However, I still think ethkey export-private-key should be accompanied with a text, something like this:

WARNING!
This will output the raw private key to the console. A raw private key gives total 
access to the corresponding account. Use extreme caution when handling raw 
keys. Most tools can handle encrypted keyfiles, and you don't normally even
need the raw private key. 

Are you quite sure you want to export the raw private key? [y/N]

As Felix says, you can use bash to skip through that anyway, but at least it would be harder to trick an unsuspecting user into doing it.

@stevenroose
Copy link
Contributor Author

Made some changes. Most of the comments should have been addressed.

All subcommands should take a key path as the (required) first argument, pointing to a JSON file on disk.

This is now true, except of course for verifymessage since it has to take an address, verifying when you have the keyfile makes little sense.

However, I still think ethkey export-private-key should be accompanied with a text, something like this:

This is not true right now, but the private key is hidden behind a --private flag. Requiring additional input makes it too hard to use the tool from a shell script.

My suggestion is to only accept it via stdin because it is the most secure/private way to pass data to another program. Users can always script themselves out of this by piping it in.

I kept a flag to point to a passprase file (a lot of keyfiles have an empty passphrase so they can be used by passing /dev/null in this case). No longer being able to pass the passphrase literally in the arguments prevents leaking it into shell history.

It's a tool that serves as a command line interface to the basic key
management functionalities of geth.
It currently supports:
 - generating keyfiles
 - inspecting keyfiles (print public and private key)
 - signing messages
 - verifying signed messages
@fjl fjl merged commit eeb53bc into ethereum:master Dec 21, 2017
mariameda pushed a commit to NiluPlatform/go-nilu that referenced this pull request Aug 23, 2018
ethkey is a new tool that serves as a command line interface to
the basic key management functionalities of geth. It currently
supports:
 
 - generating keyfiles
 - inspecting keyfiles (print public and private key)
 - signing messages
 - verifying signed messages
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants