bridge: implement keygen command
Tested using `/guardiand keygen /bar --desc foobar`.
ghstack-source-id: 9f96ce7c0c
Pull Request resolved: https://github.com/certusone/wormhole/pull/91
This commit is contained in:
parent
d9f8174d76
commit
798ffec09c
|
@ -122,6 +122,17 @@ func rootLoggerName() string {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// lockMemory locks current and future pages in memory to protect secret keys from being swapped out to disk.
|
||||||
|
// It's possible (and strongly recommended) to deploy Wormhole such that keys are only ever
|
||||||
|
// stored in memory and never touch the disk. This is a privileged operation and requires CAP_IPC_LOCK.
|
||||||
|
func lockMemory() {
|
||||||
|
err := unix.Mlockall(syscall.MCL_CURRENT | syscall.MCL_FUTURE)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Failed to lock memory: %v (CAP_IPC_LOCK missing?)\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// BridgeCmd represents the bridge command
|
// BridgeCmd represents the bridge command
|
||||||
var BridgeCmd = &cobra.Command{
|
var BridgeCmd = &cobra.Command{
|
||||||
Use: "bridge",
|
Use: "bridge",
|
||||||
|
@ -134,14 +145,7 @@ func runBridge(cmd *cobra.Command, args []string) {
|
||||||
fmt.Print(devwarning)
|
fmt.Print(devwarning)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Lock current and future pages in memory to protect secret keys from being swapped out to disk.
|
lockMemory()
|
||||||
// It's possible (and strongly recommended) to deploy Wormhole such that keys are only ever
|
|
||||||
// stored in memory and never touch the disk. This is a privileged operation and requires CAP_IPC_LOCK.
|
|
||||||
err := unix.Mlockall(syscall.MCL_CURRENT | syscall.MCL_FUTURE)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Failed to lock memory: %v (CAP_IPC_LOCK missing?)\n", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set up logging. The go-log zap wrapper that libp2p uses is compatible with our
|
// Set up logging. The go-log zap wrapper that libp2p uses is compatible with our
|
||||||
// usage of zap in supervisor, which is nice.
|
// usage of zap in supervisor, which is nice.
|
||||||
|
|
|
@ -2,16 +2,50 @@ package guardiand
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"crypto/ecdsa"
|
"crypto/ecdsa"
|
||||||
|
"crypto/rand"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
"google.golang.org/protobuf/encoding/prototext"
|
"google.golang.org/protobuf/encoding/prototext"
|
||||||
|
|
||||||
"github.com/certusone/wormhole/bridge/pkg/devnet"
|
"github.com/certusone/wormhole/bridge/pkg/devnet"
|
||||||
nodev1 "github.com/certusone/wormhole/bridge/pkg/proto/node/v1"
|
nodev1 "github.com/certusone/wormhole/bridge/pkg/proto/node/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var keyDescription *string
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
keyDescription = KeygenCmd.Flags().String("desc", "", "Human-readable key description (optional)")
|
||||||
|
}
|
||||||
|
|
||||||
|
var KeygenCmd = &cobra.Command{
|
||||||
|
Use: "keygen",
|
||||||
|
Short: "Create guardian key at the specified path",
|
||||||
|
Run: runKeygen,
|
||||||
|
Args: cobra.ExactArgs(1),
|
||||||
|
}
|
||||||
|
|
||||||
|
func runKeygen(cmd *cobra.Command, args []string) {
|
||||||
|
lockMemory()
|
||||||
|
|
||||||
|
log.Print("Creating new key at ", args[0])
|
||||||
|
|
||||||
|
gk, err := ecdsa.GenerateKey(ethcrypto.S256(), rand.Reader)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to generate key: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = writeGuardianKey(gk, *keyDescription, args[0])
|
||||||
|
if err != nil {
|
||||||
|
log.Fatalf("failed to write key: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// loadGuardianKey loads a serialized guardian key from disk.
|
// loadGuardianKey loads a serialized guardian key from disk.
|
||||||
func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
||||||
b, err := ioutil.ReadFile(filename)
|
b, err := ioutil.ReadFile(filename)
|
||||||
|
@ -35,6 +69,10 @@ func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
||||||
|
|
||||||
// writeGuardianKey serializes a guardian key and writes it to disk.
|
// writeGuardianKey serializes a guardian key and writes it to disk.
|
||||||
func writeGuardianKey(key *ecdsa.PrivateKey, description string, filename string) error {
|
func writeGuardianKey(key *ecdsa.PrivateKey, description string, filename string) error {
|
||||||
|
if _, err := os.Stat(filename); !os.IsNotExist(err) {
|
||||||
|
return errors.New("refusing to override existing key")
|
||||||
|
}
|
||||||
|
|
||||||
m := &nodev1.GuardianKey{
|
m := &nodev1.GuardianKey{
|
||||||
Description: description,
|
Description: description,
|
||||||
Data: ethcrypto.FromECDSA(key),
|
Data: ethcrypto.FromECDSA(key),
|
||||||
|
|
|
@ -33,6 +33,7 @@ func init() {
|
||||||
|
|
||||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.guardiand.yaml)")
|
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.guardiand.yaml)")
|
||||||
rootCmd.AddCommand(guardiand.BridgeCmd)
|
rootCmd.AddCommand(guardiand.BridgeCmd)
|
||||||
|
rootCmd.AddCommand(guardiand.KeygenCmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
// initConfig reads in config file and ENV variables if set.
|
// initConfig reads in config file and ENV variables if set.
|
||||||
|
|
Loading…
Reference in New Issue