// NodeKey retrieves the currently configured private key of the node, checking // first any manually set key, falling back to the one found in the configured // data folder. If no key can be found, a new one is generated. func (c *Config) NodeKey() *ecdsa.PrivateKey { // Use any specifically configured key if c.PrivateKey != nil { return c.PrivateKey } // Generate ephemeral key if no datadir is being used if c.DataDir == "" { key, err := crypto.GenerateKey() if err != nil { glog.Fatalf("Failed to generate ephemeral node key: %v", err) } return key } // Fall back to persistent key from the data directory keyfile := filepath.Join(c.DataDir, datadirPrivateKey) if key, err := crypto.LoadECDSA(keyfile); err == nil { return key } // No persistent key found, generate and store a new one key, err := crypto.GenerateKey() if err != nil { glog.Fatalf("Failed to generate node key: %v", err) } if err := crypto.SaveECDSA(keyfile, key); err != nil { glog.V(logger.Error).Infof("Failed to persist node key: %v", err) } return key }
// Tests that node keys can be correctly created, persisted, loaded and/or made // ephemeral. func TestNodeKeyPersistency(t *testing.T) { // Create a temporary folder and make sure no key is present dir, err := ioutil.TempDir("", "") if err != nil { t.Fatalf("failed to create temporary data directory: %v", err) } defer os.RemoveAll(dir) if _, err := os.Stat(filepath.Join(dir, datadirPrivateKey)); err == nil { t.Fatalf("non-created node key already exists") } // Configure a node with a preset key and ensure it's not persisted key, err := crypto.GenerateKey() if err != nil { t.Fatalf("failed to generate one-shot node key: %v", err) } if _, err := New(&Config{DataDir: dir, PrivateKey: key}); err != nil { t.Fatalf("failed to create empty stack: %v", err) } if _, err := os.Stat(filepath.Join(dir, datadirPrivateKey)); err == nil { t.Fatalf("one-shot node key persisted to data directory") } // Configure a node with no preset key and ensure it is persisted this time if _, err := New(&Config{DataDir: dir}); err != nil { t.Fatalf("failed to create newly keyed stack: %v", err) } if _, err := os.Stat(filepath.Join(dir, datadirPrivateKey)); err != nil { t.Fatalf("node key not persisted to data directory: %v", err) } key, err = crypto.LoadECDSA(filepath.Join(dir, datadirPrivateKey)) if err != nil { t.Fatalf("failed to load freshly persisted node key: %v", err) } blob1, err := ioutil.ReadFile(filepath.Join(dir, datadirPrivateKey)) if err != nil { t.Fatalf("failed to read freshly persisted node key: %v", err) } // Configure a new node and ensure the previously persisted key is loaded if _, err := New(&Config{DataDir: dir}); err != nil { t.Fatalf("failed to create previously keyed stack: %v", err) } blob2, err := ioutil.ReadFile(filepath.Join(dir, datadirPrivateKey)) if err != nil { t.Fatalf("failed to read previously persisted node key: %v", err) } if bytes.Compare(blob1, blob2) != 0 { t.Fatalf("persisted node key mismatch: have %x, want %x", blob2, blob1) } // Configure ephemeral node and ensure no key is dumped locally if _, err := New(&Config{DataDir: ""}); err != nil { t.Fatalf("failed to create ephemeral stack: %v", err) } if _, err := os.Stat(filepath.Join(".", datadirPrivateKey)); err == nil { t.Fatalf("ephemeral node key persisted to disk") } }
func (am *Manager) Import(path string, keyAuth string) (Account, error) { privateKeyECDSA, err := crypto.LoadECDSA(path) if err != nil { return Account{}, err } key := crypto.NewKeyFromECDSA(privateKeyECDSA) if err = am.keyStore.StoreKey(key, keyAuth); err != nil { return Account{}, err } return Account{Address: key.Address}, nil }
func main() { var ( listenAddr = flag.String("addr", ":30301", "listen address") genKey = flag.String("genkey", "", "generate a node key and quit") nodeKeyFile = flag.String("nodekey", "", "private key filename") nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)") natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)") nodeKey *ecdsa.PrivateKey err error ) flag.Var(glog.GetVerbosity(), "verbosity", "log verbosity (0-9)") flag.Var(glog.GetVModule(), "vmodule", "log verbosity pattern") glog.SetToStderr(true) flag.Parse() if *genKey != "" { key, err := crypto.GenerateKey() if err != nil { utils.Fatalf("could not generate key: %v", err) } if err := crypto.SaveECDSA(*genKey, key); err != nil { utils.Fatalf("%v", err) } os.Exit(0) } natm, err := nat.Parse(*natdesc) if err != nil { utils.Fatalf("-nat: %v", err) } switch { case *nodeKeyFile == "" && *nodeKeyHex == "": utils.Fatalf("Use -nodekey or -nodekeyhex to specify a private key") case *nodeKeyFile != "" && *nodeKeyHex != "": utils.Fatalf("Options -nodekey and -nodekeyhex are mutually exclusive") case *nodeKeyFile != "": if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil { utils.Fatalf("-nodekey: %v", err) } case *nodeKeyHex != "": if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil { utils.Fatalf("-nodekeyhex: %v", err) } } if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm, ""); err != nil { utils.Fatalf("%v", err) } select {} }
func GetNodeKey(ctx *cli.Context) (key *ecdsa.PrivateKey) { hex, file := ctx.GlobalString(NodeKeyHexFlag.Name), ctx.GlobalString(NodeKeyFileFlag.Name) var err error switch { case file != "" && hex != "": Fatalf("Options %q and %q are mutually exclusive", NodeKeyFileFlag.Name, NodeKeyHexFlag.Name) case file != "": if key, err = crypto.LoadECDSA(file); err != nil { Fatalf("Option %q: %v", NodeKeyFileFlag.Name, err) } case hex != "": if key, err = crypto.HexToECDSA(hex); err != nil { Fatalf("Option %q: %v", NodeKeyHexFlag.Name, err) } } return key }
func accountImport(ctx *cli.Context) { keyfile := ctx.Args().First() if len(keyfile) == 0 { utils.Fatalf("keyfile must be given as argument") } key, err := crypto.LoadECDSA(keyfile) if err != nil { utils.Fatalf("keyfile must be given as argument") } accman := utils.MakeAccountManager(ctx) passphrase := getPassPhrase("Your new account is locked with a password. Please give a password. Do not forget this password.", true, 0, utils.MakePasswordList(ctx)) acct, err := accman.ImportECDSA(key, passphrase) if err != nil { utils.Fatalf("Could not create the account: %v", err) } fmt.Printf("Address: {%x}\n", acct.Address) }
func main() { var ( listenAddr = flag.String("addr", ":30301", "listen address") genKey = flag.String("genkey", "", "generate a node key and quit") nodeKeyFile = flag.String("nodekey", "", "private key filename") nodeKeyHex = flag.String("nodekeyhex", "", "private key as hex (for testing)") natdesc = flag.String("nat", "none", "port mapping mechanism (any|none|upnp|pmp|extip:<IP>)") nodeKey *ecdsa.PrivateKey err error ) flag.Parse() logger.AddLogSystem(logger.NewStdLogSystem(os.Stdout, log.LstdFlags, logger.DebugLevel)) if *genKey != "" { writeKey(*genKey) os.Exit(0) } natm, err := nat.Parse(*natdesc) if err != nil { log.Fatalf("-nat: %v", err) } switch { case *nodeKeyFile == "" && *nodeKeyHex == "": log.Fatal("Use -nodekey or -nodekeyhex to specify a private key") case *nodeKeyFile != "" && *nodeKeyHex != "": log.Fatal("Options -nodekey and -nodekeyhex are mutually exclusive") case *nodeKeyFile != "": if nodeKey, err = crypto.LoadECDSA(*nodeKeyFile); err != nil { log.Fatalf("-nodekey: %v", err) } case *nodeKeyHex != "": if nodeKey, err = crypto.HexToECDSA(*nodeKeyHex); err != nil { log.Fatalf("-nodekeyhex: %v", err) } } if _, err := discover.ListenUDP(nodeKey, *listenAddr, natm, ""); err != nil { log.Fatal(err) } select {} }
func (cfg *Config) nodeKey() (*ecdsa.PrivateKey, error) { // use explicit key from command line args if set if cfg.NodeKey != nil { return cfg.NodeKey, nil } // use persistent key if present keyfile := filepath.Join(cfg.DataDir, "nodekey") key, err := crypto.LoadECDSA(keyfile) if err == nil { return key, nil } // no persistent key, generate and store a new one if key, err = crypto.GenerateKey(); err != nil { return nil, fmt.Errorf("could not generate server key: %v", err) } if err := crypto.SaveECDSA(keyfile, key); err != nil { glog.V(logger.Error).Infoln("could not persist nodekey: ", err) } return key, nil }