From 45fc43c9cf72a17ccf01b4d82933520a748cf47e Mon Sep 17 00:00:00 2001 From: Jeromy <jeromyj@gmail.com> Date: Mon, 1 Sep 2014 16:09:03 -0700 Subject: [PATCH] add pub/priv key code to identify, not complete yet --- config/config.go | 11 +++++-- core/core.go | 70 +++++++++++++++++++++++++++--------------- identify/identify.go | 69 +++++++++++++++++++++++++++++++++++++++++ routing/dht/dht.go | 8 +++++ routing/dht/routing.go | 50 ++++++++++++++++++++++++++++++ 5 files changed, 181 insertions(+), 27 deletions(-) diff --git a/config/config.go b/config/config.go index a69166c31..2bbbae3d7 100644 --- a/config/config.go +++ b/config/config.go @@ -1,13 +1,15 @@ package config import ( - u "github.com/jbenet/go-ipfs/util" "os" + + u "github.com/jbenet/go-ipfs/util" ) // Identity tracks the configuration of the local node's identity. type Identity struct { - PeerID string + PeerID string + Address string } // Datastore tracks the configuration of the datastore. @@ -16,10 +18,15 @@ type Datastore struct { Path string } +type SavedPeer struct { + Address string +} + // Config is used to load IPFS config files. type Config struct { Identity *Identity Datastore *Datastore + Peers []*SavedPeer } var defaultConfigFilePath = "~/.go-ipfs/config" diff --git a/core/core.go b/core/core.go index 43bf632c4..2d7ba0efe 100644 --- a/core/core.go +++ b/core/core.go @@ -67,34 +67,10 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) { var swap *bitswap.BitSwap if online { - maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/4001") + swap, err = loadBitswap(cfg, d) if err != nil { return nil, err } - - local := &peer.Peer{ - ID: peer.ID(cfg.Identity.PeerID), - Addresses: []*ma.Multiaddr{maddr}, - } - - if len(local.ID) == 0 { - mh, err := u.Hash([]byte("blah blah blah ID")) - if err != nil { - return nil, err - } - local.ID = peer.ID(mh) - } - - net := swarm.NewSwarm(local) - err = net.Listen() - if err != nil { - return nil, err - } - - route := dht.NewDHT(local, net, d) - route.Start() - - swap = bitswap.NewBitSwap(local, net, d, route) } bs, err := bserv.NewBlockService(d, swap) @@ -115,3 +91,47 @@ func NewIpfsNode(cfg *config.Config, online bool) (*IpfsNode, error) { return n, nil } + +func loadBitswap(cfg *config.Config, d ds.Datastore) (*bitswap.BitSwap, error) { + maddr, err := ma.NewMultiaddr("/ip4/127.0.0.1/tcp/4001") + if err != nil { + return nil, err + } + + local := &peer.Peer{ + ID: peer.ID(cfg.Identity.PeerID), + Addresses: []*ma.Multiaddr{maddr}, + } + + if len(local.ID) == 0 { + mh, err := u.Hash([]byte("blah blah blah ID")) + if err != nil { + return nil, err + } + local.ID = peer.ID(mh) + } + + net := swarm.NewSwarm(local) + err = net.Listen() + if err != nil { + return nil, err + } + + route := dht.NewDHT(local, net, d) + route.Start() + + for _, p := range cfg.Peers { + maddr, err := ma.NewMultiaddr(p.Address) + if err != nil { + u.PErr("error: %v\n", err) + continue + } + + _, err = route.Connect(maddr) + if err != nil { + u.PErr("Bootstrapping error: %v\n", err) + } + } + + return bitswap.NewBitSwap(local, net, d, route), nil +} diff --git a/identify/identify.go b/identify/identify.go index ab0f56118..5bc664390 100644 --- a/identify/identify.go +++ b/identify/identify.go @@ -3,6 +3,13 @@ package identify import ( + "crypto" + "crypto/rand" + "crypto/rsa" + "crypto/x509" + "errors" + "io/ioutil" + peer "github.com/jbenet/go-ipfs/peer" u "github.com/jbenet/go-ipfs/util" ) @@ -18,3 +25,65 @@ func Handshake(self, remote *peer.Peer, in, out chan []byte) error { return nil } + +type KeyPair struct { + Pub crypto.PublicKey + Priv crypto.PrivateKey +} + +func GenKeypair() (*KeyPair, error) { + priv, err := rsa.GenerateKey(rand.Reader, 4096) + if err != nil { + return nil, err + } + + return &KeyPair{ + Priv: priv, + Pub: priv.PublicKey, + }, nil +} + +func LoadKeypair(dir string) (*KeyPair, error) { + var kp KeyPair + pk_b, err := ioutil.ReadFile(dir + "/priv.key") + if err != nil { + return nil, err + } + + priv, err := x509.ParsePKCS1PrivateKey(pk_b) + if err != nil { + return nil, err + } + + kp.Priv = priv + kp.Pub = priv.PublicKey + + return &kp, nil +} + +func (pk *KeyPair) ID() (peer.ID, error) { + pub_b, err := x509.MarshalPKIXPublicKey(pk.Pub) + if err != nil { + return nil, err + } + hash, err := u.Hash(pub_b) + if err != nil { + return nil, err + } + return peer.ID(hash), nil +} + +func (kp *KeyPair) Save(dir string) error { + switch k := kp.Priv.(type) { + case *rsa.PrivateKey: + err := k.Validate() + if err != nil { + return err + } + pk_b := x509.MarshalPKCS1PrivateKey(k) + err = ioutil.WriteFile(dir+"/priv.key", pk_b, 0600) + return err + default: + return errors.New("invalid private key type.") + } +} diff --git a/routing/dht/dht.go b/routing/dht/dht.go index b1a6e59c9..3be7a2cbb 100644 --- a/routing/dht/dht.go +++ b/routing/dht/dht.go @@ -2,6 +2,7 @@ package dht import ( "bytes" + "crypto/rand" "fmt" "sync" "time" @@ -637,3 +638,10 @@ func (dht *IpfsDHT) peerFromInfo(pbp *PBDHTMessage_PBPeer) (*peer.Peer, error) { return dht.network.GetConnection(peer.ID(pbp.GetId()), maddr) } + +// Builds up list of peers by requesting random peer IDs +func (dht *IpfsDHT) Bootstrap() { + id := make([]byte, 16) + rand.Read(id) + dht.FindPeer(peer.ID(id), time.Second*10) +} diff --git a/routing/dht/routing.go b/routing/dht/routing.go index 082f737f5..5ab1b65de 100644 --- a/routing/dht/routing.go +++ b/routing/dht/routing.go @@ -340,6 +340,56 @@ func (dht *IpfsDHT) FindPeer(id peer.ID, timeout time.Duration) (*peer.Peer, err return nil, u.ErrNotFound } +func (dht *IpfsDHT) findPeerMultiple(id peer.ID, timeout time.Duration) (*peer.Peer, error) { + // Check if were already connected to them + p, _ := dht.Find(id) + if p != nil { + return p, nil + } + + routeLevel := 0 + peers := dht.routingTables[routeLevel].NearestPeers(kb.ConvertPeerID(id), AlphaValue) + if len(peers) == 0 { + return nil, kb.ErrLookupFailure + } + + found := make(chan *peer.Peer) + after := time.After(timeout) + + for _, p := range peers { + go func(p *peer.Peer) { + pmes, err := dht.findPeerSingle(p, id, timeout, routeLevel) + if err != nil { + u.DErr("getPeer error: %v\n", err) + return + } + plist := pmes.GetPeers() + if len(plist) == 0 { + routeLevel++ + } + for _, fp := range plist { + nxtp, err := dht.peerFromInfo(fp) + if err != nil { + u.DErr("findPeer error: %v\n", err) + continue + } + + if nxtp.ID.Equal(dht.self.ID) { + found <- nxtp + return + } + } + }(p) + } + + select { + case p := <-found: + return p, nil + case <-after: + return nil, u.ErrTimeout + } +} + // Ping a peer, log the time it took func (dht *IpfsDHT) Ping(p *peer.Peer, timeout time.Duration) error { // Thoughts: maybe this should accept an ID and do a peer lookup? -- GitLab