github.com/hechain20/hechain@v0.0.0-20220316014945-b544036ba106/internal/peer/gossip/mcs_test.go (about)

     1  /*
     2  Copyright hechain. 2017 All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package gossip
     8  
     9  import (
    10  	"crypto/sha256"
    11  	"errors"
    12  	"reflect"
    13  	"strings"
    14  	"testing"
    15  	"time"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	"github.com/hechain20/hechain/bccsp/sw"
    19  	"github.com/hechain20/hechain/common/policies"
    20  	"github.com/hechain20/hechain/common/util"
    21  	"github.com/hechain20/hechain/gossip/api"
    22  	"github.com/hechain20/hechain/internal/peer/gossip/mocks"
    23  	"github.com/hechain20/hechain/internal/pkg/identity"
    24  	"github.com/hechain20/hechain/msp"
    25  	"github.com/hechain20/hechain/msp/mgmt"
    26  	"github.com/hechain20/hechain/protoutil"
    27  	"github.com/hyperledger/fabric-protos-go/common"
    28  	pmsp "github.com/hyperledger/fabric-protos-go/msp"
    29  	protospeer "github.com/hyperledger/fabric-protos-go/peer"
    30  	"github.com/stretchr/testify/mock"
    31  	"github.com/stretchr/testify/require"
    32  )
    33  
    34  //go:generate counterfeiter -o mocks/policy_manager.go -fake-name PolicyManager . policyManager
    35  
    36  type policyManager interface {
    37  	policies.Manager
    38  }
    39  
    40  //go:generate counterfeiter -o mocks/signer_serializer.go --fake-name SignerSerializer . signerSerializer
    41  
    42  type signerSerializer interface {
    43  	identity.SignerSerializer
    44  }
    45  
    46  func TestPKIidOfCert(t *testing.T) {
    47  	deserializersManager := &mocks.DeserializersManager{
    48  		LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
    49  	}
    50  	signer := &mocks.SignerSerializer{}
    51  	signer.SerializeReturns([]byte("Alice"), nil)
    52  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    53  	require.NoError(t, err)
    54  	msgCryptoService := NewMCS(
    55  		&mocks.ChannelPolicyManagerGetterWithManager{},
    56  		signer,
    57  		deserializersManager,
    58  		cryptoProvider,
    59  	)
    60  
    61  	peerIdentity := []byte("Alice")
    62  	pkid := msgCryptoService.GetPKIidOfCert(peerIdentity)
    63  
    64  	// Check pkid is not nil
    65  	require.NotNil(t, pkid, "PKID must be different from nil")
    66  	// Check that pkid is correctly computed
    67  	id, err := deserializersManager.Deserialize(peerIdentity)
    68  	require.NoError(t, err, "Failed getting validated identity from [% x]", []byte(peerIdentity))
    69  	idRaw := append([]byte(id.Mspid), id.IdBytes...)
    70  	require.NoError(t, err, "Failed marshalling identity identifier [% x]: [%s]", peerIdentity, err)
    71  	h := sha256.New()
    72  	h.Write(idRaw)
    73  	digest := h.Sum(nil)
    74  	require.Equal(t, digest, []byte(pkid), "PKID must be the SHA2-256 of peerIdentity")
    75  
    76  	//  The PKI-ID is calculated by concatenating the MspId with IdBytes.
    77  	// Ensure that additional fields haven't been introduced in the code
    78  	v := reflect.Indirect(reflect.ValueOf(id)).Type()
    79  	fieldsThatStartWithXXX := 0
    80  	for i := 0; i < v.NumField(); i++ {
    81  		if strings.Index(v.Field(i).Name, "XXX_") == 0 {
    82  			fieldsThatStartWithXXX++
    83  		}
    84  	}
    85  	require.Equal(t, 2+fieldsThatStartWithXXX, v.NumField())
    86  }
    87  
    88  func TestPKIidOfNil(t *testing.T) {
    89  	signer := &mocks.SignerSerializer{}
    90  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
    91  	require.NoError(t, err)
    92  	localMSP := mgmt.GetLocalMSP(cryptoProvider)
    93  	msgCryptoService := NewMCS(
    94  		&mocks.ChannelPolicyManagerGetter{},
    95  		signer,
    96  		NewDeserializersManager(localMSP),
    97  		cryptoProvider,
    98  	)
    99  
   100  	pkid := msgCryptoService.GetPKIidOfCert(nil)
   101  	// Check pkid is not nil
   102  	require.Nil(t, pkid, "PKID must be nil")
   103  }
   104  
   105  func TestValidateIdentity(t *testing.T) {
   106  	deserializersManager := &mocks.DeserializersManager{
   107  		LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
   108  		ChannelDeserializers: map[string]msp.IdentityDeserializer{
   109  			"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
   110  		},
   111  	}
   112  	signer := &mocks.SignerSerializer{}
   113  	signer.SerializeReturns([]byte("Charlie"), nil)
   114  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   115  	require.NoError(t, err)
   116  	msgCryptoService := NewMCS(
   117  		&mocks.ChannelPolicyManagerGetterWithManager{},
   118  		signer,
   119  		deserializersManager,
   120  		cryptoProvider,
   121  	)
   122  
   123  	err = msgCryptoService.ValidateIdentity([]byte("Alice"))
   124  	require.NoError(t, err)
   125  
   126  	err = msgCryptoService.ValidateIdentity([]byte("Bob"))
   127  	require.NoError(t, err)
   128  
   129  	err = msgCryptoService.ValidateIdentity([]byte("Charlie"))
   130  	require.Error(t, err)
   131  
   132  	err = msgCryptoService.ValidateIdentity(nil)
   133  	require.Error(t, err)
   134  
   135  	// Now, pretend the identities are not well formed
   136  	deserializersManager.ChannelDeserializers["A"].(*mocks.IdentityDeserializer).On("IsWellFormed", mock.Anything).Return(errors.New("invalid form"))
   137  	err = msgCryptoService.ValidateIdentity([]byte("Bob"))
   138  	require.Error(t, err)
   139  	require.Equal(t, "identity is not well formed: invalid form", err.Error())
   140  
   141  	deserializersManager.LocalDeserializer.(*mocks.IdentityDeserializer).On("IsWellFormed", mock.Anything).Return(errors.New("invalid form"))
   142  	err = msgCryptoService.ValidateIdentity([]byte("Alice"))
   143  	require.Error(t, err)
   144  	require.Equal(t, "identity is not well formed: invalid form", err.Error())
   145  }
   146  
   147  func TestSign(t *testing.T) {
   148  	signer := &mocks.SignerSerializer{}
   149  	signer.SignReturns([]byte("signature"), nil)
   150  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   151  	require.NoError(t, err)
   152  
   153  	localMSP := mgmt.GetLocalMSP(cryptoProvider)
   154  	msgCryptoService := NewMCS(
   155  		&mocks.ChannelPolicyManagerGetter{},
   156  		signer,
   157  		NewDeserializersManager(localMSP),
   158  		cryptoProvider,
   159  	)
   160  
   161  	msg := []byte("Hello World!!!")
   162  	sigma, err := msgCryptoService.Sign(msg)
   163  	require.NoError(t, err, "Failed generating signature")
   164  	require.NotNil(t, sigma, "Signature must be different from nil")
   165  }
   166  
   167  func TestVerify(t *testing.T) {
   168  	signer := &mocks.SignerSerializer{}
   169  	signer.SerializeReturns([]byte("Alice"), nil)
   170  	signer.SignReturns([]byte("msg1"), nil)
   171  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   172  	require.NoError(t, err)
   173  	msgCryptoService := NewMCS(
   174  		&mocks.ChannelPolicyManagerGetterWithManager{
   175  			Managers: map[string]policies.Manager{
   176  				"A": &mocks.ChannelPolicyManager{
   177  					Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}}},
   178  				},
   179  				"B": &mocks.ChannelPolicyManager{
   180  					Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}}},
   181  				},
   182  				"C": nil,
   183  			},
   184  		},
   185  		signer,
   186  		&mocks.DeserializersManager{
   187  			LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
   188  			ChannelDeserializers: map[string]msp.IdentityDeserializer{
   189  				"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
   190  				"B": &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}},
   191  				"C": &mocks.IdentityDeserializer{Identity: []byte("Dave"), Msg: []byte("msg4"), Mock: mock.Mock{}},
   192  			},
   193  		},
   194  		cryptoProvider,
   195  	)
   196  
   197  	msg := []byte("msg1")
   198  	sigma, err := msgCryptoService.Sign(msg)
   199  	require.NoError(t, err, "Failed generating signature")
   200  
   201  	err = msgCryptoService.Verify(api.PeerIdentityType("Alice"), sigma, msg)
   202  	require.NoError(t, err, "Alice should verify the signature")
   203  
   204  	err = msgCryptoService.Verify(api.PeerIdentityType("Bob"), sigma, msg)
   205  	require.Error(t, err, "Bob should not verify the signature")
   206  
   207  	err = msgCryptoService.Verify(api.PeerIdentityType("Charlie"), sigma, msg)
   208  	require.Error(t, err, "Charlie should not verify the signature")
   209  
   210  	sigma, err = msgCryptoService.Sign(msg)
   211  	require.NoError(t, err)
   212  	err = msgCryptoService.Verify(api.PeerIdentityType("Dave"), sigma, msg)
   213  	require.Error(t, err)
   214  	require.Contains(t, err.Error(), "Could not acquire policy manager")
   215  
   216  	// Check invalid args
   217  	require.Error(t, msgCryptoService.Verify(nil, sigma, msg))
   218  }
   219  
   220  func TestVerifyBlock(t *testing.T) {
   221  	aliceSigner := &mocks.SignerSerializer{}
   222  	aliceSigner.SerializeReturns([]byte("Alice"), nil)
   223  	policyManagerGetter := &mocks.ChannelPolicyManagerGetterWithManager{
   224  		Managers: map[string]policies.Manager{
   225  			"A": &mocks.ChannelPolicyManager{
   226  				Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}}},
   227  			},
   228  			"B": &mocks.ChannelPolicyManager{
   229  				Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}}},
   230  			},
   231  			"C": &mocks.ChannelPolicyManager{
   232  				Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}}},
   233  			},
   234  			"D": &mocks.ChannelPolicyManager{
   235  				Policy: &mocks.Policy{Deserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}}},
   236  			},
   237  		},
   238  	}
   239  
   240  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   241  	require.NoError(t, err)
   242  	msgCryptoService := NewMCS(
   243  		policyManagerGetter,
   244  		aliceSigner,
   245  		&mocks.DeserializersManager{
   246  			LocalDeserializer: &mocks.IdentityDeserializer{Identity: []byte("Alice"), Msg: []byte("msg1"), Mock: mock.Mock{}},
   247  			ChannelDeserializers: map[string]msp.IdentityDeserializer{
   248  				"A": &mocks.IdentityDeserializer{Identity: []byte("Bob"), Msg: []byte("msg2"), Mock: mock.Mock{}},
   249  				"B": &mocks.IdentityDeserializer{Identity: []byte("Charlie"), Msg: []byte("msg3"), Mock: mock.Mock{}},
   250  			},
   251  		},
   252  		cryptoProvider,
   253  	)
   254  
   255  	// - Prepare testing valid block, Alice signs it.
   256  	blockRaw, msg := mockBlock(t, "C", 42, aliceSigner, nil)
   257  	policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
   258  	blockRaw2, msg2 := mockBlock(t, "D", 42, aliceSigner, nil)
   259  	policyManagerGetter.Managers["D"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg2
   260  
   261  	// - Verify block
   262  	require.NoError(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
   263  	// Wrong sequence number claimed
   264  	err = msgCryptoService.VerifyBlock([]byte("C"), 43, blockRaw)
   265  	require.Error(t, err)
   266  	require.Contains(t, err.Error(), "but actual seqNum inside block is")
   267  	delete(policyManagerGetter.Managers, "D")
   268  	nilPolMgrErr := msgCryptoService.VerifyBlock([]byte("D"), 42, blockRaw2)
   269  	require.Contains(t, nilPolMgrErr.Error(), "Could not acquire policy manager")
   270  	require.Error(t, nilPolMgrErr)
   271  	require.Error(t, msgCryptoService.VerifyBlock([]byte("A"), 42, blockRaw))
   272  	require.Error(t, msgCryptoService.VerifyBlock([]byte("B"), 42, blockRaw))
   273  
   274  	// - Prepare testing invalid block (wrong data has), Alice signs it.
   275  	blockRaw, msg = mockBlock(t, "C", 42, aliceSigner, []byte{0})
   276  	policyManagerGetter.Managers["C"].(*mocks.ChannelPolicyManager).Policy.(*mocks.Policy).Deserializer.(*mocks.IdentityDeserializer).Msg = msg
   277  
   278  	// - Verify block
   279  	require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, blockRaw))
   280  
   281  	// Check invalid args
   282  	require.Error(t, msgCryptoService.VerifyBlock([]byte("C"), 42, &common.Block{}))
   283  }
   284  
   285  func mockBlock(t *testing.T, channel string, seqNum uint64, localSigner *mocks.SignerSerializer, dataHash []byte) (*common.Block, []byte) {
   286  	block := protoutil.NewBlock(seqNum, nil)
   287  
   288  	// Add a fake transaction to the block referring channel "C"
   289  	sProp, _ := protoutil.MockSignedEndorserProposalOrPanic(channel, &protospeer.ChaincodeSpec{}, []byte("transactor"), []byte("transactor's signature"))
   290  	sPropRaw, err := protoutil.Marshal(sProp)
   291  	require.NoError(t, err, "Failed marshalling signed proposal")
   292  	block.Data.Data = [][]byte{sPropRaw}
   293  
   294  	// Compute hash of block.Data and put into the Header
   295  	if len(dataHash) != 0 {
   296  		block.Header.DataHash = dataHash
   297  	} else {
   298  		block.Header.DataHash = protoutil.BlockDataHash(block.Data)
   299  	}
   300  
   301  	// Add signer's signature to the block
   302  	shdr, err := protoutil.NewSignatureHeader(localSigner)
   303  	require.NoError(t, err, "Failed generating signature header")
   304  
   305  	blockSignature := &common.MetadataSignature{
   306  		SignatureHeader: protoutil.MarshalOrPanic(shdr),
   307  	}
   308  
   309  	// Note, this value is intentionally nil, as this metadata is only about the signature, there is no additional metadata
   310  	// information required beyond the fact that the metadata item is signed.
   311  	blockSignatureValue := []byte(nil)
   312  
   313  	msg := util.ConcatenateBytes(blockSignatureValue, blockSignature.SignatureHeader, protoutil.BlockHeaderBytes(block.Header))
   314  	localSigner.SignReturns(msg, nil)
   315  	blockSignature.Signature, err = localSigner.Sign(msg)
   316  	require.NoError(t, err, "Failed signing block")
   317  
   318  	block.Metadata.Metadata[common.BlockMetadataIndex_SIGNATURES] = protoutil.MarshalOrPanic(&common.Metadata{
   319  		Value: blockSignatureValue,
   320  		Signatures: []*common.MetadataSignature{
   321  			blockSignature,
   322  		},
   323  	})
   324  
   325  	return block, msg
   326  }
   327  
   328  func TestExpiration(t *testing.T) {
   329  	expirationDate := time.Now().Add(time.Minute)
   330  	id1 := &pmsp.SerializedIdentity{
   331  		Mspid:   "X509BasedMSP",
   332  		IdBytes: []byte("X509BasedIdentity"),
   333  	}
   334  
   335  	x509IdentityBytes, _ := proto.Marshal(id1)
   336  
   337  	id2 := &pmsp.SerializedIdentity{
   338  		Mspid:   "nonX509BasedMSP",
   339  		IdBytes: []byte("nonX509RawIdentity"),
   340  	}
   341  
   342  	nonX509IdentityBytes, _ := proto.Marshal(id2)
   343  
   344  	deserializersManager := &mocks.DeserializersManager{
   345  		LocalDeserializer: &mocks.IdentityDeserializer{
   346  			Identity: []byte{1, 2, 3},
   347  			Msg:      []byte{1, 2, 3},
   348  		},
   349  		ChannelDeserializers: map[string]msp.IdentityDeserializer{
   350  			"X509BasedMSP": &mocks.IdentityDeserializerWithExpiration{
   351  				Expiration: expirationDate,
   352  				IdentityDeserializer: &mocks.IdentityDeserializer{
   353  					Identity: x509IdentityBytes,
   354  					Msg:      []byte("x509IdentityBytes"),
   355  				},
   356  			},
   357  			"nonX509BasedMSP": &mocks.IdentityDeserializer{
   358  				Identity: nonX509IdentityBytes,
   359  				Msg:      []byte("nonX509IdentityBytes"),
   360  			},
   361  		},
   362  	}
   363  	cryptoProvider, err := sw.NewDefaultSecurityLevelWithKeystore(sw.NewDummyKeyStore())
   364  	require.NoError(t, err)
   365  	msgCryptoService := NewMCS(
   366  		&mocks.ChannelPolicyManagerGetterWithManager{},
   367  		&mocks.SignerSerializer{},
   368  		deserializersManager,
   369  		cryptoProvider,
   370  	)
   371  
   372  	// Green path I check the expiration date is as expected
   373  	exp, err := msgCryptoService.Expiration(x509IdentityBytes)
   374  	require.NoError(t, err)
   375  	require.Equal(t, expirationDate.Second(), exp.Second())
   376  
   377  	// Green path II - a non-x509 identity has a zero expiration time
   378  	exp, err = msgCryptoService.Expiration(nonX509IdentityBytes)
   379  	require.NoError(t, err)
   380  	require.Zero(t, exp)
   381  
   382  	// Bad path I - corrupt the x509 identity and make sure error is returned
   383  	x509IdentityBytes = append(x509IdentityBytes, 0, 0, 0, 0, 0, 0)
   384  	exp, err = msgCryptoService.Expiration(x509IdentityBytes)
   385  	require.Error(t, err)
   386  	require.Contains(t, err.Error(), "No MSP found able to do that")
   387  	require.Zero(t, exp)
   388  }