github.com/ethxdao/go-ethereum@v0.0.0-20221218102228-5ae34a9cc189/cmd/ethkey/generate.go (about) 1 // Copyright 2017 The go-ethereum Authors 2 // This file is part of go-ethereum. 3 // 4 // go-ethereum is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // go-ethereum is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with go-ethereum. If not, see <http://www.gnu.org/licenses/>. 16 17 package main 18 19 import ( 20 "crypto/ecdsa" 21 "fmt" 22 "os" 23 "path/filepath" 24 25 "github.com/ethxdao/go-ethereum/accounts/keystore" 26 "github.com/ethxdao/go-ethereum/cmd/utils" 27 "github.com/ethxdao/go-ethereum/crypto" 28 "github.com/google/uuid" 29 ) 30 31 type outputGenerate struct { 32 Address string 33 AddressEIP55 string 34 } 35 36 var ( 37 privateKeyFlag = &cli.StringFlag{ 38 Name: "privatekey", 39 Usage: "file containing a raw private key to encrypt", 40 } 41 lightKDFFlag = &cli.BoolFlag{ 42 Name: "lightkdf", 43 Usage: "use less secure scrypt parameters", 44 } 45 ) 46 47 var commandGenerate = &cli.Command{ 48 Name: "generate", 49 Usage: "generate new keyfile", 50 ArgsUsage: "[ <keyfile> ]", 51 Description: ` 52 Generate a new keyfile. 53 54 If you want to encrypt an existing private key, it can be specified by setting 55 --privatekey with the location of the file containing the private key. 56 `, 57 Flags: []cli.Flag{ 58 passphraseFlag, 59 jsonFlag, 60 privateKeyFlag, 61 lightKDFFlag, 62 }, 63 Action: func(ctx *cli.Context) error { 64 // Check if keyfile path given and make sure it doesn't already exist. 65 keyfilepath := ctx.Args().First() 66 if keyfilepath == "" { 67 keyfilepath = defaultKeyfileName 68 } 69 if _, err := os.Stat(keyfilepath); err == nil { 70 utils.Fatalf("Keyfile already exists at %s.", keyfilepath) 71 } else if !os.IsNotExist(err) { 72 utils.Fatalf("Error checking if keyfile exists: %v", err) 73 } 74 75 var privateKey *ecdsa.PrivateKey 76 var err error 77 if file := ctx.String(privateKeyFlag.Name); file != "" { 78 // Load private key from file. 79 privateKey, err = crypto.LoadECDSA(file) 80 if err != nil { 81 utils.Fatalf("Can't load private key: %v", err) 82 } 83 } else { 84 // If not loaded, generate random. 85 privateKey, err = crypto.GenerateKey() 86 if err != nil { 87 utils.Fatalf("Failed to generate random private key: %v", err) 88 } 89 } 90 91 // Create the keyfile object with a random UUID. 92 UUID, err := uuid.NewRandom() 93 if err != nil { 94 utils.Fatalf("Failed to generate random uuid: %v", err) 95 } 96 key := &keystore.Key{ 97 Id: UUID, 98 Address: crypto.PubkeyToAddress(privateKey.PublicKey), 99 PrivateKey: privateKey, 100 } 101 102 // Encrypt key with passphrase. 103 passphrase := getPassphrase(ctx, true) 104 scryptN, scryptP := keystore.StandardScryptN, keystore.StandardScryptP 105 if ctx.Bool(lightKDFFlag.Name) { 106 scryptN, scryptP = keystore.LightScryptN, keystore.LightScryptP 107 } 108 keyjson, err := keystore.EncryptKey(key, passphrase, scryptN, scryptP) 109 if err != nil { 110 utils.Fatalf("Error encrypting key: %v", err) 111 } 112 113 // Store the file to disk. 114 if err := os.MkdirAll(filepath.Dir(keyfilepath), 0700); err != nil { 115 utils.Fatalf("Could not create directory %s", filepath.Dir(keyfilepath)) 116 } 117 if err := os.WriteFile(keyfilepath, keyjson, 0600); err != nil { 118 utils.Fatalf("Failed to write keyfile to %s: %v", keyfilepath, err) 119 } 120 121 // Output some information. 122 out := outputGenerate{ 123 Address: key.Address.Hex(), 124 } 125 if ctx.Bool(jsonFlag.Name) { 126 mustPrintJSON(out) 127 } else { 128 fmt.Println("Address:", out.Address) 129 } 130 return nil 131 }, 132 }