2018-01-16 14:42:41 +00: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 10:36:05 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"crypto/ecdsa"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
|
|
|
|
|
|
|
"github.com/ethereum/go-ethereum/accounts/keystore"
|
|
|
|
"github.com/ethereum/go-ethereum/cmd/utils"
|
|
|
|
"github.com/ethereum/go-ethereum/crypto"
|
2021-02-26 14:28:34 +00:00
|
|
|
"github.com/google/uuid"
|
2017-12-21 10:36:05 +00:00
|
|
|
"gopkg.in/urfave/cli.v1"
|
|
|
|
)
|
|
|
|
|
|
|
|
type outputGenerate struct {
|
|
|
|
Address string
|
|
|
|
AddressEIP55 string
|
|
|
|
}
|
|
|
|
|
2022-04-26 07:32:31 +00:00
|
|
|
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",
|
|
|
|
}
|
|
|
|
)
|
|
|
|
|
2017-12-21 10:36:05 +00:00
|
|
|
var commandGenerate = cli.Command{
|
|
|
|
Name: "generate",
|
|
|
|
Usage: "generate new keyfile",
|
|
|
|
ArgsUsage: "[ <keyfile> ]",
|
|
|
|
Description: `
|
|
|
|
Generate a new keyfile.
|
2018-01-16 14:42:41 +00: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 10:36:05 +00:00
|
|
|
Flags: []cli.Flag{
|
|
|
|
passphraseFlag,
|
|
|
|
jsonFlag,
|
2022-04-26 07:32:31 +00:00
|
|
|
privateKeyFlag,
|
|
|
|
lightKDFFlag,
|
2017-12-21 10:36:05 +00: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 14:42:41 +00:00
|
|
|
var err error
|
2022-04-26 07:32:31 +00:00
|
|
|
if file := ctx.String(privateKeyFlag.Name); file != "" {
|
2018-01-16 14:42:41 +00:00
|
|
|
// Load private key from file.
|
|
|
|
privateKey, err = crypto.LoadECDSA(file)
|
2017-12-21 10:36:05 +00:00
|
|
|
if err != nil {
|
2018-01-16 14:42:41 +00:00
|
|
|
utils.Fatalf("Can't load private key: %v", err)
|
2017-12-21 10:36:05 +00:00
|
|
|
}
|
2018-01-16 14:42:41 +00:00
|
|
|
} else {
|
|
|
|
// If not loaded, generate random.
|
|
|
|
privateKey, err = crypto.GenerateKey()
|
2017-12-21 10:36:05 +00:00
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Failed to generate random private key: %v", err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Create the keyfile object with a random UUID.
|
2021-02-26 14:28:34 +00:00
|
|
|
UUID, err := uuid.NewRandom()
|
|
|
|
if err != nil {
|
|
|
|
utils.Fatalf("Failed to generate random uuid: %v", err)
|
|
|
|
}
|
2017-12-21 10:36:05 +00:00
|
|
|
key := &keystore.Key{
|
2021-02-26 14:28:34 +00:00
|
|
|
Id: UUID,
|
2017-12-21 10:36:05 +00:00
|
|
|
Address: crypto.PubkeyToAddress(privateKey.PublicKey),
|
|
|
|
PrivateKey: privateKey,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Encrypt key with passphrase.
|
2020-06-08 09:55:51 +00:00
|
|
|
passphrase := getPassphrase(ctx, true)
|
2020-02-17 11:22:52 +00:00
|
|
|
scryptN, scryptP := keystore.StandardScryptN, keystore.StandardScryptP
|
2022-04-26 07:32:31 +00:00
|
|
|
if ctx.Bool(lightKDFFlag.Name) {
|
2020-02-17 11:22:52 +00:00
|
|
|
scryptN, scryptP = keystore.LightScryptN, keystore.LightScryptP
|
|
|
|
}
|
|
|
|
keyjson, err := keystore.EncryptKey(key, passphrase, scryptN, scryptP)
|
2017-12-21 10:36:05 +00: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))
|
|
|
|
}
|
2022-05-16 09:59:35 +00:00
|
|
|
if err := os.WriteFile(keyfilepath, keyjson, 0600); err != nil {
|
2017-12-21 10:36:05 +00:00
|
|
|
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 14:42:41 +00:00
|
|
|
fmt.Println("Address:", out.Address)
|
2017-12-21 10:36:05 +00:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
},
|
|
|
|
}
|