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  }