mirror of https://github.com/status-im/go-waku.git
feat: options to generate/specify/load node privatekey
This commit is contained in:
parent
f82732cd19
commit
de0b63f4a2
|
@ -1,4 +1,5 @@
|
||||||
*.db
|
*.db
|
||||||
|
nodekey
|
||||||
|
|
||||||
# Binaries for programs and plugins
|
# Binaries for programs and plugins
|
||||||
*.exe
|
*.exe
|
||||||
|
|
121
waku/node.go
121
waku/node.go
|
@ -2,11 +2,12 @@ package waku
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"crypto/rand"
|
"crypto/ecdsa"
|
||||||
"database/sql"
|
"database/sql"
|
||||||
"encoding/hex"
|
"encoding/hex"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
|
@ -19,7 +20,9 @@ import (
|
||||||
|
|
||||||
logging "github.com/ipfs/go-log"
|
logging "github.com/ipfs/go-log"
|
||||||
"github.com/libp2p/go-libp2p"
|
"github.com/libp2p/go-libp2p"
|
||||||
|
libp2pcrypto "github.com/libp2p/go-libp2p-core/crypto"
|
||||||
libp2pdisc "github.com/libp2p/go-libp2p-core/discovery"
|
libp2pdisc "github.com/libp2p/go-libp2p-core/discovery"
|
||||||
|
|
||||||
"github.com/libp2p/go-libp2p-core/protocol"
|
"github.com/libp2p/go-libp2p-core/protocol"
|
||||||
"github.com/libp2p/go-libp2p-peerstore/pstoreds"
|
"github.com/libp2p/go-libp2p-peerstore/pstoreds"
|
||||||
"github.com/multiformats/go-multiaddr"
|
"github.com/multiformats/go-multiaddr"
|
||||||
|
@ -40,14 +43,6 @@ import (
|
||||||
|
|
||||||
var log = logging.Logger("wakunode")
|
var log = logging.Logger("wakunode")
|
||||||
|
|
||||||
func randomHex(n int) (string, error) {
|
|
||||||
bytes := make([]byte, n)
|
|
||||||
if _, err := rand.Read(bytes); err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
return hex.EncodeToString(bytes), nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func failOnErr(err error, msg string) {
|
func failOnErr(err error, msg string) {
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if msg != "" {
|
if msg != "" {
|
||||||
|
@ -58,17 +53,19 @@ func failOnErr(err error, msg string) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func Execute(options Options) {
|
func Execute(options Options) {
|
||||||
|
if options.GenerateKey {
|
||||||
|
if err := writePrivateKeyToFile(options.KeyFile, options.Overwrite); err != nil {
|
||||||
|
failOnErr(err, "nodekey error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
hostAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprint("0.0.0.0:", options.Port))
|
hostAddr, _ := net.ResolveTCPAddr("tcp", fmt.Sprint("0.0.0.0:", options.Port))
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
if options.NodeKey == "" {
|
prvKey, err := getPrivKey(options)
|
||||||
options.NodeKey, err = randomHex(32)
|
failOnErr(err, "nodekey error")
|
||||||
failOnErr(err, "could not generate random key")
|
|
||||||
}
|
|
||||||
|
|
||||||
prvKey, err := crypto.HexToECDSA(options.NodeKey)
|
|
||||||
failOnErr(err, "error converting key into valid ecdsa key")
|
|
||||||
|
|
||||||
if options.DBPath == "" && options.UseDB {
|
if options.DBPath == "" && options.UseDB {
|
||||||
failOnErr(errors.New("dbpath can't be null"), "")
|
failOnErr(errors.New("dbpath can't be null"), "")
|
||||||
|
@ -245,3 +242,95 @@ func addPeers(wakuNode *node.WakuNode, addresses []string, protocol protocol.ID)
|
||||||
failOnErr(err, "error adding peer")
|
failOnErr(err, "error adding peer")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func loadPrivateKeyFromFile(path string) (*ecdsa.PrivateKey, error) {
|
||||||
|
src, err := ioutil.ReadFile(path)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
dst := make([]byte, hex.DecodedLen(len(src)))
|
||||||
|
_, err = hex.Decode(dst, src)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
p, err := libp2pcrypto.UnmarshalSecp256k1PrivateKey(dst)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
privKey := (*ecdsa.PrivateKey)(p.(*libp2pcrypto.Secp256k1PrivateKey))
|
||||||
|
privKey.Curve = crypto.S256()
|
||||||
|
|
||||||
|
return privKey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func writePrivateKeyToFile(path string, force bool) error {
|
||||||
|
_, err := os.Stat(path)
|
||||||
|
|
||||||
|
if err == nil && !force {
|
||||||
|
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
|
||||||
|
}
|
||||||
|
|
||||||
|
key, err := crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
privKey := libp2pcrypto.PrivKey((*libp2pcrypto.Secp256k1PrivateKey)(key))
|
||||||
|
|
||||||
|
b, err := privKey.Raw()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
output := make([]byte, hex.EncodedLen(len(b)))
|
||||||
|
hex.Encode(output, b)
|
||||||
|
|
||||||
|
return ioutil.WriteFile(path, output, 0600)
|
||||||
|
}
|
||||||
|
|
||||||
|
func getPrivKey(options Options) (*ecdsa.PrivateKey, error) {
|
||||||
|
var prvKey *ecdsa.PrivateKey
|
||||||
|
var err error
|
||||||
|
if options.KeyFile != "" {
|
||||||
|
prvKey, err = loadPrivateKeyFromFile(options.KeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read keyfile: %w", err)
|
||||||
|
}
|
||||||
|
} else if options.NodeKey != "" {
|
||||||
|
prvKey, err = crypto.HexToECDSA(options.NodeKey)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error converting key into valid ecdsa key: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
keyString := os.Getenv("GOWAKU-NODEKEY")
|
||||||
|
if keyString != "" {
|
||||||
|
prvKey, err = crypto.HexToECDSA(keyString)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error converting key into valid ecdsa key: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if _, err := os.Stat(options.KeyFile); err == nil {
|
||||||
|
prvKey, err = loadPrivateKeyFromFile(options.KeyFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("could not read keyfile: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if os.IsNotExist(err) {
|
||||||
|
prvKey, err = crypto.GenerateKey()
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("error generating key: %w", err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil, fmt.Errorf("could not read keyfile: %w", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return prvKey, nil
|
||||||
|
}
|
||||||
|
|
|
@ -47,7 +47,10 @@ type Options struct {
|
||||||
Port int `short:"p" long:"port" description:"Libp2p TCP listening port (0 for random)" default:"9000"`
|
Port int `short:"p" long:"port" description:"Libp2p TCP listening port (0 for random)" default:"9000"`
|
||||||
EnableWS bool `long:"ws" description:"Enable websockets support"`
|
EnableWS bool `long:"ws" description:"Enable websockets support"`
|
||||||
WSPort int `long:"ws-port" description:"Libp2p TCP listening port for websocket connection (0 for random)" default:"9001"`
|
WSPort int `long:"ws-port" description:"Libp2p TCP listening port for websocket connection (0 for random)" default:"9001"`
|
||||||
NodeKey string `long:"nodekey" description:"P2P node private key as hex (UNSAFE!, default random)"`
|
NodeKey string `long:"nodekey" description:"P2P node private key as hex. Can also be set with GOWAKU-NODEKEY env variable (default random)"`
|
||||||
|
KeyFile string `long:"key-file" description:"Path to a file containing the private key for the P2P node" default:"./nodekey"`
|
||||||
|
GenerateKey bool `long:"generate-key" description:"Generate private key file at path specified in --key-file"`
|
||||||
|
Overwrite bool `long:"overwrite" description:"When generating a keyfile, overwrite the nodekey file if it already exists"`
|
||||||
StaticNodes []string `long:"staticnodes" description:"Multiaddr of peer to directly connect with. Argument may be repeated"`
|
StaticNodes []string `long:"staticnodes" description:"Multiaddr of peer to directly connect with. Argument may be repeated"`
|
||||||
KeepAlive int `long:"keep-alive" default:"300" description:"Interval in seconds for pinging peers to keep the connection alive."`
|
KeepAlive int `long:"keep-alive" default:"300" description:"Interval in seconds for pinging peers to keep the connection alive."`
|
||||||
UseDB bool `long:"use-db" description:"Use SQLiteDB to persist information"`
|
UseDB bool `long:"use-db" description:"Use SQLiteDB to persist information"`
|
||||||
|
|
Loading…
Reference in New Issue