Skip to content

Commit

Permalink
refactor: move --generate-key to a generate-key subcommand
Browse files Browse the repository at this point in the history
  • Loading branch information
richard-ramos committed Aug 9, 2023
1 parent 299801d commit dbc541c
Show file tree
Hide file tree
Showing 9 changed files with 136 additions and 76 deletions.
10 changes: 0 additions & 10 deletions cmd/waku/flags.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,6 @@ var (
Destination: &options.KeyPasswd,
EnvVars: []string{"WAKUNODE2_KEY_PASSWORD"},
})
GenerateKey = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "generate-key",
Usage: "Generate private key file at path specified in --key-file with the password defined by --key-password",
Destination: &options.GenerateKey,
})
Overwrite = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "overwrite",
Usage: "When generating a keyfile, overwrite the nodekey file if it already exists",
Destination: &options.Overwrite,
})
StaticNode = cliutils.NewGenericFlagMultiValue(&cli.GenericFlag{
Name: "staticnode",
Usage: "Multiaddr of peer to directly connect with. Option may be repeated",
Expand Down
80 changes: 80 additions & 0 deletions cmd/waku/keygen/command.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package keygen

import (
"encoding/json"
"fmt"
"os"

"github.com/ethereum/go-ethereum/accounts/keystore"
"github.com/ethereum/go-ethereum/crypto"
"github.com/urfave/cli/v2"
"github.com/waku-org/go-waku/waku/v2/utils"
"go.uber.org/zap"
)

// Command generates a key file used to generate the node's peerID, encrypted with an optional password
var Command = cli.Command{
Name: "generate-key",
Usage: "Generate private key file at path specified in --key-file with the password defined by --key-password",
Action: func(cCtx *cli.Context) error {
if err := generateKeyFile(Options.KeyFile, []byte(Options.KeyPasswd), Options.Overwrite); err != nil {
utils.Logger().Fatal("could not write keyfile", zap.Error(err))
}
return nil
},
Flags: []cli.Flag{
KeyFile,
KeyPassword,
Overwrite,
},
}

func checkForFileExistence(path string, overwrite bool) error {
_, err := os.Stat(path)

if err == nil && !overwrite {
return fmt.Errorf("%s already exists. Use --overwrite to overwrite the file", path)
}

if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return err
}

return nil
}

func generatePrivateKey() ([]byte, error) {
key, err := crypto.GenerateKey()
if err != nil {
return nil, err
}

return key.D.Bytes(), nil
}

func writeKeyFile(path string, key []byte, passwd []byte) error {
encryptedK, err := keystore.EncryptDataV3(key, passwd, keystore.StandardScryptN, keystore.StandardScryptP)
if err != nil {
return err
}

output, err := json.Marshal(encryptedK)
if err != nil {
return err
}

return os.WriteFile(path, output, 0600)
}

func generateKeyFile(path string, passwd []byte, overwrite bool) error {
if err := checkForFileExistence(path, overwrite); err != nil {
return err
}

key, err := generatePrivateKey()
if err != nil {
return err
}

return writeKeyFile(path, key, passwd)
}
34 changes: 34 additions & 0 deletions cmd/waku/keygen/flags.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
package keygen

import (
cli "github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
)

// Options contain the settings used for generating a key file
var Options GenerateKeyOptions

var (
// KeyFile is a flag that contains the path where the node key will be written
KeyFile = altsrc.NewPathFlag(&cli.PathFlag{
Name: "key-file",
Value: "./nodekey",
Usage: "Path to a file containing the private key for the P2P node",
Destination: &Options.KeyFile,
EnvVars: []string{"WAKUNODE2_KEY_FILE"},
})
// KeyPassword is a flag to set the password used to encrypt the file
KeyPassword = altsrc.NewStringFlag(&cli.StringFlag{
Name: "key-password",
Value: "secret",
Usage: "Password used for the private key file",
Destination: &Options.KeyPasswd,
EnvVars: []string{"WAKUNODE2_KEY_PASSWORD"},
})
// Overwrite is a flag used to overwrite an existing key file
Overwrite = altsrc.NewBoolFlag(&cli.BoolFlag{
Name: "overwrite",
Usage: "Overwrite the nodekey file if it already exists",
Destination: &Options.Overwrite,
})
)
9 changes: 9 additions & 0 deletions cmd/waku/keygen/options.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package keygen

// GenerateKeyOptions contains all the settings that can be used when generating
// a keyfile with the generate-key command
type GenerateKeyOptions struct {
KeyFile string
KeyPasswd string
Overwrite bool
}
8 changes: 5 additions & 3 deletions cmd/waku/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,11 @@ import (

cli "github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
"github.com/waku-org/go-waku/cmd/waku/keygen"
"github.com/waku-org/go-waku/waku/v2/node"
)

var options Options
var options NodeOptions

func main() {
// Defaults
Expand All @@ -31,8 +32,6 @@ func main() {
NodeKey,
KeyFile,
KeyPassword,
GenerateKey,
Overwrite,
StaticNode,
KeepAlive,
PersistPeers,
Expand Down Expand Up @@ -111,6 +110,9 @@ func main() {
Execute(options)
return nil
},
Commands: []*cli.Command{
&keygen.Command,
},
}

err := app.Run(os.Args)
Expand Down
61 changes: 4 additions & 57 deletions cmd/waku/node.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func failOnErr(err error, msg string) {
}
}

func requiresDB(options Options) bool {
func requiresDB(options NodeOptions) bool {
return options.Store.Enable || options.Rendezvous.Enable
}

Expand All @@ -83,14 +83,7 @@ func scalePerc(value float64) float64 {
const dialTimeout = 7 * time.Second

// Execute starts a go-waku node with settings determined by the Options parameter
func Execute(options Options) {
if options.GenerateKey {
if err := writePrivateKeyToFile(options.KeyFile, []byte(options.KeyPasswd), options.Overwrite); err != nil {
failOnErr(err, "nodekey error")
}
return
}

func Execute(options NodeOptions) {
hostAddr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("%s:%d", options.Address, options.Port))
failOnErr(err, "invalid host address")

Expand Down Expand Up @@ -528,53 +521,7 @@ func loadPrivateKeyFromFile(path string, passwd string) (*ecdsa.PrivateKey, erro
return crypto.ToECDSA(pKey)
}

func checkForFileExistence(path string, overwrite bool) error {
_, err := os.Stat(path)

if err == nil && !overwrite {
return fmt.Errorf("%s already exists. Use --overwrite to overwrite the file", path)
}

if err := os.Remove(path); err != nil && !os.IsNotExist(err) {
return err
}

return nil
}

func generatePrivateKey() ([]byte, error) {
key, err := crypto.GenerateKey()
if err != nil {
return nil, err
}

return key.D.Bytes(), nil
}

func writePrivateKeyToFile(path string, passwd []byte, overwrite bool) error {
if err := checkForFileExistence(path, overwrite); err != nil {
return err
}

key, err := generatePrivateKey()
if err != nil {
return err
}

encryptedK, err := keystore.EncryptDataV3(key, passwd, keystore.StandardScryptN, keystore.StandardScryptP)
if err != nil {
return err
}

output, err := json.Marshal(encryptedK)
if err != nil {
return err
}

return os.WriteFile(path, output, 0600)
}

func getPrivKey(options Options) (*ecdsa.PrivateKey, error) {
func getPrivKey(options NodeOptions) (*ecdsa.PrivateKey, error) {
var prvKey *ecdsa.PrivateKey
// get private key from nodeKey or keyFile
if options.NodeKey != nil {
Expand All @@ -597,7 +544,7 @@ func getPrivKey(options Options) (*ecdsa.PrivateKey, error) {
return prvKey, nil
}

func printListeningAddresses(ctx context.Context, nodeOpts []node.WakuNodeOption, options Options) {
func printListeningAddresses(ctx context.Context, nodeOpts []node.WakuNodeOption, options NodeOptions) {
params := new(node.WakuNodeParameters)
for _, opt := range nodeOpts {
err := opt(params)
Expand Down
2 changes: 1 addition & 1 deletion cmd/waku/node_no_rln.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,6 @@ import (
"go.uber.org/zap"
)

func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeOption) {
func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuNodeOption) {
// Do nothing
}
2 changes: 1 addition & 1 deletion cmd/waku/node_rln.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import (
"go.uber.org/zap"
)

func checkForRLN(logger *zap.Logger, options Options, nodeOpts *[]node.WakuNodeOption) {
func checkForRLN(logger *zap.Logger, options NodeOptions, nodeOpts *[]node.WakuNodeOption) {
if options.RLNRelay.Enable {
if !options.Relay.Enable {
failOnErr(errors.New("relay not available"), "Could not enable RLN Relay")
Expand Down
6 changes: 2 additions & 4 deletions cmd/waku/options.go
Original file line number Diff line number Diff line change
Expand Up @@ -142,17 +142,15 @@ type RendezvousOptions struct {
Nodes []multiaddr.Multiaddr
}

// Options contains all the available features and settings that can be
// NodeOptions contains all the available features and settings that can be
// configured via flags when executing go-waku as a service.
type Options struct {
type NodeOptions struct {
Port int
Address string
DNS4DomainName string
NodeKey *ecdsa.PrivateKey
KeyFile string
KeyPasswd string
GenerateKey bool
Overwrite bool
StaticNodes []multiaddr.Multiaddr
KeepAlive time.Duration
AdvertiseAddresses []multiaddr.Multiaddr
Expand Down

0 comments on commit dbc541c

Please sign in to comment.