github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/peer/gossip/mcs.go (about)

     1  /*
     2  Copyright IBM Corp. 2017 All Rights Reserved.
     3  
     4  Licensed under the Apache License, Version 2.0 (the "License");
     5  you may not use this file except in compliance with the License.
     6  You may obtain a copy of the License at
     7  
     8  		 http://www.apache.org/licenses/LICENSE-2.0
     9  
    10  Unless required by applicable law or agreed to in writing, software
    11  distributed under the License is distributed on an "AS IS" BASIS,
    12  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13  See the License for the specific language governing permissions and
    14  limitations under the License.
    15  */
    16  
    17  package gossip
    18  
    19  import (
    20  	"bytes"
    21  	"errors"
    22  	"fmt"
    23  
    24  	"github.com/hyperledger/fabric/bccsp"
    25  	"github.com/hyperledger/fabric/bccsp/factory"
    26  	"github.com/hyperledger/fabric/common/crypto"
    27  	"github.com/hyperledger/fabric/common/flogging"
    28  	"github.com/hyperledger/fabric/common/policies"
    29  	"github.com/hyperledger/fabric/common/util"
    30  	"github.com/hyperledger/fabric/gossip/api"
    31  	"github.com/hyperledger/fabric/gossip/common"
    32  	"github.com/hyperledger/fabric/msp"
    33  	"github.com/hyperledger/fabric/msp/mgmt"
    34  	pcommon "github.com/hyperledger/fabric/protos/common"
    35  	"github.com/hyperledger/fabric/protos/utils"
    36  )
    37  
    38  var mcsLogger = flogging.MustGetLogger("peer/gossip/mcs")
    39  
    40  // mspMessageCryptoService implements the MessageCryptoService interface
    41  // using the peer MSPs (local and channel-related)
    42  //
    43  // In order for the system to be secure it is vital to have the
    44  // MSPs to be up-to-date. Channels' MSPs are updated via
    45  // configuration transactions distributed by the ordering service.
    46  //
    47  // A similar mechanism needs to be in place to update the local MSP, as well.
    48  // This implementation assumes that these mechanisms are all in place and working.
    49  type mspMessageCryptoService struct {
    50  	channelPolicyManagerGetter policies.ChannelPolicyManagerGetter
    51  	localSigner                crypto.LocalSigner
    52  	deserializer               mgmt.DeserializersManager
    53  }
    54  
    55  // NewMCS creates a new instance of mspMessageCryptoService
    56  // that implements MessageCryptoService.
    57  // The method takes in input:
    58  // 1. a policies.ChannelPolicyManagerGetter that gives access to the policy manager of a given channel via the Manager method.
    59  // 2. an instance of crypto.LocalSigner
    60  // 3. an identity deserializer manager
    61  func NewMCS(channelPolicyManagerGetter policies.ChannelPolicyManagerGetter, localSigner crypto.LocalSigner, deserializer mgmt.DeserializersManager) api.MessageCryptoService {
    62  	return &mspMessageCryptoService{channelPolicyManagerGetter: channelPolicyManagerGetter, localSigner: localSigner, deserializer: deserializer}
    63  }
    64  
    65  // ValidateIdentity validates the identity of a remote peer.
    66  // If the identity is invalid, revoked, expired it returns an error.
    67  // Else, returns nil
    68  func (s *mspMessageCryptoService) ValidateIdentity(peerIdentity api.PeerIdentityType) error {
    69  	// As prescibed by the contract of method,
    70  	// here we check only that peerIdentity is not
    71  	// invalid, revoked or expired.
    72  
    73  	_, _, err := s.getValidatedIdentity(peerIdentity)
    74  	return err
    75  }
    76  
    77  // GetPKIidOfCert returns the PKI-ID of a peer's identity
    78  // If any error occurs, the method return nil
    79  // The PKid of a peer is computed as the SHA2-256 of peerIdentity which
    80  // is supposed to be the serialized version of MSP identity.
    81  // This method does not validate peerIdentity.
    82  // This validation is supposed to be done appropriately during the execution flow.
    83  func (s *mspMessageCryptoService) GetPKIidOfCert(peerIdentity api.PeerIdentityType) common.PKIidType {
    84  	// Validate arguments
    85  	if len(peerIdentity) == 0 {
    86  		mcsLogger.Error("Invalid Peer Identity. It must be different from nil.")
    87  
    88  		return nil
    89  	}
    90  
    91  	sid, err := s.deserializer.Deserialize(peerIdentity)
    92  	if err != nil {
    93  		mcsLogger.Errorf("Failed getting validated identity from peer identity [% x]: [%s]", peerIdentity, err)
    94  
    95  		return nil
    96  	}
    97  
    98  	// concatenate msp-id and idbytes
    99  	// idbytes is the low-level representation of an identity.
   100  	// it is supposed to be already in its minimal representation
   101  
   102  	mspIdRaw := []byte(sid.Mspid)
   103  	raw := append(mspIdRaw, sid.IdBytes...)
   104  
   105  	// Hash
   106  	digest, err := factory.GetDefault().Hash(raw, &bccsp.SHA256Opts{})
   107  	if err != nil {
   108  		mcsLogger.Errorf("Failed computing digest of serialized identity [% x]: [%s]", peerIdentity, err)
   109  
   110  		return nil
   111  	}
   112  
   113  	return digest
   114  }
   115  
   116  // VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
   117  // sequence number that the block's header contains.
   118  // else returns error
   119  func (s *mspMessageCryptoService) VerifyBlock(chainID common.ChainID, seqNum uint64, signedBlock []byte) error {
   120  	// - Convert signedBlock to common.Block.
   121  	block, err := utils.GetBlockFromBlockBytes(signedBlock)
   122  	if err != nil {
   123  		return fmt.Errorf("Failed unmarshalling block bytes on channel [%s]: [%s]", chainID, err)
   124  	}
   125  
   126  	if block.Header == nil {
   127  		return fmt.Errorf("Invalid Block on channel [%s]. Header must be different from nil.", chainID)
   128  	}
   129  
   130  	blockSeqNum := block.Header.Number
   131  	if seqNum != blockSeqNum {
   132  		return fmt.Errorf("Claimed seqNum is [%d] but actual seqNum inside block is [%d]", seqNum, blockSeqNum)
   133  	}
   134  
   135  	// - Extract channelID and compare with chainID
   136  	channelID, err := utils.GetChainIDFromBlock(block)
   137  	if err != nil {
   138  		return fmt.Errorf("Failed getting channel id from block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   139  	}
   140  
   141  	if channelID != string(chainID) {
   142  		return fmt.Errorf("Invalid block's channel id. Expected [%s]. Given [%s]", chainID, channelID)
   143  	}
   144  
   145  	// - Unmarshal medatada
   146  	if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
   147  		return fmt.Errorf("Block with id [%d] on channel [%s] does not have metadata. Block not valid.", block.Header.Number, chainID)
   148  	}
   149  
   150  	metadata, err := utils.GetMetadataFromBlock(block, pcommon.BlockMetadataIndex_SIGNATURES)
   151  	if err != nil {
   152  		return fmt.Errorf("Failed unmarshalling medatata for signatures [%s]", err)
   153  	}
   154  
   155  	// - Verify that Header.DataHash is equal to the hash of block.Data
   156  	// This is to ensure that the header is consistent with the data carried by this block
   157  	if !bytes.Equal(block.Data.Hash(), block.Header.DataHash) {
   158  		return fmt.Errorf("Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]", block.Header.Number, chainID)
   159  	}
   160  
   161  	// - Get Policy for block validation
   162  
   163  	// Get the policy manager for channelID
   164  	cpm, ok := s.channelPolicyManagerGetter.Manager(channelID)
   165  	if cpm == nil {
   166  		return fmt.Errorf("Could not acquire policy manager for channel %s", channelID)
   167  	}
   168  	// ok is true if it was the manager requested, or false if it is the default manager
   169  	mcsLogger.Debugf("Got policy manager for channel [%s] with flag [%s]", channelID, ok)
   170  
   171  	// Get block validation policy
   172  	policy, ok := cpm.GetPolicy(policies.BlockValidation)
   173  	// ok is true if it was the policy requested, or false if it is the default policy
   174  	mcsLogger.Debugf("Got block validation policy for channel [%s] with flag [%s]", channelID, ok)
   175  
   176  	// - Prepare SignedData
   177  	signatureSet := []*pcommon.SignedData{}
   178  	for _, metadataSignature := range metadata.Signatures {
   179  		shdr, err := utils.GetSignatureHeader(metadataSignature.SignatureHeader)
   180  		if err != nil {
   181  			return fmt.Errorf("Failed unmarshalling signature header for block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   182  		}
   183  		signatureSet = append(
   184  			signatureSet,
   185  			&pcommon.SignedData{
   186  				Identity:  shdr.Creator,
   187  				Data:      util.ConcatenateBytes(metadata.Value, metadataSignature.SignatureHeader, block.Header.Bytes()),
   188  				Signature: metadataSignature.Signature,
   189  			},
   190  		)
   191  	}
   192  
   193  	// - Evaluate policy
   194  	return policy.Evaluate(signatureSet)
   195  }
   196  
   197  // Sign signs msg with this peer's signing key and outputs
   198  // the signature if no error occurred.
   199  func (s *mspMessageCryptoService) Sign(msg []byte) ([]byte, error) {
   200  	return s.localSigner.Sign(msg)
   201  }
   202  
   203  // Verify checks that signature is a valid signature of message under a peer's verification key.
   204  // If the verification succeeded, Verify returns nil meaning no error occurred.
   205  // If peerIdentity is nil, then the verification fails.
   206  func (s *mspMessageCryptoService) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
   207  	identity, chainID, err := s.getValidatedIdentity(peerIdentity)
   208  	if err != nil {
   209  		mcsLogger.Errorf("Failed getting validated identity from peer identity [%s]", err)
   210  
   211  		return err
   212  	}
   213  
   214  	if len(chainID) == 0 {
   215  		// At this stage, this means that peerIdentity
   216  		// belongs to this peer's LocalMSP.
   217  		// The signature is validated directly
   218  		return identity.Verify(message, signature)
   219  	}
   220  
   221  	// At this stage, the signature must be validated
   222  	// against the reader policy of the channel
   223  	// identified by chainID
   224  
   225  	return s.VerifyByChannel(chainID, peerIdentity, signature, message)
   226  }
   227  
   228  // VerifyByChannel checks that signature is a valid signature of message
   229  // under a peer's verification key, but also in the context of a specific channel.
   230  // If the verification succeeded, Verify returns nil meaning no error occurred.
   231  // If peerIdentity is nil, then the verification fails.
   232  func (s *mspMessageCryptoService) VerifyByChannel(chainID common.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error {
   233  	// Validate arguments
   234  	if len(peerIdentity) == 0 {
   235  		return errors.New("Invalid Peer Identity. It must be different from nil.")
   236  	}
   237  
   238  	// Get the policy manager for channel chainID
   239  	cpm, flag := s.channelPolicyManagerGetter.Manager(string(chainID))
   240  	if cpm == nil {
   241  		return fmt.Errorf("Could not acquire policy manager for channel %s", string(chainID))
   242  	}
   243  	mcsLogger.Debugf("Got policy manager for channel [%s] with flag [%s]", string(chainID), flag)
   244  
   245  	// Get channel reader policy
   246  	policy, flag := cpm.GetPolicy(policies.ChannelApplicationReaders)
   247  	mcsLogger.Debugf("Got reader policy for channel [%s] with flag [%s]", string(chainID), flag)
   248  
   249  	return policy.Evaluate(
   250  		[]*pcommon.SignedData{{
   251  			Data:      message,
   252  			Identity:  []byte(peerIdentity),
   253  			Signature: signature,
   254  		}},
   255  	)
   256  }
   257  
   258  func (s *mspMessageCryptoService) getValidatedIdentity(peerIdentity api.PeerIdentityType) (msp.Identity, common.ChainID, error) {
   259  	// Validate arguments
   260  	if len(peerIdentity) == 0 {
   261  		return nil, nil, errors.New("Invalid Peer Identity. It must be different from nil.")
   262  	}
   263  
   264  	// Notice that peerIdentity is assumed to be the serialization of an identity.
   265  	// So, first step is the identity deserialization and then verify it.
   266  
   267  	// First check against the local MSP.
   268  	// If the peerIdentity is in the same organization of this node then
   269  	// the local MSP is required to take the final decision on the validity
   270  	// of the signature.
   271  	identity, err := s.deserializer.GetLocalDeserializer().DeserializeIdentity([]byte(peerIdentity))
   272  	if err == nil {
   273  		// No error means that the local MSP successfully deserialized the identity.
   274  		// We now check additional properties.
   275  
   276  		// TODO: The following check will be replaced by a check on the organizational units
   277  		// when we allow the gossip network to have organization unit (MSP subdivisions)
   278  		// scoped messages.
   279  		// The following check is consistent with the SecurityAdvisor#OrgByPeerIdentity
   280  		// implementation.
   281  		// TODO: Notice that the following check saves us from the fact
   282  		// that DeserializeIdentity does not yet enforce MSP-IDs consistency.
   283  		// This check can be removed once DeserializeIdentity will be fixed.
   284  		if identity.GetMSPIdentifier() == s.deserializer.GetLocalMSPIdentifier() {
   285  			// Check identity validity
   286  
   287  			// Notice that at this stage we don't have to check the identity
   288  			// against any channel's policies.
   289  			// This will be done by the caller function, if needed.
   290  			return identity, nil, identity.Validate()
   291  		}
   292  	}
   293  
   294  	// Check against managers
   295  	for chainID, mspManager := range s.deserializer.GetChannelDeserializers() {
   296  		// Deserialize identity
   297  		identity, err := mspManager.DeserializeIdentity([]byte(peerIdentity))
   298  		if err != nil {
   299  			mcsLogger.Debugf("Failed deserialization identity [% x] on [%s]: [%s]", peerIdentity, chainID, err)
   300  			continue
   301  		}
   302  
   303  		// Check identity validity
   304  		// Notice that at this stage we don't have to check the identity
   305  		// against any channel's policies.
   306  		// This will be done by the caller function, if needed.
   307  
   308  		if err := identity.Validate(); err != nil {
   309  			mcsLogger.Debugf("Failed validating identity [% x] on [%s]: [%s]", peerIdentity, chainID, err)
   310  			continue
   311  		}
   312  
   313  		mcsLogger.Debugf("Validation succeeded [% x] on [%s]", peerIdentity, chainID)
   314  
   315  		return identity, common.ChainID(chainID), nil
   316  	}
   317  
   318  	return nil, nil, fmt.Errorf("Peer Identity [% x] cannot be validated. No MSP found able to do that.", peerIdentity)
   319  }