| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | // Copyright 2017 The go-ethereum Authors | 
					
						
							|  |  |  | // This file is part of go-ethereum. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is free software: you can redistribute it and/or modify | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by | 
					
						
							|  |  |  | // the Free Software Foundation, either version 3 of the License, or | 
					
						
							|  |  |  | // (at your option) any later version. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // go-ethereum is distributed in the hope that it will be useful, | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 
					
						
							|  |  |  | // GNU General Public License for more details. | 
					
						
							|  |  |  | // | 
					
						
							|  |  |  | // You should have received a copy of the GNU General Public License | 
					
						
							|  |  |  | // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | package main | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"crypto/ecdsa" | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							|  |  |  | 	"io/ioutil" | 
					
						
							|  |  |  | 	"os" | 
					
						
							|  |  |  | 	"path/filepath" | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/accounts/keystore" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/cmd/utils" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/crypto" | 
					
						
							|  |  |  | 	"github.com/pborman/uuid" | 
					
						
							|  |  |  | 	"gopkg.in/urfave/cli.v1" | 
					
						
							|  |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | type outputGenerate struct { | 
					
						
							|  |  |  | 	Address      string | 
					
						
							|  |  |  | 	AddressEIP55 string | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | var commandGenerate = cli.Command{ | 
					
						
							|  |  |  | 	Name:      "generate", | 
					
						
							|  |  |  | 	Usage:     "generate new keyfile", | 
					
						
							|  |  |  | 	ArgsUsage: "[ <keyfile> ]", | 
					
						
							|  |  |  | 	Description: ` | 
					
						
							|  |  |  | Generate a new keyfile. | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | If you want to encrypt an existing private key, it can be specified by setting | 
					
						
							|  |  |  | --privatekey with the location of the file containing the private key. | 
					
						
							|  |  |  | `, | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 	Flags: []cli.Flag{ | 
					
						
							|  |  |  | 		passphraseFlag, | 
					
						
							|  |  |  | 		jsonFlag, | 
					
						
							|  |  |  | 		cli.StringFlag{ | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 			Name:  "privatekey", | 
					
						
							|  |  |  | 			Usage: "file containing a raw private key to encrypt", | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 		}, | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | 	Action: func(ctx *cli.Context) error { | 
					
						
							|  |  |  | 		// Check if keyfile path given and make sure it doesn't already exist. | 
					
						
							|  |  |  | 		keyfilepath := ctx.Args().First() | 
					
						
							|  |  |  | 		if keyfilepath == "" { | 
					
						
							|  |  |  | 			keyfilepath = defaultKeyfileName | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if _, err := os.Stat(keyfilepath); err == nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Keyfile already exists at %s.", keyfilepath) | 
					
						
							|  |  |  | 		} else if !os.IsNotExist(err) { | 
					
						
							|  |  |  | 			utils.Fatalf("Error checking if keyfile exists: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		var privateKey *ecdsa.PrivateKey | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 		var err error | 
					
						
							|  |  |  | 		if file := ctx.String("privatekey"); file != "" { | 
					
						
							|  |  |  | 			// Load private key from file. | 
					
						
							|  |  |  | 			privateKey, err = crypto.LoadECDSA(file) | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 			if err != nil { | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 				utils.Fatalf("Can't load private key: %v", err) | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 		} else { | 
					
						
							|  |  |  | 			// If not loaded, generate random. | 
					
						
							|  |  |  | 			privateKey, err = crypto.GenerateKey() | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 			if err != nil { | 
					
						
							|  |  |  | 				utils.Fatalf("Failed to generate random private key: %v", err) | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Create the keyfile object with a random UUID. | 
					
						
							|  |  |  | 		id := uuid.NewRandom() | 
					
						
							|  |  |  | 		key := &keystore.Key{ | 
					
						
							|  |  |  | 			Id:         id, | 
					
						
							|  |  |  | 			Address:    crypto.PubkeyToAddress(privateKey.PublicKey), | 
					
						
							|  |  |  | 			PrivateKey: privateKey, | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Encrypt key with passphrase. | 
					
						
							| 
									
										
										
										
											2018-06-08 15:07:07 +02:00
										 |  |  | 		passphrase := promptPassphrase(true) | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 		keyjson, err := keystore.EncryptKey(key, passphrase, keystore.StandardScryptN, keystore.StandardScryptP) | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Error encrypting key: %v", err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Store the file to disk. | 
					
						
							|  |  |  | 		if err := os.MkdirAll(filepath.Dir(keyfilepath), 0700); err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Could not create directory %s", filepath.Dir(keyfilepath)) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if err := ioutil.WriteFile(keyfilepath, keyjson, 0600); err != nil { | 
					
						
							|  |  |  | 			utils.Fatalf("Failed to write keyfile to %s: %v", keyfilepath, err) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// Output some information. | 
					
						
							|  |  |  | 		out := outputGenerate{ | 
					
						
							|  |  |  | 			Address: key.Address.Hex(), | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		if ctx.Bool(jsonFlag.Name) { | 
					
						
							|  |  |  | 			mustPrintJSON(out) | 
					
						
							|  |  |  | 		} else { | 
					
						
							| 
									
										
										
										
											2018-01-16 15:42:41 +01:00
										 |  |  | 			fmt.Println("Address:", out.Address) | 
					
						
							| 
									
										
										
										
											2017-12-21 11:36:05 +01:00
										 |  |  | 		} | 
					
						
							|  |  |  | 		return nil | 
					
						
							|  |  |  | 	}, | 
					
						
							|  |  |  | } |