github.com/lzy4123/fabric@v2.1.1+incompatible/gossip/api/crypto.go (about)

     1  /*
     2  Copyright IBM Corp. All Rights Reserved.
     3  
     4  SPDX-License-Identifier: Apache-2.0
     5  */
     6  
     7  package api
     8  
     9  import (
    10  	"crypto/x509"
    11  	"encoding/base64"
    12  	"encoding/json"
    13  	"encoding/pem"
    14  	"fmt"
    15  	"time"
    16  
    17  	"github.com/golang/protobuf/proto"
    18  	cb "github.com/hyperledger/fabric-protos-go/common"
    19  	"github.com/hyperledger/fabric-protos-go/msp"
    20  	"github.com/hyperledger/fabric/gossip/common"
    21  	"google.golang.org/grpc"
    22  )
    23  
    24  // MessageCryptoService is the contract between the gossip component and the
    25  // peer's cryptographic layer and is used by the gossip component to verify,
    26  // and authenticate remote peers and data they send, as well as to verify
    27  // received blocks from the ordering service.
    28  type MessageCryptoService interface {
    29  	// GetPKIidOfCert returns the PKI-ID of a peer's identity
    30  	// If any error occurs, the method return nil
    31  	// This method does not validate peerIdentity.
    32  	// This validation is supposed to be done appropriately during the execution flow.
    33  	GetPKIidOfCert(peerIdentity PeerIdentityType) common.PKIidType
    34  
    35  	// VerifyBlock returns nil if the block is properly signed, and the claimed seqNum is the
    36  	// sequence number that the block's header contains.
    37  	// else returns error
    38  	VerifyBlock(channelID common.ChannelID, seqNum uint64, block *cb.Block) error
    39  
    40  	// Sign signs msg with this peer's signing key and outputs
    41  	// the signature if no error occurred.
    42  	Sign(msg []byte) ([]byte, error)
    43  
    44  	// Verify checks that signature is a valid signature of message under a peer's verification key.
    45  	// If the verification succeeded, Verify returns nil meaning no error occurred.
    46  	// If peerIdentity is nil, then the verification fails.
    47  	Verify(peerIdentity PeerIdentityType, signature, message []byte) error
    48  
    49  	// VerifyByChannel checks that signature is a valid signature of message
    50  	// under a peer's verification key, but also in the context of a specific channel.
    51  	// If the verification succeeded, Verify returns nil meaning no error occurred.
    52  	// If peerIdentity is nil, then the verification fails.
    53  	VerifyByChannel(channelID common.ChannelID, peerIdentity PeerIdentityType, signature, message []byte) error
    54  
    55  	// ValidateIdentity validates the identity of a remote peer.
    56  	// If the identity is invalid, revoked, expired it returns an error.
    57  	// Else, returns nil
    58  	ValidateIdentity(peerIdentity PeerIdentityType) error
    59  
    60  	// Expiration returns:
    61  	// - The time when the identity expires, nil
    62  	//   In case it can expire
    63  	// - A zero value time.Time, nil
    64  	//   in case it cannot expire
    65  	// - A zero value, error in case it cannot be
    66  	//   determined if the identity can expire or not
    67  	Expiration(peerIdentity PeerIdentityType) (time.Time, error)
    68  }
    69  
    70  // PeerIdentityInfo aggregates a peer's identity,
    71  // and also additional metadata about it
    72  type PeerIdentityInfo struct {
    73  	PKIId        common.PKIidType
    74  	Identity     PeerIdentityType
    75  	Organization OrgIdentityType
    76  }
    77  
    78  // PeerIdentitySet aggregates a PeerIdentityInfo slice
    79  type PeerIdentitySet []PeerIdentityInfo
    80  
    81  // PeerIdentityFilter defines predicate function used to filter
    82  // peer identities
    83  type PeerIdentityFilter func(info PeerIdentityInfo) bool
    84  
    85  // ByOrg sorts the PeerIdentitySet by organizations of its peers
    86  func (pis PeerIdentitySet) ByOrg() map[string]PeerIdentitySet {
    87  	m := make(map[string]PeerIdentitySet)
    88  	for _, id := range pis {
    89  		m[string(id.Organization)] = append(m[string(id.Organization)], id)
    90  	}
    91  	return m
    92  }
    93  
    94  // ByID sorts the PeerIdentitySet by PKI-IDs of its peers
    95  func (pis PeerIdentitySet) ByID() map[string]PeerIdentityInfo {
    96  	m := make(map[string]PeerIdentityInfo)
    97  	for _, id := range pis {
    98  		m[string(id.PKIId)] = id
    99  	}
   100  	return m
   101  }
   102  
   103  // Filter filters identities based on predicate, returns new  PeerIdentitySet
   104  // with filtered ids.
   105  func (pis PeerIdentitySet) Filter(filter PeerIdentityFilter) PeerIdentitySet {
   106  	var result PeerIdentitySet
   107  	for _, id := range pis {
   108  		if filter(id) {
   109  			result = append(result, id)
   110  		}
   111  	}
   112  	return result
   113  }
   114  
   115  // PeerIdentityType is the peer's certificate
   116  type PeerIdentityType []byte
   117  
   118  // String returns a string representation of this PeerIdentityType
   119  func (pit PeerIdentityType) String() string {
   120  	base64Representation := base64.StdEncoding.EncodeToString(pit)
   121  	sID := &msp.SerializedIdentity{}
   122  	err := proto.Unmarshal(pit, sID)
   123  	if err != nil {
   124  		return fmt.Sprintf("non SerializedIdentity: %s", base64Representation)
   125  	}
   126  
   127  	bl, _ := pem.Decode(sID.IdBytes)
   128  	if bl == nil {
   129  		return fmt.Sprintf("non PEM encoded identity: %s", base64Representation)
   130  	}
   131  
   132  	cert, _ := x509.ParseCertificate(bl.Bytes)
   133  	if cert == nil {
   134  		return fmt.Sprintf("non x509 identity: %s", base64Representation)
   135  	}
   136  	m := make(map[string]interface{})
   137  	m["MSP"] = sID.Mspid
   138  	s := cert.Subject
   139  	m["CN"] = s.CommonName
   140  	m["OU"] = s.OrganizationalUnit
   141  	m["L-ST-C"] = fmt.Sprintf("%s-%s-%s", s.Locality, s.StreetAddress, s.Country)
   142  	i := cert.Issuer
   143  	m["Issuer-CN"] = i.CommonName
   144  	m["Issuer-OU"] = i.OrganizationalUnit
   145  	m["Issuer-L-ST-C"] = fmt.Sprintf("%s-%s-%s", i.Locality, i.StreetAddress, i.Country)
   146  
   147  	rawJSON, err := json.Marshal(m)
   148  	if err != nil {
   149  		return base64Representation
   150  	}
   151  	return string(rawJSON)
   152  }
   153  
   154  // PeerSuspector returns whether a peer with a given identity is suspected
   155  // as being revoked, or its CA is revoked
   156  type PeerSuspector func(identity PeerIdentityType) bool
   157  
   158  // PeerSecureDialOpts returns the gRPC DialOptions to use for connection level
   159  // security when communicating with remote peer endpoints
   160  type PeerSecureDialOpts func() []grpc.DialOption
   161  
   162  // PeerSignature defines a signature of a peer
   163  // on a given message
   164  type PeerSignature struct {
   165  	Signature    []byte
   166  	Message      []byte
   167  	PeerIdentity PeerIdentityType
   168  }