Sign all messages
This commit is contained in:
parent
0874c5036e
commit
b3d54ab284
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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++ {
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue