Node: Keygen changes (#3401)

This commit is contained in:
bruce-riley 2023-09-27 12:06:12 -05:00 committed by GitHub
parent 99d01324b8
commit 06d8f2d268
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 93 additions and 111 deletions

View File

@ -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)
}

View File

@ -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)
}
}

View File

@ -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))
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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
}