github.com/sykesm/fabric@v1.1.0-preview.0.20200129034918-2aa12b1a0181/gossip/protoext/signing_test.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package protoext_test
     8  
     9  import (
    10  	"errors"
    11  	"fmt"
    12  	"testing"
    13  
    14  	"github.com/golang/protobuf/proto"
    15  	"github.com/hyperledger/fabric-protos-go/gossip"
    16  	"github.com/hyperledger/fabric/gossip/protoext"
    17  	"github.com/hyperledger/fabric/protoutil"
    18  	"github.com/stretchr/testify/assert"
    19  )
    20  
    21  func TestToGossipMessageNilEnvelope(t *testing.T) {
    22  	memReq := &gossip.MembershipRequest{}
    23  	_, err := protoext.EnvelopeToGossipMessage(memReq.SelfInformation)
    24  	assert.EqualError(t, err, "nil envelope")
    25  }
    26  
    27  func TestToString(t *testing.T) {
    28  	// Ensure we don't print the byte content when we
    29  	// log messages.
    30  	// Each payload or signature contains '2' so we would've logged
    31  	// them if not for the overloading of the String() method in SignedGossipMessage
    32  
    33  	// The following line proves that the envelopes constructed in this test
    34  	// have "2" in them when they are printed
    35  	assert.Contains(t, fmt.Sprintf("%v", envelopes()[0]), "2")
    36  	// and the following does the same for payloads:
    37  	dMsg := &gossip.DataMessage{
    38  		Payload: &gossip.Payload{
    39  			SeqNum: 3,
    40  			Data:   []byte{2, 2, 2, 2, 2},
    41  		},
    42  	}
    43  	assert.Contains(t, fmt.Sprintf("%v", dMsg), "2")
    44  
    45  	// Now we construct all types of messages that have envelopes or payloads in them
    46  	// and see that "2" is not outputted into their formatting even though it is found
    47  	// as a sub-message of the outer message.
    48  
    49  	sMsg := &protoext.SignedGossipMessage{
    50  		GossipMessage: &gossip.GossipMessage{
    51  			Tag:     gossip.GossipMessage_EMPTY,
    52  			Nonce:   5,
    53  			Channel: []byte("A"),
    54  			Content: &gossip.GossipMessage_DataMsg{
    55  				DataMsg: &gossip.DataMessage{
    56  					Payload: &gossip.Payload{
    57  						SeqNum: 3,
    58  						Data:   []byte{2, 2, 2, 2, 2},
    59  					},
    60  				},
    61  			},
    62  		},
    63  		Envelope: &gossip.Envelope{
    64  			Payload:   []byte{0, 1, 2, 3, 4, 5, 6},
    65  			Signature: []byte{0, 1, 2},
    66  			SecretEnvelope: &gossip.SecretEnvelope{
    67  				Payload:   []byte{0, 1, 2, 3, 4, 5},
    68  				Signature: []byte{0, 1, 2},
    69  			},
    70  		},
    71  	}
    72  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
    73  	sMsg.GetDataMsg().Payload = nil
    74  	assert.NotPanics(t, func() {
    75  		_ = sMsg.String()
    76  	})
    77  
    78  	sMsg = &protoext.SignedGossipMessage{
    79  		GossipMessage: &gossip.GossipMessage{
    80  			Channel: []byte("A"),
    81  			Tag:     gossip.GossipMessage_EMPTY,
    82  			Nonce:   5,
    83  			Content: &gossip.GossipMessage_DataUpdate{
    84  				DataUpdate: &gossip.DataUpdate{
    85  					Nonce:   11,
    86  					MsgType: gossip.PullMsgType_BLOCK_MSG,
    87  					Data:    envelopes(),
    88  				},
    89  			},
    90  		},
    91  		Envelope: envelopes()[0],
    92  	}
    93  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
    94  
    95  	sMsg = &protoext.SignedGossipMessage{
    96  		GossipMessage: &gossip.GossipMessage{
    97  			Channel: []byte("A"),
    98  			Tag:     gossip.GossipMessage_EMPTY,
    99  			Nonce:   5,
   100  			Content: &gossip.GossipMessage_MemRes{
   101  				MemRes: &gossip.MembershipResponse{
   102  					Alive: envelopes(),
   103  					Dead:  envelopes(),
   104  				},
   105  			},
   106  		},
   107  		Envelope: envelopes()[0],
   108  	}
   109  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   110  
   111  	sMsg = &protoext.SignedGossipMessage{
   112  		GossipMessage: &gossip.GossipMessage{
   113  			Channel: []byte("A"),
   114  			Tag:     gossip.GossipMessage_EMPTY,
   115  			Nonce:   5,
   116  			Content: &gossip.GossipMessage_StateSnapshot{
   117  				StateSnapshot: &gossip.StateInfoSnapshot{
   118  					Elements: envelopes(),
   119  				},
   120  			},
   121  		},
   122  		Envelope: envelopes()[0],
   123  	}
   124  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   125  
   126  	sMsg = &protoext.SignedGossipMessage{
   127  		GossipMessage: &gossip.GossipMessage{
   128  			Channel: []byte("A"),
   129  			Tag:     gossip.GossipMessage_EMPTY,
   130  			Nonce:   5,
   131  			Content: &gossip.GossipMessage_AliveMsg{
   132  				AliveMsg: &gossip.AliveMessage{
   133  					Membership: &gossip.Member{
   134  						Endpoint: "localhost",
   135  						Metadata: []byte{1, 2, 3, 4, 5},
   136  						PkiId:    []byte{17},
   137  					},
   138  					Timestamp: &gossip.PeerTime{
   139  						IncNum: 1,
   140  						SeqNum: 1,
   141  					},
   142  					Identity: []byte("peerID1"),
   143  				},
   144  			},
   145  		},
   146  		Envelope: envelopes()[0],
   147  	}
   148  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   149  
   150  	sMsg = &protoext.SignedGossipMessage{
   151  		GossipMessage: &gossip.GossipMessage{
   152  			Channel: []byte("A"),
   153  			Tag:     gossip.GossipMessage_EMPTY,
   154  			Nonce:   5,
   155  			Content: &gossip.GossipMessage_StateResponse{
   156  				StateResponse: &gossip.RemoteStateResponse{
   157  					Payloads: []*gossip.Payload{
   158  						{Data: []byte{2, 2, 2}},
   159  					},
   160  				},
   161  			},
   162  		},
   163  		Envelope: envelopes()[0],
   164  	}
   165  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   166  
   167  	sMsg = &protoext.SignedGossipMessage{
   168  		GossipMessage: &gossip.GossipMessage{
   169  			Channel: []byte("A"),
   170  			Tag:     gossip.GossipMessage_EMPTY,
   171  			Nonce:   5,
   172  			Content: &gossip.GossipMessage_MemReq{
   173  				MemReq: &gossip.MembershipRequest{
   174  					SelfInformation: sMsg.Envelope,
   175  					Known:           [][]byte{},
   176  				},
   177  			},
   178  		},
   179  		Envelope: envelopes()[0],
   180  	}
   181  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   182  
   183  	sMsg = &protoext.SignedGossipMessage{
   184  		GossipMessage: &gossip.GossipMessage{
   185  			Channel: []byte("A"),
   186  			Tag:     gossip.GossipMessage_EMPTY,
   187  			Nonce:   5,
   188  			Content: &gossip.GossipMessage_StateInfoPullReq{
   189  				StateInfoPullReq: &gossip.StateInfoPullRequest{
   190  					Channel_MAC: []byte{17},
   191  				},
   192  			},
   193  		},
   194  		Envelope: envelopes()[0],
   195  	}
   196  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   197  
   198  	sMsg = &protoext.SignedGossipMessage{
   199  		GossipMessage: &gossip.GossipMessage{
   200  			Channel: []byte("A"),
   201  			Tag:     gossip.GossipMessage_EMPTY,
   202  			Nonce:   5,
   203  			Content: &gossip.GossipMessage_StateInfo{
   204  				StateInfo: &gossip.StateInfo{
   205  					Channel_MAC: []byte{17},
   206  				},
   207  			},
   208  		},
   209  		Envelope: envelopes()[0],
   210  	}
   211  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   212  
   213  	sMsg = &protoext.SignedGossipMessage{
   214  		GossipMessage: &gossip.GossipMessage{
   215  			Channel: []byte("A"),
   216  			Tag:     gossip.GossipMessage_EMPTY,
   217  			Nonce:   5,
   218  			Content: &gossip.GossipMessage_DataDig{
   219  				DataDig: &gossip.DataDigest{
   220  					Nonce:   0,
   221  					Digests: [][]byte{[]byte("msg1"), []byte("msg2")},
   222  					MsgType: gossip.PullMsgType_BLOCK_MSG,
   223  				},
   224  			},
   225  		},
   226  		Envelope: envelopes()[0],
   227  	}
   228  	assert.Contains(t, fmt.Sprintf("%v", sMsg), "2")
   229  
   230  	sMsg = &protoext.SignedGossipMessage{
   231  		GossipMessage: &gossip.GossipMessage{
   232  			Channel: []byte("A"),
   233  			Tag:     gossip.GossipMessage_EMPTY,
   234  			Nonce:   5,
   235  			Content: &gossip.GossipMessage_DataReq{
   236  				DataReq: &gossip.DataRequest{
   237  					Nonce:   0,
   238  					Digests: [][]byte{[]byte("msg1"), []byte("msg2")},
   239  					MsgType: gossip.PullMsgType_BLOCK_MSG,
   240  				},
   241  			},
   242  		},
   243  		Envelope: envelopes()[0],
   244  	}
   245  	assert.Contains(t, fmt.Sprintf("%v", sMsg), "2")
   246  
   247  	sMsg = &protoext.SignedGossipMessage{
   248  		GossipMessage: &gossip.GossipMessage{
   249  			Channel: []byte("A"),
   250  			Tag:     gossip.GossipMessage_EMPTY,
   251  			Nonce:   5,
   252  			Content: &gossip.GossipMessage_LeadershipMsg{
   253  				LeadershipMsg: &gossip.LeadershipMessage{
   254  					Timestamp: &gossip.PeerTime{
   255  						IncNum: 1,
   256  						SeqNum: 1,
   257  					},
   258  					PkiId:         []byte{17},
   259  					IsDeclaration: true,
   260  				},
   261  			},
   262  		},
   263  		Envelope: envelopes()[0],
   264  	}
   265  	assert.NotContains(t, fmt.Sprintf("%v", sMsg), "2")
   266  }
   267  
   268  func TestSignedGossipMessageSign(t *testing.T) {
   269  	idSigner := func(msg []byte) ([]byte, error) {
   270  		return msg, nil
   271  	}
   272  
   273  	errSigner := func(msg []byte) ([]byte, error) {
   274  		return nil, errors.New("Error")
   275  	}
   276  
   277  	msg := &protoext.SignedGossipMessage{
   278  		GossipMessage: &gossip.GossipMessage{
   279  			Channel: []byte("testChannelID"),
   280  			Tag:     gossip.GossipMessage_EMPTY,
   281  			Content: &gossip.GossipMessage_DataMsg{
   282  				DataMsg: &gossip.DataMessage{},
   283  			},
   284  		},
   285  	}
   286  	signedMsg, _ := msg.Sign(idSigner)
   287  
   288  	// Since checking the identity signer, signature will be same as the payload
   289  	assert.Equal(t, signedMsg.Payload, signedMsg.Signature)
   290  
   291  	env, err := msg.Sign(errSigner)
   292  	assert.Error(t, err)
   293  	assert.Nil(t, env)
   294  }
   295  
   296  func TestEnvelope_NoopSign(t *testing.T) {
   297  	msg := &gossip.GossipMessage{
   298  		Channel: []byte("testChannelID"),
   299  		Tag:     gossip.GossipMessage_EMPTY,
   300  		Content: &gossip.GossipMessage_DataMsg{
   301  			DataMsg: &gossip.DataMessage{},
   302  		},
   303  	}
   304  
   305  	signedMsg, err := protoext.NoopSign(msg)
   306  
   307  	// Since checking the identity signer, signature will be same as the payload
   308  	assert.Nil(t, signedMsg.Signature)
   309  	assert.NoError(t, err)
   310  }
   311  
   312  func TestSignedGossipMessage_Verify(t *testing.T) {
   313  	channelID := "testChannelID"
   314  	peerID := []byte("peer")
   315  
   316  	msg := &protoext.SignedGossipMessage{
   317  		GossipMessage: &gossip.GossipMessage{
   318  			Channel: []byte(channelID),
   319  			Tag:     gossip.GossipMessage_EMPTY,
   320  			Content: &gossip.GossipMessage_DataMsg{
   321  				DataMsg: &gossip.DataMessage{},
   322  			},
   323  		},
   324  		Envelope: envelopes()[0],
   325  	}
   326  	assert.True(t, msg.IsSigned())
   327  
   328  	verifier := func(peerIdentity []byte, signature, message []byte) error {
   329  		return nil
   330  	}
   331  	res := msg.Verify(peerID, verifier)
   332  	assert.Nil(t, res)
   333  
   334  	msg = &protoext.SignedGossipMessage{
   335  		GossipMessage: &gossip.GossipMessage{
   336  			Channel: []byte(channelID),
   337  			Tag:     gossip.GossipMessage_EMPTY,
   338  			Content: &gossip.GossipMessage_DataMsg{
   339  				DataMsg: &gossip.DataMessage{},
   340  			},
   341  		},
   342  		Envelope: envelopes()[0],
   343  	}
   344  
   345  	env := msg.Envelope
   346  	msg.Envelope = nil
   347  	res = msg.Verify(peerID, verifier)
   348  	assert.Error(t, res)
   349  
   350  	msg.Envelope = env
   351  	payload := msg.Envelope.Payload
   352  	msg.Envelope.Payload = nil
   353  	res = msg.Verify(peerID, verifier)
   354  	assert.Error(t, res)
   355  
   356  	msg.Envelope.Payload = payload
   357  	sig := msg.Signature
   358  	msg.Signature = nil
   359  	res = msg.Verify(peerID, verifier)
   360  	assert.Error(t, res)
   361  	msg.Signature = sig
   362  
   363  	errVerifier := func(peerIdentity []byte, signature, message []byte) error {
   364  		return errors.New("Test")
   365  	}
   366  
   367  	res = msg.Verify(peerID, errVerifier)
   368  	assert.Error(t, res)
   369  }
   370  
   371  func TestEnvelope(t *testing.T) {
   372  	dataMsg := &gossip.GossipMessage{
   373  		Content: dataMessage(1, []byte("data")),
   374  	}
   375  	bytes, err := proto.Marshal(dataMsg)
   376  	assert.NoError(t, err)
   377  
   378  	env := envelopes()[0]
   379  	env.Payload = bytes
   380  
   381  	msg, err := protoext.EnvelopeToGossipMessage(env)
   382  	assert.NoError(t, err)
   383  	assert.NotNil(t, msg)
   384  
   385  	assert.True(t, protoext.IsDataMsg(msg.GossipMessage))
   386  }
   387  
   388  func TestEnvelope_SignSecret(t *testing.T) {
   389  	dataMsg := &gossip.GossipMessage{
   390  		Content: dataMessage(1, []byte("data")),
   391  	}
   392  	bytes, err := proto.Marshal(dataMsg)
   393  	assert.NoError(t, err)
   394  
   395  	env := envelopes()[0]
   396  	env.Payload = bytes
   397  	env.SecretEnvelope = nil
   398  
   399  	protoext.SignSecret(env, func(message []byte) ([]byte, error) {
   400  		return message, nil
   401  	}, &gossip.Secret{
   402  		Content: &gossip.Secret_InternalEndpoint{
   403  			InternalEndpoint: "localhost:5050",
   404  		},
   405  	})
   406  
   407  	assert.NotNil(t, env.SecretEnvelope)
   408  	assert.Equal(t, protoext.InternalEndpoint(env.SecretEnvelope), "localhost:5050")
   409  }
   410  
   411  func TestInternalEndpoint(t *testing.T) {
   412  	assert.Empty(t, protoext.InternalEndpoint(nil))
   413  	assert.Empty(t, protoext.InternalEndpoint(&gossip.SecretEnvelope{
   414  		Payload: []byte{1, 2, 3}}))
   415  	assert.Equal(t, "foo", protoext.InternalEndpoint(&gossip.SecretEnvelope{
   416  		Payload: protoutil.MarshalOrPanic(
   417  			&gossip.Secret{
   418  				Content: &gossip.Secret_InternalEndpoint{
   419  					InternalEndpoint: "foo",
   420  				},
   421  			})}))
   422  }
   423  
   424  func envelopes() []*gossip.Envelope {
   425  	return []*gossip.Envelope{
   426  		{Payload: []byte{2, 2, 2},
   427  			Signature: []byte{2, 2, 2},
   428  			SecretEnvelope: &gossip.SecretEnvelope{
   429  				Payload:   []byte{2, 2, 2},
   430  				Signature: []byte{2, 2, 2},
   431  			},
   432  		},
   433  	}
   434  }