Node: Keygen changes (#3401)
This commit is contained in:
parent
99d01324b8
commit
06d8f2d268
|
@ -21,6 +21,7 @@ import (
|
|||
"github.com/spf13/pflag"
|
||||
"golang.org/x/crypto/sha3"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
gossipv1 "github.com/certusone/wormhole/node/pkg/proto/gossip/v1"
|
||||
publicrpcv1 "github.com/certusone/wormhole/node/pkg/proto/publicrpc/v1"
|
||||
"github.com/wormhole-foundation/wormhole/sdk"
|
||||
|
@ -39,6 +40,7 @@ import (
|
|||
var (
|
||||
clientSocketPath *string
|
||||
shouldBackfill *bool
|
||||
unsafeDevnetMode *bool
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -68,6 +70,10 @@ func init() {
|
|||
SignExistingVaaCmd.Flags().AddFlagSet(pf)
|
||||
SignExistingVaasFromCSVCmd.Flags().AddFlagSet(pf)
|
||||
|
||||
adminClientSignWormchainAddressFlags := pflag.NewFlagSet("adminClientSignWormchainAddressFlags", pflag.ContinueOnError)
|
||||
unsafeDevnetMode = adminClientSignWormchainAddressFlags.Bool("unsafeDevMode", false, "Run in unsafe devnet mode")
|
||||
AdminClientSignWormchainAddress.Flags().AddFlagSet(adminClientSignWormchainAddressFlags)
|
||||
|
||||
AdminCmd.AddCommand(AdminClientInjectGuardianSetUpdateCmd)
|
||||
AdminCmd.AddCommand(AdminClientFindMissingMessagesCmd)
|
||||
AdminCmd.AddCommand(AdminClientGovernanceVAAVerifyCmd)
|
||||
|
@ -225,7 +231,7 @@ func runSignWormchainValidatorAddress(cmd *cobra.Command, args []string) error {
|
|||
if !strings.HasPrefix(wormchainAddress, "wormhole") || strings.HasPrefix(wormchainAddress, "wormholeval") {
|
||||
return fmt.Errorf("must provide a bech32 address that has 'wormhole' prefix")
|
||||
}
|
||||
gk, err := loadGuardianKey(guardianKeyPath)
|
||||
gk, err := common.LoadGuardianKey(guardianKeyPath, *unsafeDevnetMode)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to load guardian key: %w", err)
|
||||
}
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
package guardiand
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"log"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
var keyDescription *string
|
||||
var blockType *string
|
||||
|
||||
func init() {
|
||||
keyDescription = KeygenCmd.Flags().String("desc", "", "Human-readable key description (optional)")
|
||||
blockType = KeygenCmd.Flags().String("block-type", common.GuardianKeyArmoredBlock, "block type of armored file (optional)")
|
||||
}
|
||||
|
||||
var KeygenCmd = &cobra.Command{
|
||||
Use: "keygen [KEYFILE]",
|
||||
Short: "Create guardian key at the specified path",
|
||||
Run: runKeygen,
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
func runKeygen(cmd *cobra.Command, args []string) {
|
||||
common.LockMemory()
|
||||
common.SetRestrictiveUmask()
|
||||
|
||||
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 = common.WriteArmoredKey(gk, *keyDescription, args[0], *blockType, false)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to write key: %v", err)
|
||||
}
|
||||
}
|
|
@ -781,15 +781,10 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
|
||||
// In devnet mode, we generate a deterministic guardian key and write it to disk.
|
||||
if *unsafeDevMode {
|
||||
gk, err := generateDevnetGuardianKey()
|
||||
err := devnet.GenerateAndStoreDevnetGuardianKey(*guardianKeyPath)
|
||||
if err != nil {
|
||||
logger.Fatal("failed to generate devnet guardian key", zap.Error(err))
|
||||
}
|
||||
|
||||
err = writeGuardianKey(gk, "auto-generated deterministic devnet key", *guardianKeyPath, true)
|
||||
if err != nil {
|
||||
logger.Fatal("failed to write devnet guardian key", zap.Error(err))
|
||||
}
|
||||
}
|
||||
|
||||
// Database
|
||||
|
@ -797,7 +792,7 @@ func runNode(cmd *cobra.Command, args []string) {
|
|||
defer db.Close()
|
||||
|
||||
// Guardian key
|
||||
gk, err := loadGuardianKey(*guardianKeyPath)
|
||||
gk, err := common.LoadGuardianKey(*guardianKeyPath, *unsafeDevMode)
|
||||
if err != nil {
|
||||
logger.Fatal("failed to load guardian key", zap.Error(err))
|
||||
}
|
||||
|
|
|
@ -7,24 +7,15 @@ import (
|
|||
"context"
|
||||
"crypto/ecdsa"
|
||||
"encoding/hex"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/accountant"
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
|
||||
"github.com/certusone/wormhole/node/pkg/wormconn"
|
||||
"github.com/wormhole-foundation/wormhole/sdk/vaa"
|
||||
|
||||
sdktx "github.com/cosmos/cosmos-sdk/types/tx"
|
||||
|
||||
ethCrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
|
||||
"golang.org/x/crypto/openpgp/armor" //nolint
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"go.uber.org/zap"
|
||||
)
|
||||
|
||||
|
@ -54,7 +45,7 @@ func main() {
|
|||
)
|
||||
|
||||
logger.Info("Loading guardian key", zap.String("guardianKeyPath", guardianKeyPath))
|
||||
gk, err := loadGuardianKey(guardianKeyPath)
|
||||
gk, err := common.LoadGuardianKey(guardianKeyPath, true)
|
||||
if err != nil {
|
||||
logger.Fatal("failed to load guardian key", zap.Error(err))
|
||||
}
|
||||
|
@ -448,42 +439,3 @@ func submit(
|
|||
|
||||
return accountant.SubmitObservationsToContract(ctx, logger, gk, gsIndex, guardianIndex, wormchainConn, contract, msgs)
|
||||
}
|
||||
|
||||
const (
|
||||
GuardianKeyArmoredBlock = "WORMHOLE GUARDIAN PRIVATE KEY"
|
||||
)
|
||||
|
||||
// loadGuardianKey loads a serialized guardian key from disk.
|
||||
func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %w", err)
|
||||
}
|
||||
|
||||
p, err := armor.Decode(f)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read armored file: %w", err)
|
||||
}
|
||||
|
||||
if p.Type != GuardianKeyArmoredBlock {
|
||||
return nil, fmt.Errorf("invalid block type: %s", p.Type)
|
||||
}
|
||||
|
||||
b, err := io.ReadAll(p.Body)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to read file: %w", err)
|
||||
}
|
||||
|
||||
var m nodev1.GuardianKey
|
||||
err = proto.Unmarshal(b, &m)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to deserialize protobuf: %w", err)
|
||||
}
|
||||
|
||||
gk, err := ethCrypto.ToECDSA(m.Data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to deserialize raw key data: %w", err)
|
||||
}
|
||||
|
||||
return gk, nil
|
||||
}
|
||||
|
|
|
@ -1,61 +1,30 @@
|
|||
package guardiand
|
||||
package common
|
||||
|
||||
import (
|
||||
"crypto/ecdsa"
|
||||
"crypto/rand"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
"github.com/spf13/cobra"
|
||||
"golang.org/x/crypto/openpgp/armor" //nolint
|
||||
"google.golang.org/protobuf/proto"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/devnet"
|
||||
nodev1 "github.com/certusone/wormhole/node/pkg/proto/node/v1"
|
||||
)
|
||||
|
||||
var keyDescription *string
|
||||
|
||||
const (
|
||||
GuardianKeyArmoredBlock = "WORMHOLE GUARDIAN PRIVATE KEY"
|
||||
)
|
||||
|
||||
func init() {
|
||||
keyDescription = KeygenCmd.Flags().String("desc", "", "Human-readable key description (optional)")
|
||||
// LoadGuardianKey loads a serialized guardian key from disk.
|
||||
func LoadGuardianKey(filename string, unsafeDevMode bool) (*ecdsa.PrivateKey, error) {
|
||||
return LoadArmoredKey(filename, GuardianKeyArmoredBlock, unsafeDevMode)
|
||||
}
|
||||
|
||||
var KeygenCmd = &cobra.Command{
|
||||
Use: "keygen [KEYFILE]",
|
||||
Short: "Create guardian key at the specified path",
|
||||
Run: runKeygen,
|
||||
Args: cobra.ExactArgs(1),
|
||||
}
|
||||
|
||||
func runKeygen(cmd *cobra.Command, args []string) {
|
||||
common.LockMemory()
|
||||
common.SetRestrictiveUmask()
|
||||
|
||||
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], false)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to write key: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
// loadGuardianKey loads a serialized guardian key from disk.
|
||||
func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
||||
// LoadArmoredKey loads a serialized key from disk.
|
||||
func LoadArmoredKey(filename string, blockType string, unsafeDevMode bool) (*ecdsa.PrivateKey, error) {
|
||||
f, err := os.Open(filename)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to open file: %w", err)
|
||||
|
@ -66,7 +35,7 @@ func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
|||
return nil, fmt.Errorf("failed to read armored file: %w", err)
|
||||
}
|
||||
|
||||
if p.Type != GuardianKeyArmoredBlock {
|
||||
if p.Type != blockType {
|
||||
return nil, fmt.Errorf("invalid block type: %s", p.Type)
|
||||
}
|
||||
|
||||
|
@ -81,7 +50,7 @@ func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
|||
return nil, fmt.Errorf("failed to deserialize protobuf: %w", err)
|
||||
}
|
||||
|
||||
if !*unsafeDevMode && m.UnsafeDeterministicKey {
|
||||
if !unsafeDevMode && m.UnsafeDeterministicKey {
|
||||
return nil, errors.New("refusing to use deterministic key in production")
|
||||
}
|
||||
|
||||
|
@ -93,8 +62,8 @@ func loadGuardianKey(filename string) (*ecdsa.PrivateKey, error) {
|
|||
return gk, nil
|
||||
}
|
||||
|
||||
// writeGuardianKey serializes a guardian key and writes it to disk.
|
||||
func writeGuardianKey(key *ecdsa.PrivateKey, description string, filename string, unsafe bool) error {
|
||||
// WriteArmoredKey serializes a key and writes it to disk.
|
||||
func WriteArmoredKey(key *ecdsa.PrivateKey, description string, filename string, blockType string, unsafe bool) error {
|
||||
if _, err := os.Stat(filename); !os.IsNotExist(err) {
|
||||
return errors.New("refusing to override existing key")
|
||||
}
|
||||
|
@ -122,7 +91,7 @@ func writeGuardianKey(key *ecdsa.PrivateKey, description string, filename string
|
|||
if description != "" {
|
||||
headers["Description"] = description
|
||||
}
|
||||
a, err := armor.Encode(f, GuardianKeyArmoredBlock, headers)
|
||||
a, err := armor.Encode(f, blockType, headers)
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
@ -136,15 +105,3 @@ func writeGuardianKey(key *ecdsa.PrivateKey, description string, filename string
|
|||
}
|
||||
return f.Close()
|
||||
}
|
||||
|
||||
// generateDevnetGuardianKey returns a deterministic testnet key.
|
||||
func generateDevnetGuardianKey() (*ecdsa.PrivateKey, error) {
|
||||
// Figure out our devnet index
|
||||
idx, err := devnet.GetDevnetIndex()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Generate guardian key
|
||||
return devnet.InsecureDeterministicEcdsaKeyByIndex(ethcrypto.S256(), uint64(idx)), nil
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package devnet
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"github.com/certusone/wormhole/node/pkg/common"
|
||||
|
||||
ethcrypto "github.com/ethereum/go-ethereum/crypto"
|
||||
)
|
||||
|
||||
// GenerateAndStoreDevnetGuardianKey returns a deterministic testnet key.
|
||||
func GenerateAndStoreDevnetGuardianKey(filename string) error {
|
||||
// Figure out our devnet index
|
||||
idx, err := GetDevnetIndex()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Generate the guardian key.
|
||||
gk := InsecureDeterministicEcdsaKeyByIndex(ethcrypto.S256(), uint64(idx))
|
||||
|
||||
// Store it to disk.
|
||||
if err := common.WriteArmoredKey(gk, "auto-generated deterministic devnet key", filename, common.GuardianKeyArmoredBlock, true); err != nil {
|
||||
return fmt.Errorf("failed to store generated guardian key: %w", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue