Refactoring

This commit is contained in:
Aviv Eyal 2017-11-29 12:56:44 +02:00 committed by Steven Allen
parent 7702e9b8be
commit 9f7564448d
4 changed files with 41 additions and 35 deletions

View File

@ -57,7 +57,7 @@ func (e *EchoProtocol) onEchoRequest(s inet.Stream) {
// send response to the request using the message string he provided
resp := &p2p.EchoResponse{
MessageData: NewMessageData(e.node, data.MessageData.Id, false),
MessageData: e.node.NewMessageData(data.MessageData.Id, false),
Message: data.Message}
// sign the data
@ -121,7 +121,7 @@ func (e *EchoProtocol) Echo(host host.Host) bool {
// create message data
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())}
signature, err := e.node.signProtoMessage(req)

View File

@ -5,9 +5,9 @@ import (
"github.com/gogo/protobuf/proto"
host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
crypto "gx/ipfs/QmaPbCnUMBohSGo3KnxEa2bHqyJVVeEEcwtqJAYxerieBo/go-libp2p-crypto"
"log"
"time"
)
// Node type - a p2p host implementing one or more p2p protocols
@ -18,7 +18,7 @@ type Node struct {
// 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 {
node := &Node{Host: host}
node.PingProtocol = NewPingProtocol(node, done)
@ -26,13 +26,16 @@ func NewNode(host host.Host, done chan bool) *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 {
// 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
data.Sign = ""
// marshall data without the sig to binary format
// marshall data without the signature to protobufs3 binary format
bin, err := proto.Marshal(message)
if err != nil {
log.Println(err, "failed to marshal pb message")
@ -42,15 +45,19 @@ func (n *Node) authenticateMessage(message proto.Message, data *p2p.MessageData)
// restore sig in message data (for possible future use)
data.Sign = sign
// restore peer id binary format from base58 encoded node id data
peerId, err := peer.IDB58Decode(data.NodeId)
if err != nil {
log.Println(err, "Failed to decode node id from base58")
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)
}
// sign an outgoing p2p message payload
func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) {
data, err := proto.Marshal(message)
if err != nil {
@ -59,17 +66,20 @@ func (n *Node) signProtoMessage(message proto.Message) ([]byte, error) {
return n.signData(data)
}
// sign binary data using the local node's private key
func (n *Node) signData(data []byte) ([]byte, error) {
key := n.Peerstore().PrivKey(n.ID())
res, err := key.Sign(data)
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 {
key, err := crypto.UnmarshalPublicKey(pubKeyData)
if err != nil {
log.Println(err, "Failed to extract key from message key data")
return false
@ -90,7 +100,6 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD
}
res, err := key.Verify(data, signature)
if err != nil {
log.Println(err, "Error authenticating data")
return false
@ -98,3 +107,23 @@ func (n *Node) verifyData(data []byte, signature []byte, peerId peer.ID, pubKeyD
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}
}

View File

@ -56,7 +56,7 @@ func (p *PingProtocol) onPingRequest(s inet.Stream) {
// generate response message
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())}
// sign the data
@ -117,7 +117,7 @@ func (p *PingProtocol) Ping(host host.Host) bool {
log.Printf("%s: Sending ping to: %s....", p.node.ID(), host.ID())
// 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())}
// sign the data

View File

@ -2,13 +2,10 @@ package main
import (
"bufio"
p2p "github.com/avive/go-libp2p/examples/multipro/pb"
"github.com/gogo/protobuf/proto"
protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer"
inet "gx/ipfs/QmbD5yKbXahNvoMqzeuNyKQA9vAs9fUvJg2GXeWU1fVqY5/go-libp2p-net"
"log"
"time"
)
// node version
@ -28,23 +25,3 @@ func sendProtoMessage(data proto.Message, s inet.Stream) bool {
writer.Flush()
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}
}