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"
p2p "github.com/libp2p/go-libp2p/examples/multipro/pb"
protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
)
// 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),
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)
if respErr != nil {
log.Fatal(respErr)
return
}
ok := sendDataObject(resp, s)
ok := sendProtoMessage(resp, s)
if ok {
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
}
func (e EchoProtocol) Echo(node *Node) bool {
log.Printf("%s: Sending echo to: %s....", e.node.ID(), node.ID())
func (e EchoProtocol) Echo(host host.Host) bool {
log.Printf("%s: Sending echo to: %s....", e.node.ID(), host.ID())
// create message data
req := &p2p.EchoRequest{
MessageData: NewMessageData(e.node.ID().String(), uuid.New().String(), false),
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 {
log.Fatal(err)
return false
}
ok := sendDataObject(req, s)
ok := sendProtoMessage(req, s)
if !ok {
return false
@ -111,6 +131,6 @@ func (e EchoProtocol) Echo(node *Node) bool {
// store request so response handler has access to it
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
}

View File

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

View File

@ -3,8 +3,19 @@ package main
import (
host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
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) {
key := n.Peerstore().PrivKey(n.ID())
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
}
// Node type - implements one or more p2p protocols
// Node type - a host with one or more implemented p2p protocols
type Node struct {
host.Host // lib-p2p host
*PingProtocol // ping protocol impl
*EchoProtocol // echo protocol impl
// add other protocols here...
}
// create a new node with its implemented protocols

View File

@ -11,6 +11,7 @@ import (
uuid "github.com/google/uuid"
p2p "github.com/libp2p/go-libp2p/examples/multipro/pb"
protobufCodec "github.com/multiformats/go-multicodec/protobuf"
"gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
)
// 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)
// 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)
resp := &p2p.PingResponse{MessageData: NewMessageData(p.node.ID().String(), data.MessageData.Id, false),
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)
if respErr != nil {
log.Fatal(respErr)
return
}
ok := sendDataObject(resp, s)
ok := sendProtoMessage(resp, s)
if ok {
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
}
func (p PingProtocol) Ping(node *Node) bool {
log.Printf("%s: Sending ping to: %s....", p.node.ID(), node.ID())
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.ID().String(), uuid.New().String(), false),
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 {
log.Fatal(err)
return false
}
ok := sendDataObject(req, s)
ok := sendProtoMessage(req, s)
if !ok {
return false
@ -107,6 +129,6 @@ func (p PingProtocol) Ping(node *Node) bool {
// store ref request so response handler has access to it
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
}

View File

@ -9,6 +9,7 @@ import (
"time"
//host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host"
//"bytes"
"github.com/gogo/protobuf/proto"
)
// 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
// data - reference of protobuf go data object to send (not the object itself)
// 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)
enc := protobufCodec.Multicodec(nil).Encoder(writer)
err := enc.Encode(data)