github.com/ewagmig/fabric@v2.1.1+incompatible/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 }