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