mirror of
https://github.com/ipfs/kubo.git
synced 2025-06-28 00:39:31 +08:00
change handshake to use pub/priv keys for verification
This commit is contained in:
@ -3,6 +3,7 @@
|
||||
package identify
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto"
|
||||
"crypto/rand"
|
||||
"crypto/rsa"
|
||||
@ -10,6 +11,7 @@ import (
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
|
||||
proto "code.google.com/p/goprotobuf/proto"
|
||||
peer "github.com/jbenet/go-ipfs/peer"
|
||||
u "github.com/jbenet/go-ipfs/util"
|
||||
)
|
||||
@ -17,15 +19,90 @@ import (
|
||||
// Perform initial communication with this peer to share node ID's and
|
||||
// initiate communication
|
||||
func Handshake(self, remote *peer.Peer, in, out chan []byte) error {
|
||||
// TODO: make this more... secure.
|
||||
out <- self.ID
|
||||
encoded, err := buildHandshake(self)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
out <- encoded
|
||||
resp := <-in
|
||||
|
||||
pbresp := new(Identify)
|
||||
err = proto.Unmarshal(resp, pbresp)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Verify that the given ID matches their given public key
|
||||
if verifyErr := verifyID(peer.ID(pbresp.GetId()), pbresp.GetPubkey()); verifyErr != nil {
|
||||
return verifyErr
|
||||
}
|
||||
|
||||
pubkey, err := x509.ParsePKIXPublicKey(pbresp.GetPubkey())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Challenge peer to ensure they own the given pubkey
|
||||
secret := make([]byte, 32)
|
||||
rand.Read(secret)
|
||||
encrypted, err := rsa.EncryptPKCS1v15(rand.Reader, pubkey.(*rsa.PublicKey), secret)
|
||||
if err != nil {
|
||||
//... this is odd
|
||||
return err
|
||||
}
|
||||
|
||||
out <- encrypted
|
||||
challenge := <-in
|
||||
|
||||
plain, err := rsa.DecryptPKCS1v15(rand.Reader, self.PrivKey.(*rsa.PrivateKey), challenge)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
out <- plain
|
||||
chalResp := <-in
|
||||
if !bytes.Equal(chalResp, secret) {
|
||||
return errors.New("Recieved incorrect challenge response!")
|
||||
}
|
||||
|
||||
remote.ID = peer.ID(resp)
|
||||
remote.PubKey = pubkey
|
||||
u.DOut("[%s] identify: Got node id: %s\n", self.ID.Pretty(), remote.ID.Pretty())
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func buildHandshake(self *peer.Peer) ([]byte, error) {
|
||||
pkb, err := x509.MarshalPKIXPublicKey(self.PubKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
pmes := new(Identify)
|
||||
pmes.Id = []byte(self.ID)
|
||||
pmes.Pubkey = pkb
|
||||
|
||||
encoded, err := proto.Marshal(pmes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return encoded, nil
|
||||
}
|
||||
|
||||
func verifyID(id peer.ID, pubkey []byte) error {
|
||||
hash, err := u.Hash(pubkey)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if id.Equal(peer.ID(hash)) {
|
||||
return nil
|
||||
}
|
||||
|
||||
return errors.New("ID did not match public key!")
|
||||
}
|
||||
|
||||
type KeyPair struct {
|
||||
Pub crypto.PublicKey
|
||||
Priv crypto.PrivateKey
|
||||
|
48
identify/message.pb.go
Normal file
48
identify/message.pb.go
Normal file
@ -0,0 +1,48 @@
|
||||
// Code generated by protoc-gen-go.
|
||||
// source: message.proto
|
||||
// DO NOT EDIT!
|
||||
|
||||
/*
|
||||
Package identify is a generated protocol buffer package.
|
||||
|
||||
It is generated from these files:
|
||||
message.proto
|
||||
|
||||
It has these top-level messages:
|
||||
Identify
|
||||
*/
|
||||
package identify
|
||||
|
||||
import proto "code.google.com/p/goprotobuf/proto"
|
||||
import math "math"
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = math.Inf
|
||||
|
||||
type Identify struct {
|
||||
Id []byte `protobuf:"bytes,1,req,name=id" json:"id,omitempty"`
|
||||
Pubkey []byte `protobuf:"bytes,2,req,name=pubkey" json:"pubkey,omitempty"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
}
|
||||
|
||||
func (m *Identify) Reset() { *m = Identify{} }
|
||||
func (m *Identify) String() string { return proto.CompactTextString(m) }
|
||||
func (*Identify) ProtoMessage() {}
|
||||
|
||||
func (m *Identify) GetId() []byte {
|
||||
if m != nil {
|
||||
return m.Id
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *Identify) GetPubkey() []byte {
|
||||
if m != nil {
|
||||
return m.Pubkey
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func init() {
|
||||
}
|
@ -1,3 +1,6 @@
|
||||
package identify;
|
||||
|
||||
message Identify {
|
||||
required bytes id = 1;
|
||||
required bytes pubkey = 2;
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
package peer
|
||||
|
||||
import (
|
||||
"crypto"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
@ -33,6 +34,9 @@ type Peer struct {
|
||||
ID ID
|
||||
Addresses []*ma.Multiaddr
|
||||
|
||||
PubKey crypto.PublicKey
|
||||
PrivKey crypto.PrivateKey
|
||||
|
||||
latency time.Duration
|
||||
latenLock sync.RWMutex
|
||||
}
|
||||
|
Reference in New Issue
Block a user