Sign all messages

This commit is contained in:
Aviv Eyal 2017-11-28 11:21:39 +02:00 committed by Steven Allen
parent 0874c5036e
commit b3d54ab284
5 changed files with 74 additions and 19 deletions

View File

@ -12,6 +12,7 @@ import (
"github.com/ipfs/go-ipfs/thirdparty/assert" "github.com/ipfs/go-ipfs/thirdparty/assert"
p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" p2p "github.com/libp2p/go-libp2p/examples/multipro/pb"
protobufCodec "github.com/multiformats/go-multicodec/protobuf" protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
) )
// pattern: /protocol-name/request-or-response-message/version // pattern: /protocol-name/request-or-response-message/version
@ -51,13 +52,23 @@ func (e EchoProtocol) onEchoRequest(s inet.Stream) {
MessageData: NewMessageData(e.node.ID().String(), data.MessageData.Id, false), MessageData: NewMessageData(e.node.ID().String(), data.MessageData.Id, false),
Message: data.Message} Message: data.Message}
// sign the data
signature, err := e.node.signProtoMessage(resp)
if err != nil {
log.Fatal("failed to sign response")
return
}
// add the signature to the message
resp.MessageData.Sign = string(signature)
s, respErr := e.node.NewStream(context.Background(), s.Conn().RemotePeer(), echoResponse) s, respErr := e.node.NewStream(context.Background(), s.Conn().RemotePeer(), echoResponse)
if respErr != nil { if respErr != nil {
log.Fatal(respErr) log.Fatal(respErr)
return return
} }
ok := sendDataObject(resp, s) ok := sendProtoMessage(resp, s)
if ok { if ok {
log.Printf("%s: Echo response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String()) log.Printf("%s: Echo response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String())
@ -89,21 +100,30 @@ func (e EchoProtocol) onEchoResponse(s inet.Stream) {
e.done <- true e.done <- true
} }
func (e EchoProtocol) Echo(node *Node) bool { func (e EchoProtocol) Echo(host host.Host) bool {
log.Printf("%s: Sending echo to: %s....", e.node.ID(), node.ID()) log.Printf("%s: Sending echo to: %s....", e.node.ID(), host.ID())
// create message data // create message data
req := &p2p.EchoRequest{ req := &p2p.EchoRequest{
MessageData: NewMessageData(e.node.ID().String(), uuid.New().String(), false), MessageData: NewMessageData(e.node.ID().String(), uuid.New().String(), false),
Message: fmt.Sprintf("Echo from %s", e.node.ID())} Message: fmt.Sprintf("Echo from %s", e.node.ID())}
s, err := e.node.NewStream(context.Background(), node.ID(), echoRequest) signature, err := e.node.signProtoMessage(req)
if err != nil {
log.Fatal("failed to sign message")
return false
}
// add the signature to the message
req.MessageData.Sign = string(signature)
s, err := e.node.NewStream(context.Background(), host.ID(), echoRequest)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
return false return false
} }
ok := sendDataObject(req, s) ok := sendProtoMessage(req, s)
if !ok { if !ok {
return false return false
@ -111,6 +131,6 @@ func (e EchoProtocol) Echo(node *Node) bool {
// store request so response handler has access to it // store request so response handler has access to it
e.requests[req.MessageData.Id] = req e.requests[req.MessageData.Id] = req
log.Printf("%s: Echo to: %s was sent. Message Id: %s, Message: %s", e.node.ID(), node.ID(), req.MessageData.Id, req.Message) log.Printf("%s: Echo to: %s was sent. Message Id: %s, Message: %s", e.node.ID(), host.ID(), req.MessageData.Id, req.Message)
return true return true
} }

View File

@ -47,10 +47,10 @@ func main() {
log.Printf("This is a conversation between %s and %s\n", h1.ID(), h2.ID()) log.Printf("This is a conversation between %s and %s\n", h1.ID(), h2.ID())
// send messages using the protocols // send messages using the protocols
h1.Ping(h2) h1.Ping(h2.Host)
h2.Ping(h1) h2.Ping(h1.Host)
h1.Echo(h2) h1.Echo(h2.Host)
h2.Echo(h1) h2.Echo(h1.Host)
// block until all responses have been processed // block until all responses have been processed
for i := 0; i < 4; i++ { for i := 0; i < 4; i++ {

View File

@ -3,8 +3,19 @@ package main
import ( import (
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"
"github.com/gogo/protobuf/proto"
) )
func (n Node) signProtoMessage(message proto.Message) ([]byte, error) {
// sign the data
data, err := proto.Marshal(message)
if err != nil {
return nil, err
}
return n.signData(data)
}
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)
@ -17,11 +28,12 @@ func (n Node) verifyData(data []byte, signature []byte, signerHostId peer.ID) bo
return res == true && err == nil return res == true && err == nil
} }
// Node type - implements one or more p2p protocols // Node type - a host with one or more implemented p2p protocols
type Node struct { type Node struct {
host.Host // lib-p2p host host.Host // lib-p2p host
*PingProtocol // ping protocol impl *PingProtocol // ping protocol impl
*EchoProtocol // echo protocol impl *EchoProtocol // echo protocol impl
// add other protocols here...
} }
// create a new node with its implemented protocols // create a new node with its implemented protocols

View File

@ -11,6 +11,7 @@ import (
uuid "github.com/google/uuid" uuid "github.com/google/uuid"
p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" p2p "github.com/libp2p/go-libp2p/examples/multipro/pb"
protobufCodec "github.com/multiformats/go-multicodec/protobuf" protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
) )
// pattern: /protocol-name/request-or-response-message/version // pattern: /protocol-name/request-or-response-message/version
@ -45,18 +46,29 @@ func (p PingProtocol) onPingRequest(s inet.Stream) {
log.Printf("%s: Received ping request from %s. Message: %s", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.Message) log.Printf("%s: Received ping request from %s. Message: %s", s.Conn().LocalPeer(), s.Conn().RemotePeer(), data.Message)
// send response to sender // 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.ID().String(), data.MessageData.Id, false), resp := &p2p.PingResponse{MessageData: NewMessageData(p.node.ID().String(), 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
signature, err := p.node.signProtoMessage(resp)
if err != nil {
log.Fatal("failed to sign response")
return
}
// add the signature to the message
resp.MessageData.Sign = string(signature)
// send the response
s, respErr := p.node.NewStream(context.Background(), s.Conn().RemotePeer(), pingResponse) s, respErr := p.node.NewStream(context.Background(), s.Conn().RemotePeer(), pingResponse)
if respErr != nil { if respErr != nil {
log.Fatal(respErr) log.Fatal(respErr)
return return
} }
ok := sendDataObject(resp, s) ok := sendProtoMessage(resp, s)
if ok { if ok {
log.Printf("%s: Ping response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String()) log.Printf("%s: Ping response to %s sent.", s.Conn().LocalPeer().String(), s.Conn().RemotePeer().String())
@ -86,20 +98,30 @@ func (p PingProtocol) onPingResponse(s inet.Stream) {
p.done <- true p.done <- true
} }
func (p PingProtocol) Ping(node *Node) bool { func (p PingProtocol) Ping(host host.Host) bool {
log.Printf("%s: Sending ping to: %s....", p.node.ID(), node.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.ID().String(), uuid.New().String(), false), req := &p2p.PingRequest{MessageData: NewMessageData(p.node.ID().String(), uuid.New().String(), false),
Message: fmt.Sprintf("Ping from %s", p.node.ID())} Message: fmt.Sprintf("Ping from %s", p.node.ID())}
s, err := p.node.NewStream(context.Background(), node.Host.ID(), pingRequest) // sign the data
signature, err := p.node.signProtoMessage(req)
if err != nil {
log.Fatal("failed to sign pb data")
return false
}
// add the signature to the message
req.MessageData.Sign = string(signature)
s, err := p.node.NewStream(context.Background(), host.ID(), pingRequest)
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
return false return false
} }
ok := sendDataObject(req, s) ok := sendProtoMessage(req, s)
if !ok { if !ok {
return false return false
@ -107,6 +129,6 @@ func (p PingProtocol) Ping(node *Node) bool {
// store ref request so response handler has access to it // store ref request so response handler has access to it
p.requests[req.MessageData.Id] = req p.requests[req.MessageData.Id] = req
log.Printf("%s: Ping to: %s was sent. Message Id: %s, Message: %s", p.node.ID(), node.ID(), req.MessageData.Id, req.Message) log.Printf("%s: Ping to: %s was sent. Message Id: %s, Message: %s", p.node.ID(), host.ID(), req.MessageData.Id, req.Message)
return true return true
} }

View File

@ -9,6 +9,7 @@ import (
"time" "time"
//host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" //host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
//"bytes" //"bytes"
"github.com/gogo/protobuf/proto"
) )
// node version // node version
@ -17,7 +18,7 @@ const clientVersion = "go-p2p-node/0.0.1"
// helper method - writes a protobuf go data object to a network stream // helper method - writes a protobuf go data object to a network stream
// data - reference of protobuf go data object to send (not the object itself) // data - reference of protobuf go data object to send (not the object itself)
// s - network stream to write the data to // s - network stream to write the data to
func sendDataObject(data interface{}, s inet.Stream) bool { func sendProtoMessage(data proto.Message, s inet.Stream) bool {
writer := bufio.NewWriter(s) writer := bufio.NewWriter(s)
enc := protobufCodec.Multicodec(nil).Encoder(writer) enc := protobufCodec.Multicodec(nil).Encoder(writer)
err := enc.Encode(data) err := enc.Encode(data)