// 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 . 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/google/uuid" "gopkg.in/urfave/cli.v1" ) type outputGenerate struct { Address string AddressEIP55 string } var ( privateKeyFlag = cli.StringFlag{ Name: "privatekey", Usage: "file containing a raw private key to encrypt", } lightKDFFlag = cli.BoolFlag{ Name: "lightkdf", Usage: "use less secure scrypt parameters", } ) var commandGenerate = cli.Command{ Name: "generate", Usage: "generate new keyfile", ArgsUsage: "[ ]", Description: ` Generate a new keyfile. 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. `, Flags: []cli.Flag{ passphraseFlag, jsonFlag, privateKeyFlag, lightKDFFlag, }, 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 var err error if file := ctx.String(privateKeyFlag.Name); file != "" { // Load private key from file. privateKey, err = crypto.LoadECDSA(file) if err != nil { utils.Fatalf("Can't load private key: %v", err) } } else { // If not loaded, generate random. privateKey, err = crypto.GenerateKey() if err != nil { utils.Fatalf("Failed to generate random private key: %v", err) } } // Create the keyfile object with a random UUID. UUID, err := uuid.NewRandom() if err != nil { utils.Fatalf("Failed to generate random uuid: %v", err) } key := &keystore.Key{ Id: UUID, Address: crypto.PubkeyToAddress(privateKey.PublicKey), PrivateKey: privateKey, } // Encrypt key with passphrase. passphrase := getPassphrase(ctx, true) scryptN, scryptP := keystore.StandardScryptN, keystore.StandardScryptP if ctx.Bool(lightKDFFlag.Name) { scryptN, scryptP = keystore.LightScryptN, keystore.LightScryptP } keyjson, err := keystore.EncryptKey(key, passphrase, scryptN, scryptP) 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 { fmt.Println("Address:", out.Address) } return nil }, }