@cryptotaxi247 / kubo / commits / 48865db1e

change handshake to use pub/priv keys for verification

Jeromy committed Sep 1, 2014 at 19:04 UTC 48865db1eae429ea939a40523e979157c2163644
4 files changed +134 -2
identify/identify.go
+79 -2
@@ -3,6 +3,7 @@
3 package identify
4
5 import (
6 + "bytes"
7 "crypto"
8 "crypto/rand"
9 "crypto/rsa"
@@ -10,6 +11,7 @@ import (
11 "errors"
12 "io/ioutil"
13
14 + proto "code.google.com/p/goprotobuf/proto"
15 peer "github.com/jbenet/go-ipfs/peer"
16 u "github.com/jbenet/go-ipfs/util"
17 )
@@ -17,15 +19,90 @@ import (
19 // Perform initial communication with this peer to share node ID's and
20 // initiate communication
21 func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
20 - // TODO: make this more... secure.
21 - out <- self.ID
22 + encoded, err := buildHandshake(self)
23 + if err != nil {
24 + return err
25 + }
26 + out <- encoded
27 resp := <-in
28 +
29 + pbresp := new(Identify)
30 + err = proto.Unmarshal(resp, pbresp)
31 + if err != nil {
32 + return err
33 + }
34 +
35 + // Verify that the given ID matches their given public key
36 + if verifyErr := verifyID(peer.ID(pbresp.GetId()), pbresp.GetPubkey()); verifyErr != nil {
37 + return verifyErr
38 + }
39 +
40 + pubkey, err := x509.ParsePKIXPublicKey(pbresp.GetPubkey())
41 + if err != nil {
42 + return err
43 + }
44 +
45 + // Challenge peer to ensure they own the given pubkey
46 + secret := make([]byte, 32)
47 + rand.Read(secret)
48 + encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubkey.(*rsa.PublicKey), secret)
49 + if err != nil {
50 + //... this is odd
51 + return err
52 + }
53 +
54 + out <- encrypted
55 + challenge := <-in
56 +
57 + plain, err := rsa.DecryptPKCS1v15(rand.Reader, self.PrivKey.(*rsa.PrivateKey), challenge)
58 + if err != nil {
59 + return err
60 + }
61 +
62 + out <- plain
63 + chalResp := <-in
64 + if !bytes.Equal(chalResp, secret) {
65 + return errors.New("Recieved incorrect challenge response!")
66 + }
67 +
68 remote.ID = peer.ID(resp)
69 + remote.PubKey = pubkey
70 u.DOut("[%s] identify: Got node id: %s\n", self.ID.Pretty(), remote.ID.Pretty())
71
72 return nil
73 }
74
75 +func buildHandshake(self *peer.Peer) ([]byte, error) {
76 + pkb, err := x509.MarshalPKIXPublicKey(self.PubKey)
77 + if err != nil {
78 + return nil, err
79 + }
80 +
81 + pmes := new(Identify)
82 + pmes.Id = []byte(self.ID)
83 + pmes.Pubkey = pkb
84 +
85 + encoded, err := proto.Marshal(pmes)
86 + if err != nil {
87 + return nil, err
88 + }
89 +
90 + return encoded, nil
91 +}
92 +
93 +func verifyID(id peer.ID, pubkey []byte) error {
94 + hash, err := u.Hash(pubkey)
95 + if err != nil {
96 + return err
97 + }
98 +
99 + if id.Equal(peer.ID(hash)) {
100 + return nil
101 + }
102 +
103 + return errors.New("ID did not match public key!")
104 +}
105 +
106 type KeyPair struct {
107 Pub crypto.PublicKey
108 Priv crypto.PrivateKey
identify/message.pb.go new
+48
@@ -0,0 +1,48 @@
1 +// Code generated by protoc-gen-go.
2 +// source: message.proto
3 +// DO NOT EDIT!
4 +
5 +/*
6 +Package identify is a generated protocol buffer package.
7 +
8 +It is generated from these files:
9 + message.proto
10 +
11 +It has these top-level messages:
12 + Identify
13 +*/
14 +package identify
15 +
16 +import proto "code.google.com/p/goprotobuf/proto"
17 +import math "math"
18 +
19 +// Reference imports to suppress errors if they are not otherwise used.
20 +var _ = proto.Marshal
21 +var _ = math.Inf
22 +
23 +type Identify struct {
24 + Id []byte `protobuf:"bytes,1,req,name=id" json:"id,omitempty"`
25 + Pubkey []byte `protobuf:"bytes,2,req,name=pubkey" json:"pubkey,omitempty"`
26 + XXX_unrecognized []byte `json:"-"`
27 +}
28 +
29 +func (m *Identify) Reset() { *m = Identify{} }
30 +func (m *Identify) String() string { return proto.CompactTextString(m) }
31 +func (*Identify) ProtoMessage() {}
32 +
33 +func (m *Identify) GetId() []byte {
34 + if m != nil {
35 + return m.Id
36 + }
37 + return nil
38 +}
39 +
40 +func (m *Identify) GetPubkey() []byte {
41 + if m != nil {
42 + return m.Pubkey
43 + }
44 + return nil
45 +}
46 +
47 +func init() {
48 +}
identify/message.proto
+3
@@ -1,3 +1,6 @@
1 +package identify;
2 +
3 message Identify {
4 required bytes id = 1;
5 + required bytes pubkey = 2;
6 }
peer/peer.go
+4
@@ -1,6 +1,7 @@
1 package peer
2
3 import (
4 + "crypto"
5 "sync"
6 "time"
7
@@ -33,6 +34,9 @@ type Peer struct {
34 ID ID
35 Addresses []*ma.Multiaddr
36
37 + PubKey crypto.PublicKey
38 + PrivKey crypto.PrivateKey
39 +
40 latency time.Duration
41 latenLock sync.RWMutex
42 }