github.com/leonlxy/hyperledger@v1.0.0-alpha.0.20170427033203-34922035d248/peer/gossip/mcs/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 mcs
    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 logger = 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  // New 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 New(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  		logger.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  		logger.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  		logger.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,
   117  // else returns error
   118  func (s *mspMessageCryptoService) VerifyBlock(chainID common.ChainID, signedBlock []byte) error {
   119  	// - Convert signedBlock to common.Block.
   120  	block, err := utils.GetBlockFromBlockBytes(signedBlock)
   121  	if err != nil {
   122  		return fmt.Errorf("Failed unmarshalling block bytes on channel [%s]: [%s]", chainID, err)
   123  	}
   124  
   125  	if block.Header == nil {
   126  		return fmt.Errorf("Invalid Block on channel [%s]. Header must be different from nil.", chainID)
   127  	}
   128  
   129  	// - Extract channelID and compare with chainID
   130  	channelID, err := utils.GetChainIDFromBlock(block)
   131  	if err != nil {
   132  		return fmt.Errorf("Failed getting channel id from block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   133  	}
   134  
   135  	if channelID != string(chainID) {
   136  		return fmt.Errorf("Invalid block's channel id. Expected [%s]. Given [%s]", chainID, channelID)
   137  	}
   138  
   139  	// - Unmarshal medatada
   140  	if block.Metadata == nil || len(block.Metadata.Metadata) == 0 {
   141  		return fmt.Errorf("Block with id [%d] on channel [%s] does not have metadata. Block not valid.", block.Header.Number, chainID)
   142  	}
   143  
   144  	metadata, err := utils.GetMetadataFromBlock(block, pcommon.BlockMetadataIndex_SIGNATURES)
   145  	if err != nil {
   146  		return fmt.Errorf("Failed unmarshalling medatata for signatures [%s]", err)
   147  	}
   148  
   149  	// - Verify that Header.DataHash is equal to the hash of block.Data
   150  	// This is to ensure that the header is consistent with the data carried by this block
   151  	if !bytes.Equal(block.Data.Hash(), block.Header.DataHash) {
   152  		return fmt.Errorf("Header.DataHash is different from Hash(block.Data) for block with id [%d] on channel [%s]", block.Header.Number, chainID)
   153  	}
   154  
   155  	// - Get Policy for block validation
   156  
   157  	// Get the policy manager for channelID
   158  	cpm, ok := s.channelPolicyManagerGetter.Manager(channelID)
   159  	if cpm == nil {
   160  		return fmt.Errorf("Could not acquire policy manager for channel %s", channelID)
   161  	}
   162  	// ok is true if it was the manager requested, or false if it is the default manager
   163  	logger.Debugf("Got policy manager for channel [%s] with flag [%s]", channelID, ok)
   164  
   165  	// Get block validation policy
   166  	policy, ok := cpm.GetPolicy(policies.BlockValidation)
   167  	// ok is true if it was the policy requested, or false if it is the default policy
   168  	logger.Debugf("Got block validation policy for channel [%s] with flag [%s]", channelID, ok)
   169  
   170  	// - Prepare SignedData
   171  	signatureSet := []*pcommon.SignedData{}
   172  	for _, metadataSignature := range metadata.Signatures {
   173  		shdr, err := utils.GetSignatureHeader(metadataSignature.SignatureHeader)
   174  		if err != nil {
   175  			return fmt.Errorf("Failed unmarshalling signature header for block with id [%d] on channel [%s]: [%s]", block.Header.Number, chainID, err)
   176  		}
   177  		signatureSet = append(
   178  			signatureSet,
   179  			&pcommon.SignedData{
   180  				Identity:  shdr.Creator,
   181  				Data:      util.ConcatenateBytes(metadata.Value, metadataSignature.SignatureHeader, block.Header.Bytes()),
   182  				Signature: metadataSignature.Signature,
   183  			},
   184  		)
   185  	}
   186  
   187  	// - Evaluate policy
   188  	return policy.Evaluate(signatureSet)
   189  }
   190  
   191  // Sign signs msg with this peer's signing key and outputs
   192  // the signature if no error occurred.
   193  func (s *mspMessageCryptoService) Sign(msg []byte) ([]byte, error) {
   194  	return s.localSigner.Sign(msg)
   195  }
   196  
   197  // Verify checks that signature is a valid signature of message under a peer's verification key.
   198  // If the verification succeeded, Verify returns nil meaning no error occurred.
   199  // If peerIdentity is nil, then the verification fails.
   200  func (s *mspMessageCryptoService) Verify(peerIdentity api.PeerIdentityType, signature, message []byte) error {
   201  	identity, chainID, err := s.getValidatedIdentity(peerIdentity)
   202  	if err != nil {
   203  		logger.Errorf("Failed getting validated identity from peer identity [%s]", err)
   204  
   205  		return err
   206  	}
   207  
   208  	if len(chainID) == 0 {
   209  		// At this stage, this means that peerIdentity
   210  		// belongs to this peer's LocalMSP.
   211  		// The signature is validated directly
   212  		return identity.Verify(message, signature)
   213  	}
   214  
   215  	// At this stage, the signature must be validated
   216  	// against the reader policy of the channel
   217  	// identified by chainID
   218  
   219  	return s.VerifyByChannel(chainID, peerIdentity, signature, message)
   220  }
   221  
   222  // VerifyByChannel checks that signature is a valid signature of message
   223  // under a peer's verification key, but also in the context of a specific channel.
   224  // If the verification succeeded, Verify returns nil meaning no error occurred.
   225  // If peerIdentity is nil, then the verification fails.
   226  func (s *mspMessageCryptoService) VerifyByChannel(chainID common.ChainID, peerIdentity api.PeerIdentityType, signature, message []byte) error {
   227  	// Validate arguments
   228  	if len(peerIdentity) == 0 {
   229  		return errors.New("Invalid Peer Identity. It must be different from nil.")
   230  	}
   231  
   232  	// Get the policy manager for channel chainID
   233  	cpm, flag := s.channelPolicyManagerGetter.Manager(string(chainID))
   234  	if cpm == nil {
   235  		return fmt.Errorf("Could not acquire policy manager for channel %s", string(chainID))
   236  	}
   237  	logger.Debugf("Got policy manager for channel [%s] with flag [%s]", string(chainID), flag)
   238  
   239  	// Get channel reader policy
   240  	policy, flag := cpm.GetPolicy(policies.ChannelApplicationReaders)
   241  	logger.Debugf("Got reader policy for channel [%s] with flag [%s]", string(chainID), flag)
   242  
   243  	return policy.Evaluate(
   244  		[]*pcommon.SignedData{{
   245  			Data:      message,
   246  			Identity:  []byte(peerIdentity),
   247  			Signature: signature,
   248  		}},
   249  	)
   250  }
   251  
   252  func (s *mspMessageCryptoService) getValidatedIdentity(peerIdentity api.PeerIdentityType) (msp.Identity, common.ChainID, error) {
   253  	// Validate arguments
   254  	if len(peerIdentity) == 0 {
   255  		return nil, nil, errors.New("Invalid Peer Identity. It must be different from nil.")
   256  	}
   257  
   258  	// Notice that peerIdentity is assumed to be the serialization of an identity.
   259  	// So, first step is the identity deserialization and then verify it.
   260  
   261  	// First check against the local MSP.
   262  	// If the peerIdentity is in the same organization of this node then
   263  	// the local MSP is required to take the final decision on the validity
   264  	// of the signature.
   265  	identity, err := s.deserializer.GetLocalDeserializer().DeserializeIdentity([]byte(peerIdentity))
   266  	if err == nil {
   267  		// No error means that the local MSP successfully deserialized the identity.
   268  		// We now check additional properties.
   269  
   270  		// TODO: The following check will be replaced by a check on the organizational units
   271  		// when we allow the gossip network to have organization unit (MSP subdivisions)
   272  		// scoped messages.
   273  		// The following check is consistent with the SecurityAdvisor#OrgByPeerIdentity
   274  		// implementation.
   275  		// TODO: Notice that the following check saves us from the fact
   276  		// that DeserializeIdentity does not yet enforce MSP-IDs consistency.
   277  		// This check can be removed once DeserializeIdentity will be fixed.
   278  		if identity.GetMSPIdentifier() == s.deserializer.GetLocalMSPIdentifier() {
   279  			// Check identity validity
   280  
   281  			// Notice that at this stage we don't have to check the identity
   282  			// against any channel's policies.
   283  			// This will be done by the caller function, if needed.
   284  			return identity, nil, identity.Validate()
   285  		}
   286  	}
   287  
   288  	// Check against managers
   289  	for chainID, mspManager := range s.deserializer.GetChannelDeserializers() {
   290  		// Deserialize identity
   291  		identity, err := mspManager.DeserializeIdentity([]byte(peerIdentity))
   292  		if err != nil {
   293  			logger.Debugf("Failed deserialization identity [% x] on [%s]: [%s]", peerIdentity, chainID, err)
   294  			continue
   295  		}
   296  
   297  		// Check identity validity
   298  		// Notice that at this stage we don't have to check the identity
   299  		// against any channel's policies.
   300  		// This will be done by the caller function, if needed.
   301  
   302  		if err := identity.Validate(); err != nil {
   303  			logger.Debugf("Failed validating identity [% x] on [%s]: [%s]", peerIdentity, chainID, err)
   304  			continue
   305  		}
   306  
   307  		logger.Debugf("Validation succeeded [% x] on [%s]", peerIdentity, chainID)
   308  
   309  		return identity, common.ChainID(chainID), nil
   310  	}
   311  
   312  	return nil, nil, fmt.Errorf("Peer Identity [% x] cannot be validated. No MSP found able to do that.", peerIdentity)
   313  }