github.com/yacovm/fabric@v2.0.0-alpha.0.20191128145320-c5d4087dc723+incompatible/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 "sync" 16 "time" 17 18 "github.com/golang/protobuf/proto" 19 "github.com/hyperledger/fabric-protos-go/msp" 20 "github.com/hyperledger/fabric/bccsp" 21 "github.com/hyperledger/fabric/common/flogging" 22 "github.com/pkg/errors" 23 "go.uber.org/zap/zapcore" 24 ) 25 26 var mspIdentityLogger = flogging.MustGetLogger("msp.identity") 27 28 type identity struct { 29 // id contains the identifier (MSPID and identity identifier) for this instance 30 id *IdentityIdentifier 31 32 // cert contains the x.509 certificate that signs the public key of this instance 33 cert *x509.Certificate 34 35 // this is the public key of this instance 36 pk bccsp.Key 37 38 // reference to the MSP that "owns" this identity 39 msp *bccspmsp 40 41 // validationMutex is used to synchronise memory operation 42 // over validated and validationErr 43 validationMutex sync.Mutex 44 45 // validated is true when the validateIdentity function 46 // has been called on this instance 47 validated bool 48 49 // validationErr contains the validation error for this 50 // instance. It can be read if validated is true 51 validationErr error 52 } 53 54 func newIdentity(cert *x509.Certificate, pk bccsp.Key, msp *bccspmsp) (Identity, error) { 55 if mspIdentityLogger.IsEnabledFor(zapcore.DebugLevel) { 56 mspIdentityLogger.Debugf("Creating identity instance for cert %s", certToPEM(cert)) 57 } 58 59 // Sanitize first the certificate 60 cert, err := msp.sanitizeCert(cert) 61 if err != nil { 62 return nil, err 63 } 64 65 // Compute identity identifier 66 67 // Use the hash of the identity's certificate as id in the IdentityIdentifier 68 hashOpt, err := bccsp.GetHashOpt(msp.cryptoConfig.IdentityIdentifierHashFunction) 69 if err != nil { 70 return nil, errors.WithMessage(err, "failed getting hash function options") 71 } 72 73 digest, err := msp.bccsp.Hash(cert.Raw, hashOpt) 74 if err != nil { 75 return nil, errors.WithMessage(err, "failed hashing raw certificate to compute the id of the IdentityIdentifier") 76 } 77 78 id := &IdentityIdentifier{ 79 Mspid: msp.name, 80 Id: hex.EncodeToString(digest)} 81 82 return &identity{id: id, cert: cert, pk: pk, msp: msp}, nil 83 } 84 85 // ExpiresAt returns the time at which the Identity expires. 86 func (id *identity) ExpiresAt() time.Time { 87 return id.cert.NotAfter 88 } 89 90 // SatisfiesPrincipal returns nil if this instance matches the supplied principal or an error otherwise 91 func (id *identity) SatisfiesPrincipal(principal *msp.MSPPrincipal) error { 92 return id.msp.SatisfiesPrincipal(id, principal) 93 } 94 95 // GetIdentifier returns the identifier (MSPID/IDID) for this instance 96 func (id *identity) GetIdentifier() *IdentityIdentifier { 97 return id.id 98 } 99 100 // GetMSPIdentifier returns the MSP identifier for this instance 101 func (id *identity) GetMSPIdentifier() string { 102 return id.id.Mspid 103 } 104 105 // Validate returns nil if this instance is a valid identity or an error otherwise 106 func (id *identity) Validate() error { 107 return id.msp.Validate(id) 108 } 109 110 // GetOrganizationalUnits returns the OU for this instance 111 func (id *identity) GetOrganizationalUnits() []*OUIdentifier { 112 if id.cert == nil { 113 return nil 114 } 115 116 cid, err := id.msp.getCertificationChainIdentifier(id) 117 if err != nil { 118 mspIdentityLogger.Errorf("Failed getting certification chain identifier for [%v]: [%+v]", id, err) 119 120 return nil 121 } 122 123 res := []*OUIdentifier{} 124 for _, unit := range id.cert.Subject.OrganizationalUnit { 125 res = append(res, &OUIdentifier{ 126 OrganizationalUnitIdentifier: unit, 127 CertifiersIdentifier: cid, 128 }) 129 } 130 131 return res 132 } 133 134 // Anonymous returns true if this identity provides anonymity 135 func (id *identity) Anonymous() bool { 136 return false 137 } 138 139 // NewSerializedIdentity returns a serialized identity 140 // having as content the passed mspID and x509 certificate in PEM format. 141 // This method does not check the validity of certificate nor 142 // any consistency of the mspID with it. 143 func NewSerializedIdentity(mspID string, certPEM []byte) ([]byte, error) { 144 // We serialize identities by prepending the MSPID 145 // and appending the x509 cert in PEM format 146 sId := &msp.SerializedIdentity{Mspid: mspID, IdBytes: certPEM} 147 raw, err := proto.Marshal(sId) 148 if err != nil { 149 return nil, errors.Wrapf(err, "failed serializing identity [%s][%X]", mspID, certPEM) 150 } 151 return raw, nil 152 } 153 154 // Verify checks against a signature and a message 155 // to determine whether this identity produced the 156 // signature; it returns nil if so or an error otherwise 157 func (id *identity) Verify(msg []byte, sig []byte) error { 158 // mspIdentityLogger.Infof("Verifying signature") 159 160 // Compute Hash 161 hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily) 162 if err != nil { 163 return errors.WithMessage(err, "failed getting hash function options") 164 } 165 166 digest, err := id.msp.bccsp.Hash(msg, hashOpt) 167 if err != nil { 168 return errors.WithMessage(err, "failed computing digest") 169 } 170 171 if mspIdentityLogger.IsEnabledFor(zapcore.DebugLevel) { 172 mspIdentityLogger.Debugf("Verify: digest = %s", hex.Dump(digest)) 173 mspIdentityLogger.Debugf("Verify: sig = %s", hex.Dump(sig)) 174 } 175 176 valid, err := id.msp.bccsp.Verify(id.pk, sig, digest, nil) 177 if err != nil { 178 return errors.WithMessage(err, "could not determine the validity of the signature") 179 } else if !valid { 180 return errors.New("The signature is invalid") 181 } 182 183 return nil 184 } 185 186 // Serialize returns a byte array representation of this identity 187 func (id *identity) Serialize() ([]byte, error) { 188 // mspIdentityLogger.Infof("Serializing identity %s", id.id) 189 190 pb := &pem.Block{Bytes: id.cert.Raw, Type: "CERTIFICATE"} 191 pemBytes := pem.EncodeToMemory(pb) 192 if pemBytes == nil { 193 return nil, errors.New("encoding of identity failed") 194 } 195 196 // We serialize identities by prepending the MSPID and appending the ASN.1 DER content of the cert 197 sId := &msp.SerializedIdentity{Mspid: id.id.Mspid, IdBytes: pemBytes} 198 idBytes, err := proto.Marshal(sId) 199 if err != nil { 200 return nil, errors.Wrapf(err, "could not marshal a SerializedIdentity structure for identity %s", id.id) 201 } 202 203 return idBytes, nil 204 } 205 206 func (id *identity) getHashOpt(hashFamily string) (bccsp.HashOpts, error) { 207 switch hashFamily { 208 case bccsp.SHA2: 209 return bccsp.GetHashOpt(bccsp.SHA256) 210 case bccsp.SHA3: 211 return bccsp.GetHashOpt(bccsp.SHA3_256) 212 } 213 return nil, errors.Errorf("hash familiy not recognized [%s]", hashFamily) 214 } 215 216 type signingidentity struct { 217 // we embed everything from a base identity 218 identity 219 220 // signer corresponds to the object that can produce signatures from this identity 221 signer crypto.Signer 222 } 223 224 func newSigningIdentity(cert *x509.Certificate, pk bccsp.Key, signer crypto.Signer, msp *bccspmsp) (SigningIdentity, error) { 225 //mspIdentityLogger.Infof("Creating signing identity instance for ID %s", id) 226 mspId, err := newIdentity(cert, pk, msp) 227 if err != nil { 228 return nil, err 229 } 230 return &signingidentity{ 231 identity: identity{ 232 id: mspId.(*identity).id, 233 cert: mspId.(*identity).cert, 234 msp: mspId.(*identity).msp, 235 pk: mspId.(*identity).pk, 236 }, 237 signer: signer, 238 }, nil 239 } 240 241 // Sign produces a signature over msg, signed by this instance 242 func (id *signingidentity) Sign(msg []byte) ([]byte, error) { 243 //mspIdentityLogger.Infof("Signing message") 244 245 // Compute Hash 246 hashOpt, err := id.getHashOpt(id.msp.cryptoConfig.SignatureHashFamily) 247 if err != nil { 248 return nil, errors.WithMessage(err, "failed getting hash function options") 249 } 250 251 digest, err := id.msp.bccsp.Hash(msg, hashOpt) 252 if err != nil { 253 return nil, errors.WithMessage(err, "failed computing digest") 254 } 255 256 if len(msg) < 32 { 257 mspIdentityLogger.Debugf("Sign: plaintext: %X \n", msg) 258 } else { 259 mspIdentityLogger.Debugf("Sign: plaintext: %X...%X \n", msg[0:16], msg[len(msg)-16:]) 260 } 261 mspIdentityLogger.Debugf("Sign: digest: %X \n", digest) 262 263 // Sign 264 return id.signer.Sign(rand.Reader, digest, nil) 265 } 266 267 // GetPublicVersion returns the public version of this identity, 268 // namely, the one that is only able to verify messages and not sign them 269 func (id *signingidentity) GetPublicVersion() Identity { 270 return &id.identity 271 }