Commit 9f756444 authored by Aviv Eyal's avatar Aviv Eyal Committed by Steven Allen
Browse files

Refactoring

parent 7702e9b8
...@@ -57,7 +57,7 @@ func (e *EchoProtocol) onEchoRequest(s inet.Stream) { ...@@ -57,7 +57,7 @@ func (e *EchoProtocol) onEchoRequest(s inet.Stream) {
// send response to the request using the message string he provided // send response to the request using the message string he provided
resp := &p2p.EchoResponse{ resp := &p2p.EchoResponse{
MessageData: NewMessageData(e.node, data.MessageData.Id, false), MessageData: e.node.NewMessageData(data.MessageData.Id, false),
Message: data.Message} Message: data.Message}
// sign the data // sign the data
...@@ -121,7 +121,7 @@ func (e *EchoProtocol) Echo(host host.Host) bool { ...@@ -121,7 +121,7 @@ func (e *EchoProtocol) Echo(host host.Host) bool {
// create message data // create message data
req := &p2p.EchoRequest{ req := &p2p.EchoRequest{
MessageData: NewMessageData(e.node, uuid.New().String(), false), MessageData: e.node.NewMessageData(uuid.New().String(), false),
Message: fmt.Sprintf("Echo from %s", e.node.ID())} Message: fmt.Sprintf("Echo from %s", e.node.ID())}
signature, err := e.node.signProtoMessage(req) signature, err := e.node.signProtoMessage(req)
......
...@@ -5,9 +5,9 @@ import ( ...@@ -5,9 +5,9 @@ import (
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer" peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto" crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
"log" "log"
"time"
) )
// Node type - a p2p host implementing one or more p2p protocols // Node type - a p2p host implementing one or more p2p protocols
...@@ -18,7 +18,7 @@ type Node struct { ...@@ -18,7 +18,7 @@ type Node struct {
// add other protocols here... // add other protocols here...
} }
// create a new node with its implemented protocols // Create a new node with its implemented protocols
func NewNode(host host.Host, done chan bool) *Node { func NewNode(host host.Host, done chan bool) *Node {
node := &Node{Host: host} node := &Node{Host: host}
node.PingProtocol = NewPingProtocol(node, done) node.PingProtocol = NewPingProtocol(node, done)
...@@ -26,13 +26,16 @@ func NewNode(host host.Host, done chan bool) *Node { ...@@ -26,13 +26,16 @@ func NewNode(host host.Host, done chan bool) *Node {
return node return node
} }
// Authenticate incoming p2p message
// message: a protobufs go data object
// data: common p2p message data
func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData) bool { func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData) bool {
// store a temp ref to sig and remove it from data // store a temp ref to signature and remove it from message data
sign := data.Sign sign := data.Sign
data.Sign = "" data.Sign = ""
// marshall data without the sig to binary format // marshall data without the signature to protobufs3 binary format
bin, err := proto.Marshal(message) bin, err := proto.Marshal(message)
if err != nil { if err != nil {
log.Println(err, "failed to marshal pb message") log.Println(err, "failed to marshal pb message")
...@@ -42,15 +45,19 @@ func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData) ...@@ -42,15 +45,19 @@ func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData)
// restore sig in message data (for possible future use) // restore sig in message data (for possible future use)
data.Sign = sign data.Sign = sign
// restore peer id binary format from base58 encoded node id data
peerId, err := peer.IDB58Decode(data.NodeId) peerId, err := peer.IDB58Decode(data.NodeId)
if err != nil { if err != nil {
log.Println(err, "Failed to decode node id from base58") log.Println(err, "Failed to decode node id from base58")
return false return false
} }
// verify the data was authored by the signing peer identified by the public key
// and signature included in the message
return n.verifyData(bin, []byte(sign), peerId, data.NodePubKey) return n.verifyData(bin, []byte(sign), peerId, data.NodePubKey)
} }
// sign an outgoing p2p message payload
func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) { func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) {
data, err := proto.Marshal(message) data, err := proto.Marshal(message)
if err != nil { if err != nil {
...@@ -59,17 +66,20 @@ func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) { ...@@ -59,17 +66,20 @@ func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) {
return n.signData(data) return n.signData(data)
} }
// sign binary data using the local node's private key
func (n *Node) signData(data []byte) ([]byte, error) { func (n *Node) signData(data []byte) ([]byte, error) {
key := n.Peerstore().PrivKey(n.ID()) key := n.Peerstore().PrivKey(n.ID())
res, err := key.Sign(data) res, err := key.Sign(data)
return res, err return res, err
} }
// precondition: we have info about the signer peer in the local peer store // Verify incoming p2p message data integrity
// data: data to verify
// signature: author signature provided in the message payload
// peerId: author peer id from the message payload
// pubKeyData: author public key from the message payload
func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyData []byte) bool { func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyData []byte) bool {
key, err := crypto.UnmarshalPublicKey(pubKeyData) key, err := crypto.UnmarshalPublicKey(pubKeyData)
if err != nil { if err != nil {
log.Println(err, "Failed to extract key from message key data") log.Println(err, "Failed to extract key from message key data")
return false return false
...@@ -90,7 +100,6 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD ...@@ -90,7 +100,6 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD
} }
res, err := key.Verify(data, signature) res, err := key.Verify(data, signature)
if err != nil { if err != nil {
log.Println(err, "Error authenticating data") log.Println(err, "Error authenticating data")
return false return false
...@@ -98,3 +107,23 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD ...@@ -98,3 +107,23 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD
return res return res
} }
// helper method - generate message data shared between all node's p2p protocols
// messageId: unique for requests, copied from request for responses
func (n *Node) NewMessageData(messageId string, gossip bool) *p2p.MessageData {
// Add protobufs bin data for message author public key
// this is useful for authenticating messages forwarded by a node authored by another node
nodePubKey, err := n.Peerstore().PubKey(n.ID()).Bytes()
if err != nil {
panic("Failed to get public key for sender from local peer store.")
}
return &p2p.MessageData{ClientVersion: clientVersion,
NodeId: peer.IDB58Encode(n.ID()),
NodePubKey: nodePubKey,
Timestamp: time.Now().Unix(),
Id: messageId,
Gossip: gossip}
}
...@@ -56,7 +56,7 @@ func (p *PingProtocol) onPingRequest(s inet.Stream) { ...@@ -56,7 +56,7 @@ func (p *PingProtocol) onPingRequest(s inet.Stream) {
// generate response message // generate response message
log.Printf("%s: Sending ping response to %s. Message id: %s...", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.MessageData.Id) log.Printf("%s: Sending ping response to %s. Message id: %s...", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.MessageData.Id)
resp := &p2p.PingResponse{MessageData: NewMessageData(p.node, data.MessageData.Id, false), resp := &p2p.PingResponse{MessageData: p.node.NewMessageData(data.MessageData.Id, false),
Message: fmt.Sprintf("Ping response from %s", p.node.ID())} Message: fmt.Sprintf("Ping response from %s", p.node.ID())}
// sign the data // sign the data
...@@ -117,7 +117,7 @@ func (p *PingProtocol) Ping(host host.Host) bool { ...@@ -117,7 +117,7 @@ func (p *PingProtocol) Ping(host host.Host) bool {
log.Printf("%s: Sending ping to: %s....", p.node.ID(), host.ID()) log.Printf("%s: Sending ping to: %s....", p.node.ID(), host.ID())
// create message data // create message data
req := &p2p.PingRequest{MessageData: NewMessageData(p.node, uuid.New().String(), false), req := &p2p.PingRequest{MessageData: p.node.NewMessageData(uuid.New().String(), false),
Message: fmt.Sprintf("Ping from %s", p.node.ID())} Message: fmt.Sprintf("Ping from %s", p.node.ID())}
// sign the data // sign the data
......
...@@ -2,13 +2,10 @@ package main ...@@ -2,13 +2,10 @@ package main
import ( import (
"bufio" "bufio"
p2p "github.com/avive/go-libp2p/examples/multipro/pb"
"github.com/gogo/protobuf/proto" "github.com/gogo/protobuf/proto"
protobufCodec "github.com/multiformats/go-multicodec/protobuf" protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
inet "gx/ipfs/QmbD5yKbXahNvoMqzeuNyKQA9vAs9fUvJg2GXeWU1fVqY5/go-libp2p-net" inet "gx/ipfs/QmbD5yKbXahNvoMqzeuNyKQA9vAs9fUvJg2GXeWU1fVqY5/go-libp2p-net"
"log" "log"
"time"
) )
// node version // node version
...@@ -28,23 +25,3 @@ func sendProtoMessage(data proto.Message, s inet.Stream) bool { ...@@ -28,23 +25,3 @@ func sendProtoMessage(data proto.Message, s inet.Stream) bool {
writer.Flush() writer.Flush()
return true return true
} }
// helper method - generate message data shared between all node's p2p protocols
// messageId - unique for requests, copied from request for responses
func NewMessageData(node *Node, messageId string, gossip bool) *p2p.MessageData {
// Add protobufs bin data for message author public key
// this is useful for authenticating messages forwarded by a node authored by another node
nodePubKey, err := node.Peerstore().PubKey(node.ID()).Bytes()
if err != nil {
panic("Failed to get public key for sender from local peer store.")
}
return &p2p.MessageData{ClientVersion: clientVersion,
NodeId: peer.IDB58Encode(node.ID()),
NodePubKey: nodePubKey,
Timestamp: time.Now().Unix(),
Id: messageId,
Gossip: gossip}
}
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