Commit 7daf11d2 authored by Janos Guljas's avatar Janos Guljas

add crypto package, handle overlay address and persist swarm private key

parent aab6a17c
......@@ -68,7 +68,7 @@ func (c *command) initStartCmd() (err error) {
return fmt.Errorf("unknown verbosity level %q", v)
}
var libp2pPrivateKey io.ReadWriteCloser
var libp2pPrivateKey, swarmPrivateKey io.ReadWriteCloser
if dataDir := c.config.GetString(optionNameDataDir); dataDir != "" {
if err := os.MkdirAll(dataDir, os.ModePerm); err != nil {
return err
......@@ -78,6 +78,11 @@ func (c *command) initStartCmd() (err error) {
return err
}
libp2pPrivateKey = libp2pKey
swarmKey, err := os.OpenFile(filepath.Join(dataDir, "swarm.key"), os.O_CREATE|os.O_RDWR, 0600)
if err != nil {
return err
}
swarmPrivateKey = swarmKey
}
debugAPIAddr := c.config.GetString(optionNameDebugAPIAddr)
......@@ -86,6 +91,7 @@ func (c *command) initStartCmd() (err error) {
}
b, err := node.NewBee(node.Options{
PrivateKey: swarmPrivateKey,
APIAddr: c.config.GetString(optionNameAPIAddr),
DebugAPIAddr: debugAPIAddr,
LibP2POptions: libp2p.Options{
......
......@@ -21,6 +21,7 @@ require (
github.com/sirupsen/logrus v1.4.2
github.com/spf13/cobra v0.0.5
github.com/spf13/viper v1.6.2
golang.org/x/crypto v0.0.0-20191219195013-becbf705a915
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
resenje.org/web v0.4.0
)
// Copyright 2020 The Swarm Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.
package crypto
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/rand"
"encoding/json"
"fmt"
"github.com/btcsuite/btcd/btcec"
"github.com/ethersphere/bee/pkg/swarm"
"golang.org/x/crypto/sha3"
)
var keyTypeSecp256k1 = "Secp256k1"
func GenerateSecp256k1Key() (*ecdsa.PrivateKey, error) {
return ecdsa.GenerateKey(btcec.S256(), rand.Reader)
}
type privateKey struct {
Type string `json:"type"`
Key []byte `json:"key"`
}
func MarshalSecp256k1PrivateKey(k *ecdsa.PrivateKey) ([]byte, error) {
return json.Marshal(privateKey{
Type: keyTypeSecp256k1,
Key: (*btcec.PrivateKey)(k).Serialize(),
})
}
func UnmarshalPrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
var pk privateKey
if err := json.Unmarshal(data, &pk); err != nil {
return nil, err
}
switch t := pk.Type; t {
case keyTypeSecp256k1:
return decodeSecp256k1PrivateKey(pk.Key)
default:
return nil, fmt.Errorf("unknown key type %q", t)
}
}
func decodeSecp256k1PrivateKey(data []byte) (*ecdsa.PrivateKey, error) {
if l := len(data); l != btcec.PrivKeyBytesLen {
return nil, fmt.Errorf("secp256k1 data size %d expected %d", l, btcec.PrivKeyBytesLen)
}
privk, _ := btcec.PrivKeyFromBytes(btcec.S256(), data)
return (*ecdsa.PrivateKey)(privk), nil
}
func NewAddress(p ecdsa.PublicKey) swarm.Address {
d := elliptic.Marshal(btcec.S256(), p.X, p.Y)
return swarm.NewAddress(keccak256(d))
}
func keccak256(data ...[]byte) []byte {
d := sha3.New256()
for _, b := range data {
_, err := d.Write(b)
if err != nil {
panic(err)
}
}
return d.Sum(nil)
}
......@@ -5,17 +5,22 @@
package node
import (
"bytes"
"context"
"crypto/ecdsa"
"fmt"
"io"
"io/ioutil"
"log"
"net"
"net/http"
"os"
"github.com/sirupsen/logrus"
"golang.org/x/sync/errgroup"
"github.com/ethersphere/bee/pkg/api"
"github.com/ethersphere/bee/pkg/crypto"
"github.com/ethersphere/bee/pkg/debugapi"
"github.com/ethersphere/bee/pkg/logging"
"github.com/ethersphere/bee/pkg/metrics"
......@@ -32,6 +37,7 @@ type Bee struct {
}
type Options struct {
PrivateKey io.ReadWriteCloser
APIAddr string
DebugAPIAddr string
LibP2POptions libp2p.Options
......@@ -48,8 +54,50 @@ func NewBee(o Options) (*Bee, error) {
errorLogWriter: logger.WriterLevel(logrus.ErrorLevel),
}
var privateKey *ecdsa.PrivateKey
if o.PrivateKey != nil {
privateKeyData, err := ioutil.ReadAll(o.PrivateKey)
if err != nil && !os.IsNotExist(err) {
return nil, fmt.Errorf("read private key: %w", err)
}
if len(privateKeyData) == 0 {
var err error
privateKey, err = crypto.GenerateSecp256k1Key()
if err != nil {
return nil, fmt.Errorf("generate secp256k1 key: %w", err)
}
d, err := crypto.MarshalSecp256k1PrivateKey(privateKey)
if err != nil {
return nil, fmt.Errorf("encode private key: %w", err)
}
if _, err := io.Copy(o.PrivateKey, bytes.NewReader(d)); err != nil {
return nil, fmt.Errorf("write private key: %w", err)
}
} else {
var err error
privateKey, err = crypto.UnmarshalPrivateKey(privateKeyData)
if err != nil {
return nil, fmt.Errorf("decode private key: %w", err)
}
}
if err := o.PrivateKey.Close(); err != nil {
return nil, fmt.Errorf("close private key: %w", err)
}
} else {
var err error
privateKey, err = crypto.GenerateSecp256k1Key()
if err != nil {
return nil, fmt.Errorf("generate secp256k1 key: %w", err)
}
}
address := crypto.NewAddress(privateKey.PublicKey)
logger.Infof("address: %s", address)
// Construct P2P service.
p2ps, err := libp2p.New(p2pCtx, o.LibP2POptions)
libP2POptions := o.LibP2POptions
libP2POptions.Overlay = address
p2ps, err := libp2p.New(p2pCtx, libP2POptions)
if err != nil {
return nil, fmt.Errorf("p2p service: %w", err)
}
......
......@@ -11,7 +11,6 @@ import (
"fmt"
"io"
"io/ioutil"
"math/rand"
"net"
"os"
"time"
......@@ -38,11 +37,6 @@ import (
var _ p2p.Service = (*Service)(nil)
func init() {
// Only temporary for fake overlay address generation.
rand.Seed(time.Now().UnixNano())
}
type Service struct {
host host.Host
metrics metrics
......@@ -54,6 +48,7 @@ type Service struct {
type Options struct {
PrivateKey io.ReadWriteCloser
Overlay swarm.Address
Addr string
DisableWS bool
DisableQUIC bool
......@@ -187,15 +182,11 @@ func New(ctx context.Context, o Options) (*Service, error) {
return nil, fmt.Errorf("autonat: %w", err)
}
// This is just a temporary way to generate an overlay address.
// TODO: proper key management and overlay address generation
overlay := make([]byte, 32)
rand.Read(overlay)
s := &Service{
host: h,
metrics: newMetrics(),
networkID: o.NetworkID,
handshakeService: handshake.New(swarm.NewAddress(overlay), o.NetworkID, o.Logger),
handshakeService: handshake.New(o.Overlay, o.NetworkID, o.Logger),
peers: newPeerRegistry(),
logger: o.Logger,
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment