github.com/darrenli6/fabric-sdk-example@v0.0.0-20220109053535-94b13b56df8c/msp/identities.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package msp 8 9 import ( 10 "crypto" 11 "crypto/rand" 12 "crypto/x509" 13 "encoding/hex" 14 "encoding/pem" 15 "errors" 16 "fmt" 17 18 "github.com/golang/protobuf/proto" 19 "github.com/hyperledger/fabric/bccsp" 20 "github.com/hyperledger/fabric/common/flogging" 21 "github.com/hyperledger/fabric/protos/msp" 22 "github.com/op/go-logging" 23 ) 24 25 var mspIdentityLogger = flogging.MustGetLogger("msp/identity") 26 27 type identity struct { 28 // id contains the identifier (MSPID and identity identifier) for this instance 29 id *IdentityIdentifier 30 31 // cert contains the x.509 certificate that signs the public key of this instance 32 cert *x509.Certificate 33 34 // this is the public key of this instance 35 pk bccsp.Key 36 37 // reference to the MSP that "owns" this identity 38 msp *bccspmsp 39 } 40 41 func newIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) (Identity, error) { 42 mspIdentityLogger.Debugf("Creating identity instance for ID %s", certToPEM(cert)) 43 44 // Sanitize first the certificate 45 cert, err := msp.sanitizeCert(cert) 46 if err != nil { 47 return nil, err 48 } 49 return &identity{id: id, cert: cert, pk: pk, msp: msp}, nil 50 } 51 52 // SatisfiesPrincipal returns null if this instance matches the supplied principal or an error otherwise 53 func (id *identity) SatisfiesPrincipal(principal *msp.MSPPrincipal) error { 54 return id.msp.SatisfiesPrincipal(id, principal) 55 } 56 57 // GetIdentifier returns the identifier (MSPID/IDID) for this instance 58 func (id *identity) GetIdentifier() *IdentityIdentifier { 59 return id.id 60 } 61 62 // GetMSPIdentifier returns the MSP identifier for this instance 63 func (id *identity) GetMSPIdentifier() string { 64 return id.id.Mspid 65 } 66 67 // IsValid returns nil if this instance is a valid identity or an error otherwise 68 func (id *identity) Validate() error { 69 return id.msp.Validate(id) 70 } 71 72 // GetOrganizationalUnits returns the OU for this instance 73 func (id *identity) GetOrganizationalUnits() []*OUIdentifier { 74 if id.cert == nil { 75 return nil 76 } 77 78 cid, err := id.msp.getCertificationChainIdentifier(id) 79 if err != nil { 80 mspIdentityLogger.Errorf("Failed getting certification chain identifier for [%v]: [%s]", id, err) 81 82 return nil 83 } 84 85 res := []*OUIdentifier{} 86 for _, unit := range id.cert.Subject.OrganizationalUnit { 87 res = append(res, &OUIdentifier{ 88 OrganizationalUnitIdentifier: unit, 89 CertifiersIdentifier: cid, 90 }) 91 } 92 93 return res 94 } 95 96 // NewSerializedIdentity returns a serialized identity 97 // having as content the passed mspID and x509 certificate in PEM format. 98 // This method does not check the validity of certificate nor 99 // any consistency of the mspID with it. 100 func NewSerializedIdentity(mspID string, certPEM []byte) ([]byte, error) { 101 // We serialize identities by prepending the MSPID 102 // and appending the x509 cert in PEM format 103 sId := &msp.SerializedIdentity{Mspid: mspID, IdBytes: certPEM} 104 raw, err := proto.Marshal(sId) 105 if err != nil { 106 return nil, fmt.Errorf("Failed serializing identity [%s][% X]: [%s]", mspID, certPEM, err) 107 } 108 return raw, nil 109 } 110 111 // Verify checks against a signature and a message 112 // to determine whether this identity produced the 113 // signature; it returns nil if so or an error otherwise 114 func (id *identity) Verify(msg []byte, sig []byte) error { 115 // mspIdentityLogger.Infof("Verifying signature") 116 117 // Compute Hash 118 hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily) 119 if err != nil { 120 return fmt.Errorf("Failed getting hash function options [%s]", err) 121 } 122 123 digest, err := id.msp.bccsp.Hash(msg, hashOpt) 124 if err != nil { 125 return fmt.Errorf("Failed computing digest [%s]", err) 126 } 127 128 if mspIdentityLogger.IsEnabledFor(logging.DEBUG) { 129 mspIdentityLogger.Debugf("Verify: digest = %s", hex.Dump(digest)) 130 mspIdentityLogger.Debugf("Verify: sig = %s", hex.Dump(sig)) 131 } 132 133 valid, err := id.msp.bccsp.Verify(id.pk, sig, digest, nil) 134 if err != nil { 135 return fmt.Errorf("Could not determine the validity of the signature, err %s", err) 136 } else if !valid { 137 return errors.New("The signature is invalid") 138 } 139 140 return nil 141 } 142 143 // Serialize returns a byte array representation of this identity 144 func (id *identity) Serialize() ([]byte, error) { 145 // mspIdentityLogger.Infof("Serializing identity %s", id.id) 146 147 pb := &pem.Block{Bytes: id.cert.Raw} 148 pemBytes := pem.EncodeToMemory(pb) 149 if pemBytes == nil { 150 return nil, fmt.Errorf("Encoding of identitiy failed") 151 } 152 153 // We serialize identities by prepending the MSPID and appending the ASN.1 DER content of the cert 154 sId := &msp.SerializedIdentity{Mspid: id.id.Mspid, IdBytes: pemBytes} 155 idBytes, err := proto.Marshal(sId) 156 if err != nil { 157 return nil, fmt.Errorf("Could not marshal a SerializedIdentity structure for identity %s, err %s", id.id, err) 158 } 159 160 return idBytes, nil 161 } 162 163 func (id *identity) getHashOpt(hashFamily string) (bccsp.HashOpts, error) { 164 switch hashFamily { 165 case bccsp.SHA2: 166 return bccsp.GetHashOpt(bccsp.SHA256) 167 case bccsp.SHA3: 168 return bccsp.GetHashOpt(bccsp.SHA3_256) 169 } 170 return nil, fmt.Errorf("hash famility not recognized [%s]", hashFamily) 171 } 172 173 type signingidentity struct { 174 // we embed everything from a base identity 175 identity 176 177 // signer corresponds to the object that can produce signatures from this identity 178 signer crypto.Signer 179 } 180 181 func newSigningIdentity(id *IdentityIdentifier, cert *x509.Certificate, pk bccsp.Key, signer crypto.Signer, msp *bccspmsp) (SigningIdentity, error) { 182 //mspIdentityLogger.Infof("Creating signing identity instance for ID %s", id) 183 mspId, err := newIdentity(id, cert, pk, msp) 184 if err != nil { 185 return nil, err 186 } 187 return &signingidentity{identity: *mspId.(*identity), signer: signer}, nil 188 } 189 190 // Sign produces a signature over msg, signed by this instance 191 func (id *signingidentity) Sign(msg []byte) ([]byte, error) { 192 //mspIdentityLogger.Infof("Signing message") 193 194 // Compute Hash 195 hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily) 196 if err != nil { 197 return nil, fmt.Errorf("Failed getting hash function options [%s]", err) 198 } 199 200 digest, err := id.msp.bccsp.Hash(msg, hashOpt) 201 if err != nil { 202 return nil, fmt.Errorf("Failed computing digest [%s]", err) 203 } 204 205 if len(msg) < 32 { 206 mspIdentityLogger.Debugf("Sign: plaintext: %X \n", msg) 207 } else { 208 mspIdentityLogger.Debugf("Sign: plaintext: %X...%X \n", msg[0:16], msg[len(msg)-16:]) 209 } 210 mspIdentityLogger.Debugf("Sign: digest: %X \n", digest) 211 212 // Sign 213 return id.signer.Sign(rand.Reader, digest, nil) 214 } 215 216 func (id *signingidentity) GetPublicVersion() Identity { 217 return &id.identity 218 }