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  }