From 0b1ed3936a71430f005290957f34bdff2aeb1f22 Mon Sep 17 00:00:00 2001 From: Aviv Eyal Date: Tue, 28 Nov 2017 12:28:40 +0200 Subject: [PATCH] Authenticate ping protocol messages --- examples/multipro/node.go | 39 +++++++++++++++++++++++++++++++++++---- examples/multipro/ping.go | 24 ++++++++++++++++++++++-- 2 files changed, 57 insertions(+), 6 deletions(-) diff --git a/examples/multipro/node.go b/examples/multipro/node.go index 7771e1a4..4a633817 100644 --- a/examples/multipro/node.go +++ b/examples/multipro/node.go @@ -4,15 +4,44 @@ import ( host "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" peer "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer" "github.com/gogo/protobuf/proto" + + p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" + "log" ) +func (n Node) authenticateMessage(message proto.Message, data *p2p.MessageData) bool { + + // store a temp ref to sig and remove it from data + sign := data.Sign + data.Sign = "" + + //log.Print("Signature: %s", []byte(sign)) + + // marshall data without the sig to binary format + bin, err := proto.Marshal(message) + if err != nil { + // todo: log + return false + } + + // restore sig in message data (for possible future use) + data.Sign = sign + + peerId, err := peer.IDB58Decode(data.NodeId) + + if err != nil { + log.Fatal(err, "Failed to decode node id") + return false + } + + return n.verifyData(bin, []byte(sign), peerId) +} + 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) } @@ -22,8 +51,10 @@ func (n Node) signData(data []byte) ([]byte, error) { return res, err } -func (n Node) verifyData(data []byte, signature []byte, signerHostId peer.ID) bool { - key := n.Peerstore().PubKey(signerHostId) +// precondition: we have info about the signer peer in the local peer store +func (n Node) verifyData(data []byte, signature []byte, peerId peer.ID) bool { + key := n.Peerstore().PubKey(peerId) + //log.Print ("%s %s %s", peerId, key, peerId.String()) res, err := key.Verify(data, signature) return res == true && err == nil } diff --git a/examples/multipro/ping.go b/examples/multipro/ping.go index 06d60d05..8e3bc7e7 100644 --- a/examples/multipro/ping.go +++ b/examples/multipro/ping.go @@ -12,6 +12,7 @@ import ( p2p "github.com/libp2p/go-libp2p/examples/multipro/pb" protobufCodec "github.com/multiformats/go-multicodec/protobuf" "gx/ipfs/QmRS46AyqtpJBsf1zmQdeizSDEzo1qkWR7rdEuPFAv8237/go-libp2p-host" + "gx/ipfs/QmXYjuNuxVzXKJCfWasQk1RqkhVLDM9jtUKhqc2WPQmFSB/go-libp2p-peer" ) // pattern: /protocol-name/request-or-response-message/version @@ -46,9 +47,19 @@ 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) + valid := p.node.authenticateMessage(data, data.MessageData) + + if !valid { + log.Fatal("Failed to authenticate message") + return + } else { + log.Print("Authenticated request content was generated by claimed node :-)") + } + // 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), + + resp := &p2p.PingResponse{MessageData: NewMessageData(peer.IDB58Encode(p.node.ID()), data.MessageData.Id, false), Message: fmt.Sprintf("Ping response from %s", p.node.ID())} // sign the data @@ -84,6 +95,15 @@ func (p PingProtocol) onPingResponse(s inet.Stream) { return } + valid := p.node.authenticateMessage(data, data.MessageData) + + if !valid { + log.Fatal("Failed to authenticate message") + return + } else { + log.Print("Authenticated response content generated by claimed node :-)") + } + // locate request data and remove it if found _, ok := p.requests[data.MessageData.Id] if ok { @@ -102,7 +122,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.ID().String(), uuid.New().String(), false), + req := &p2p.PingRequest{MessageData: NewMessageData(peer.IDB58Encode(p.node.ID()), uuid.New().String(), false), Message: fmt.Sprintf("Ping from %s", p.node.ID())} // sign the data