github.com/Hnampk/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 }