From fff8132b13cf2205ffe598f9e23a54f4274f927d Mon Sep 17 00:00:00 2001 From: David Hill Date: Tue, 19 May 2020 08:24:02 -0500 Subject: [PATCH] Store signing key in db. (#34) --- config.go | 33 --------------------------------- database/database.go | 42 ++++++++++++++++++++++++++++++++++++++++++ main.go | 11 +++++++++-- 3 files changed, 51 insertions(+), 35 deletions(-) diff --git a/config.go b/config.go index 9dfa460..e663f50 100644 --- a/config.go +++ b/config.go @@ -1,9 +1,6 @@ package main import ( - "crypto/ed25519" - "crypto/rand" - "errors" "fmt" "io/ioutil" "net" @@ -41,8 +38,6 @@ type config struct { WalletPass string `long:"walletpass" ini-name:"walletpass" description:"Password for dcrwallet RPC connections."` WalletCert string `long:"walletcert" ini-name:"walletcert" description:"The dcrwallet RPC certificate file."` - signKey ed25519.PrivateKey - pubKey ed25519.PublicKey dbPath string netParams *netParams dcrwCert []byte @@ -283,33 +278,5 @@ func loadConfig() (*config, error) { // Set the database path cfg.dbPath = filepath.Join(dataDir, "vsp.db") - // Set pubKey/signKey. Read from seed file if it exists, otherwise generate - // one. - seedPath := filepath.Join(cfg.HomeDir, "sign.seed") - seed, err := ioutil.ReadFile(seedPath) - if err != nil { - if !os.IsNotExist(err) { - return nil, errors.New("seedPath does not exist") - } - - _, cfg.signKey, err = ed25519.GenerateKey(rand.Reader) - if err != nil { - return nil, fmt.Errorf("failed to generate signing key: %v", err) - } - err = ioutil.WriteFile(seedPath, cfg.signKey.Seed(), 0400) - if err != nil { - return nil, fmt.Errorf("failed to save signing key: %v", err) - } - } else { - cfg.signKey = ed25519.NewKeyFromSeed(seed) - } - - // Derive pubKey from signKey - pubKey, ok := cfg.signKey.Public().(ed25519.PublicKey) - if !ok { - return nil, fmt.Errorf("failed to cast signing key: %T", pubKey) - } - cfg.pubKey = pubKey - return &cfg, nil } diff --git a/database/database.go b/database/database.go index 80cd5b6..8e3869b 100644 --- a/database/database.go +++ b/database/database.go @@ -2,6 +2,8 @@ package database import ( "context" + "crypto/ed25519" + "crypto/rand" "encoding/binary" "fmt" "sync" @@ -25,6 +27,8 @@ var ( ticketBktK = []byte("ticketbkt") // version is the current database version. versionK = []byte("version") + // privateKeyK is the private key. + privateKeyK = []byte("privatekey") ) // Open initialises and returns an open database. If no database file is found @@ -72,6 +76,16 @@ func Open(ctx context.Context, shutdownWg *sync.WaitGroup, dbFile string) (*VspD return err } + // Generate ed25519 key + _, signKey, err := ed25519.GenerateKey(rand.Reader) + if err != nil { + return fmt.Errorf("failed to generate signing key: %v", err) + } + err = vspBkt.Put(privateKeyK, signKey.Seed()) + if err != nil { + return err + } + // Create ticket bucket. _, err = vspBkt.CreateBucket(ticketBktK) if err != nil { @@ -88,3 +102,31 @@ func Open(ctx context.Context, shutdownWg *sync.WaitGroup, dbFile string) (*VspD return &VspDatabase{db: db}, nil } + +func (vdb *VspDatabase) KeyPair() (ed25519.PrivateKey, ed25519.PublicKey, error) { + var seed []byte + err := vdb.db.View(func(tx *bolt.Tx) error { + vspBkt := tx.Bucket(vspBktK) + + seed = vspBkt.Get(privateKeyK) + if seed == nil { + // should not happen + return fmt.Errorf("no private key found") + } + + return nil + }) + if err != nil { + return nil, nil, err + } + + signKey := ed25519.NewKeyFromSeed(seed) + + // Derive pubKey from signKey + pubKey, ok := signKey.Public().(ed25519.PublicKey) + if !ok { + return nil, nil, fmt.Errorf("failed to cast signing key: %T", pubKey) + } + + return signKey, pubKey, err +} diff --git a/main.go b/main.go index 69c7004..4f6f9bc 100644 --- a/main.go +++ b/main.go @@ -61,10 +61,17 @@ func run(ctx context.Context) error { return err } + signKey, pubKey, err := db.KeyPair() + if err != nil { + log.Errorf("Failed to get keypair: %v", err) + requestShutdown() + shutdownWg.Wait() + return err + } // Create and start webapi server. apiCfg := webapi.Config{ - SignKey: cfg.signKey, - PubKey: cfg.pubKey, + SignKey: signKey, + PubKey: pubKey, VSPFee: cfg.VSPFee, NetParams: cfg.netParams.Params, }