github.com/zhouxv/fabric@v2.1.1+incompatible/msp/idemixmsp.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  	"bytes"
    11  	"encoding/hex"
    12  	"fmt"
    13  	"time"
    14  
    15  	"github.com/golang/protobuf/proto"
    16  	m "github.com/hyperledger/fabric-protos-go/msp"
    17  	"github.com/hyperledger/fabric/bccsp"
    18  	idemixbccsp "github.com/hyperledger/fabric/bccsp/idemix"
    19  	"github.com/hyperledger/fabric/bccsp/sw"
    20  	"github.com/pkg/errors"
    21  	"go.uber.org/zap/zapcore"
    22  )
    23  
    24  const (
    25  	// AttributeIndexOU contains the index of the OU attribute in the idemix credential attributes
    26  	AttributeIndexOU = iota
    27  
    28  	// AttributeIndexRole contains the index of the Role attribute in the idemix credential attributes
    29  	AttributeIndexRole
    30  
    31  	// AttributeIndexEnrollmentId contains the index of the Enrollment ID attribute in the idemix credential attributes
    32  	AttributeIndexEnrollmentId
    33  
    34  	// AttributeIndexRevocationHandle contains the index of the Revocation Handle attribute in the idemix credential attributes
    35  	AttributeIndexRevocationHandle
    36  )
    37  
    38  const (
    39  	// AttributeNameOU is the attribute name of the Organization Unit attribute
    40  	AttributeNameOU = "OU"
    41  
    42  	// AttributeNameRole is the attribute name of the Role attribute
    43  	AttributeNameRole = "Role"
    44  
    45  	// AttributeNameEnrollmentId is the attribute name of the Enrollment ID attribute
    46  	AttributeNameEnrollmentId = "EnrollmentID"
    47  
    48  	// AttributeNameRevocationHandle is the attribute name of the revocation handle attribute
    49  	AttributeNameRevocationHandle = "RevocationHandle"
    50  )
    51  
    52  // index of the revocation handle attribute in the credential
    53  const rhIndex = 3
    54  
    55  type idemixmsp struct {
    56  	csp          bccsp.BCCSP
    57  	version      MSPVersion
    58  	ipk          bccsp.Key
    59  	signer       *idemixSigningIdentity
    60  	name         string
    61  	revocationPK bccsp.Key
    62  	epoch        int
    63  }
    64  
    65  // newIdemixMsp creates a new instance of idemixmsp
    66  func newIdemixMsp(version MSPVersion) (MSP, error) {
    67  	mspLogger.Debugf("Creating Idemix-based MSP instance")
    68  
    69  	csp, err := idemixbccsp.New(sw.NewDummyKeyStore())
    70  	if err != nil {
    71  		panic(fmt.Sprintf("unexpected condition, error received [%s]", err))
    72  	}
    73  
    74  	msp := idemixmsp{csp: csp}
    75  	msp.version = version
    76  	return &msp, nil
    77  }
    78  
    79  func (msp *idemixmsp) Setup(conf1 *m.MSPConfig) error {
    80  	mspLogger.Debugf("Setting up Idemix-based MSP instance")
    81  
    82  	if conf1 == nil {
    83  		return errors.Errorf("setup error: nil conf reference")
    84  	}
    85  
    86  	if conf1.Type != int32(IDEMIX) {
    87  		return errors.Errorf("setup error: config is not of type IDEMIX")
    88  	}
    89  
    90  	var conf m.IdemixMSPConfig
    91  	err := proto.Unmarshal(conf1.Config, &conf)
    92  	if err != nil {
    93  		return errors.Wrap(err, "failed unmarshalling idemix msp config")
    94  	}
    95  
    96  	msp.name = conf.Name
    97  	mspLogger.Debugf("Setting up Idemix MSP instance %s", msp.name)
    98  
    99  	// Import Issuer Public Key
   100  	IssuerPublicKey, err := msp.csp.KeyImport(
   101  		conf.Ipk,
   102  		&bccsp.IdemixIssuerPublicKeyImportOpts{
   103  			Temporary: true,
   104  			AttributeNames: []string{
   105  				AttributeNameOU,
   106  				AttributeNameRole,
   107  				AttributeNameEnrollmentId,
   108  				AttributeNameRevocationHandle,
   109  			},
   110  		})
   111  	if err != nil {
   112  		importErr, ok := errors.Cause(err).(*bccsp.IdemixIssuerPublicKeyImporterError)
   113  		if !ok {
   114  			panic("unexpected condition, BCCSP did not return the expected *bccsp.IdemixIssuerPublicKeyImporterError")
   115  		}
   116  		switch importErr.Type {
   117  		case bccsp.IdemixIssuerPublicKeyImporterUnmarshallingError:
   118  			return errors.WithMessage(err, "failed to unmarshal ipk from idemix msp config")
   119  		case bccsp.IdemixIssuerPublicKeyImporterHashError:
   120  			return errors.WithMessage(err, "setting the hash of the issuer public key failed")
   121  		case bccsp.IdemixIssuerPublicKeyImporterValidationError:
   122  			return errors.WithMessage(err, "cannot setup idemix msp with invalid public key")
   123  		case bccsp.IdemixIssuerPublicKeyImporterNumAttributesError:
   124  			fallthrough
   125  		case bccsp.IdemixIssuerPublicKeyImporterAttributeNameError:
   126  			return errors.Errorf("issuer public key must have have attributes OU, Role, EnrollmentId, and RevocationHandle")
   127  		default:
   128  			panic(fmt.Sprintf("unexpected condtion, issuer public key import error not valid, got [%d]", importErr.Type))
   129  		}
   130  	}
   131  	msp.ipk = IssuerPublicKey
   132  
   133  	// Import revocation public key
   134  	RevocationPublicKey, err := msp.csp.KeyImport(
   135  		conf.RevocationPk,
   136  		&bccsp.IdemixRevocationPublicKeyImportOpts{Temporary: true},
   137  	)
   138  	if err != nil {
   139  		return errors.WithMessage(err, "failed to import revocation public key")
   140  	}
   141  	msp.revocationPK = RevocationPublicKey
   142  
   143  	if conf.Signer == nil {
   144  		// No credential in config, so we don't setup a default signer
   145  		mspLogger.Debug("idemix msp setup as verification only msp (no key material found)")
   146  		return nil
   147  	}
   148  
   149  	// A credential is present in the config, so we setup a default signer
   150  
   151  	// Import User secret key
   152  	UserKey, err := msp.csp.KeyImport(conf.Signer.Sk, &bccsp.IdemixUserSecretKeyImportOpts{Temporary: true})
   153  	if err != nil {
   154  		return errors.WithMessage(err, "failed importing signer secret key")
   155  	}
   156  
   157  	// Derive NymPublicKey
   158  	NymKey, err := msp.csp.KeyDeriv(UserKey, &bccsp.IdemixNymKeyDerivationOpts{Temporary: true, IssuerPK: IssuerPublicKey})
   159  	if err != nil {
   160  		return errors.WithMessage(err, "failed deriving nym")
   161  	}
   162  	NymPublicKey, err := NymKey.PublicKey()
   163  	if err != nil {
   164  		return errors.Wrapf(err, "failed getting public nym key")
   165  	}
   166  
   167  	role := &m.MSPRole{
   168  		MspIdentifier: msp.name,
   169  		Role:          m.MSPRole_MEMBER,
   170  	}
   171  	if checkRole(int(conf.Signer.Role), ADMIN) {
   172  		role.Role = m.MSPRole_ADMIN
   173  	}
   174  
   175  	ou := &m.OrganizationUnit{
   176  		MspIdentifier:                msp.name,
   177  		OrganizationalUnitIdentifier: conf.Signer.OrganizationalUnitIdentifier,
   178  		CertifiersIdentifier:         IssuerPublicKey.SKI(),
   179  	}
   180  
   181  	enrollmentId := conf.Signer.EnrollmentId
   182  
   183  	// Verify credential
   184  	valid, err := msp.csp.Verify(
   185  		UserKey,
   186  		conf.Signer.Cred,
   187  		nil,
   188  		&bccsp.IdemixCredentialSignerOpts{
   189  			IssuerPK: IssuerPublicKey,
   190  			Attributes: []bccsp.IdemixAttribute{
   191  				{Type: bccsp.IdemixBytesAttribute, Value: []byte(conf.Signer.OrganizationalUnitIdentifier)},
   192  				{Type: bccsp.IdemixIntAttribute, Value: getIdemixRoleFromMSPRole(role)},
   193  				{Type: bccsp.IdemixBytesAttribute, Value: []byte(enrollmentId)},
   194  				{Type: bccsp.IdemixHiddenAttribute},
   195  			},
   196  		},
   197  	)
   198  	if err != nil || !valid {
   199  		return errors.WithMessage(err, "Credential is not cryptographically valid")
   200  	}
   201  
   202  	// Create the cryptographic evidence that this identity is valid
   203  	proof, err := msp.csp.Sign(
   204  		UserKey,
   205  		nil,
   206  		&bccsp.IdemixSignerOpts{
   207  			Credential: conf.Signer.Cred,
   208  			Nym:        NymKey,
   209  			IssuerPK:   IssuerPublicKey,
   210  			Attributes: []bccsp.IdemixAttribute{
   211  				{Type: bccsp.IdemixBytesAttribute},
   212  				{Type: bccsp.IdemixIntAttribute},
   213  				{Type: bccsp.IdemixHiddenAttribute},
   214  				{Type: bccsp.IdemixHiddenAttribute},
   215  			},
   216  			RhIndex: rhIndex,
   217  			CRI:     conf.Signer.CredentialRevocationInformation,
   218  		},
   219  	)
   220  	if err != nil {
   221  		return errors.WithMessage(err, "Failed to setup cryptographic proof of identity")
   222  	}
   223  
   224  	// Set up default signer
   225  	msp.signer = &idemixSigningIdentity{
   226  		idemixidentity: newIdemixIdentity(msp, NymPublicKey, role, ou, proof),
   227  		Cred:           conf.Signer.Cred,
   228  		UserKey:        UserKey,
   229  		NymKey:         NymKey,
   230  		enrollmentId:   enrollmentId}
   231  
   232  	return nil
   233  }
   234  
   235  // GetVersion returns the version of this MSP
   236  func (msp *idemixmsp) GetVersion() MSPVersion {
   237  	return msp.version
   238  }
   239  
   240  func (msp *idemixmsp) GetType() ProviderType {
   241  	return IDEMIX
   242  }
   243  
   244  func (msp *idemixmsp) GetIdentifier() (string, error) {
   245  	return msp.name, nil
   246  }
   247  
   248  func (msp *idemixmsp) GetSigningIdentity(identifier *IdentityIdentifier) (SigningIdentity, error) {
   249  	return nil, errors.Errorf("GetSigningIdentity not implemented")
   250  }
   251  
   252  func (msp *idemixmsp) GetDefaultSigningIdentity() (SigningIdentity, error) {
   253  	mspLogger.Debugf("Obtaining default idemix signing identity")
   254  
   255  	if msp.signer == nil {
   256  		return nil, errors.Errorf("no default signer setup")
   257  	}
   258  	return msp.signer, nil
   259  }
   260  
   261  func (msp *idemixmsp) DeserializeIdentity(serializedID []byte) (Identity, error) {
   262  	sID := &m.SerializedIdentity{}
   263  	err := proto.Unmarshal(serializedID, sID)
   264  	if err != nil {
   265  		return nil, errors.Wrap(err, "could not deserialize a SerializedIdentity")
   266  	}
   267  
   268  	if sID.Mspid != msp.name {
   269  		return nil, errors.Errorf("expected MSP ID %s, received %s", msp.name, sID.Mspid)
   270  	}
   271  
   272  	return msp.deserializeIdentityInternal(sID.GetIdBytes())
   273  }
   274  
   275  func (msp *idemixmsp) deserializeIdentityInternal(serializedID []byte) (Identity, error) {
   276  	mspLogger.Debug("idemixmsp: deserializing identity")
   277  	serialized := new(m.SerializedIdemixIdentity)
   278  	err := proto.Unmarshal(serializedID, serialized)
   279  	if err != nil {
   280  		return nil, errors.Wrap(err, "could not deserialize a SerializedIdemixIdentity")
   281  	}
   282  	if serialized.NymX == nil || serialized.NymY == nil {
   283  		return nil, errors.Errorf("unable to deserialize idemix identity: pseudonym is invalid")
   284  	}
   285  
   286  	// Import NymPublicKey
   287  	var rawNymPublicKey []byte
   288  	rawNymPublicKey = append(rawNymPublicKey, serialized.NymX...)
   289  	rawNymPublicKey = append(rawNymPublicKey, serialized.NymY...)
   290  	NymPublicKey, err := msp.csp.KeyImport(
   291  		rawNymPublicKey,
   292  		&bccsp.IdemixNymPublicKeyImportOpts{Temporary: true},
   293  	)
   294  	if err != nil {
   295  		return nil, errors.WithMessage(err, "failed to import nym public key")
   296  	}
   297  
   298  	// OU
   299  	ou := &m.OrganizationUnit{}
   300  	err = proto.Unmarshal(serialized.Ou, ou)
   301  	if err != nil {
   302  		return nil, errors.Wrap(err, "cannot deserialize the OU of the identity")
   303  	}
   304  
   305  	// Role
   306  	role := &m.MSPRole{}
   307  	err = proto.Unmarshal(serialized.Role, role)
   308  	if err != nil {
   309  		return nil, errors.Wrap(err, "cannot deserialize the role of the identity")
   310  	}
   311  
   312  	return newIdemixIdentity(msp, NymPublicKey, role, ou, serialized.Proof), nil
   313  }
   314  
   315  func (msp *idemixmsp) Validate(id Identity) error {
   316  	var identity *idemixidentity
   317  	switch t := id.(type) {
   318  	case *idemixidentity:
   319  		identity = id.(*idemixidentity)
   320  	case *idemixSigningIdentity:
   321  		identity = id.(*idemixSigningIdentity).idemixidentity
   322  	default:
   323  		return errors.Errorf("identity type %T is not recognized", t)
   324  	}
   325  
   326  	mspLogger.Debugf("Validating identity %+v", identity)
   327  	if identity.GetMSPIdentifier() != msp.name {
   328  		return errors.Errorf("the supplied identity does not belong to this msp")
   329  	}
   330  	return identity.verifyProof()
   331  }
   332  
   333  func (id *idemixidentity) verifyProof() error {
   334  	// Verify signature
   335  	valid, err := id.msp.csp.Verify(
   336  		id.msp.ipk,
   337  		id.associationProof,
   338  		nil,
   339  		&bccsp.IdemixSignerOpts{
   340  			RevocationPublicKey: id.msp.revocationPK,
   341  			Attributes: []bccsp.IdemixAttribute{
   342  				{Type: bccsp.IdemixBytesAttribute, Value: []byte(id.OU.OrganizationalUnitIdentifier)},
   343  				{Type: bccsp.IdemixIntAttribute, Value: getIdemixRoleFromMSPRole(id.Role)},
   344  				{Type: bccsp.IdemixHiddenAttribute},
   345  				{Type: bccsp.IdemixHiddenAttribute},
   346  			},
   347  			RhIndex: rhIndex,
   348  			Epoch:   id.msp.epoch,
   349  		},
   350  	)
   351  	if err == nil && !valid {
   352  		panic("unexpected condition, an error should be returned for an invalid signature")
   353  	}
   354  
   355  	return err
   356  }
   357  
   358  func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal) error {
   359  	err := msp.Validate(id)
   360  	if err != nil {
   361  		return errors.Wrap(err, "identity is not valid with respect to this MSP")
   362  	}
   363  
   364  	return msp.satisfiesPrincipalValidated(id, principal)
   365  }
   366  
   367  // satisfiesPrincipalValidated performs all the tasks of satisfiesPrincipal except the identity validation,
   368  // such that combined principals will not cause multiple expensive identity validations.
   369  func (msp *idemixmsp) satisfiesPrincipalValidated(id Identity, principal *m.MSPPrincipal) error {
   370  	switch principal.PrincipalClassification {
   371  	// in this case, we have to check whether the
   372  	// identity has a role in the msp - member or admin
   373  	case m.MSPPrincipal_ROLE:
   374  		// Principal contains the msp role
   375  		mspRole := &m.MSPRole{}
   376  		err := proto.Unmarshal(principal.Principal, mspRole)
   377  		if err != nil {
   378  			return errors.Wrap(err, "could not unmarshal MSPRole from principal")
   379  		}
   380  
   381  		// at first, we check whether the MSP
   382  		// identifier is the same as that of the identity
   383  		if mspRole.MspIdentifier != msp.name {
   384  			return errors.Errorf("the identity is a member of a different MSP (expected %s, got %s)", mspRole.MspIdentifier, id.GetMSPIdentifier())
   385  		}
   386  
   387  		// now we validate the different msp roles
   388  		switch mspRole.Role {
   389  		case m.MSPRole_MEMBER:
   390  			// in the case of member, we simply check
   391  			// whether this identity is valid for the MSP
   392  			mspLogger.Debugf("Checking if identity satisfies MEMBER role for %s", msp.name)
   393  			return nil
   394  		case m.MSPRole_ADMIN:
   395  			mspLogger.Debugf("Checking if identity satisfies ADMIN role for %s", msp.name)
   396  			if id.(*idemixidentity).Role.Role != m.MSPRole_ADMIN {
   397  				return errors.Errorf("user is not an admin")
   398  			}
   399  			return nil
   400  		case m.MSPRole_PEER:
   401  			if msp.version >= MSPv1_3 {
   402  				return errors.Errorf("idemixmsp only supports client use, so it cannot satisfy an MSPRole PEER principal")
   403  			}
   404  			fallthrough
   405  		case m.MSPRole_CLIENT:
   406  			if msp.version >= MSPv1_3 {
   407  				return nil // any valid idemixmsp member must be a client
   408  			}
   409  			fallthrough
   410  		default:
   411  			return errors.Errorf("invalid MSP role type %d", int32(mspRole.Role))
   412  		}
   413  		// in this case we have to serialize this instance
   414  		// and compare it byte-by-byte with Principal
   415  	case m.MSPPrincipal_IDENTITY:
   416  		mspLogger.Debugf("Checking if identity satisfies IDENTITY principal")
   417  		idBytes, err := id.Serialize()
   418  		if err != nil {
   419  			return errors.Wrap(err, "could not serialize this identity instance")
   420  		}
   421  
   422  		rv := bytes.Compare(idBytes, principal.Principal)
   423  		if rv == 0 {
   424  			return nil
   425  		}
   426  		return errors.Errorf("the identities do not match")
   427  
   428  	case m.MSPPrincipal_ORGANIZATION_UNIT:
   429  		ou := &m.OrganizationUnit{}
   430  		err := proto.Unmarshal(principal.Principal, ou)
   431  		if err != nil {
   432  			return errors.Wrap(err, "could not unmarshal OU from principal")
   433  		}
   434  
   435  		mspLogger.Debugf("Checking if identity is part of OU \"%s\" of mspid \"%s\"", ou.OrganizationalUnitIdentifier, ou.MspIdentifier)
   436  
   437  		// at first, we check whether the MSP
   438  		// identifier is the same as that of the identity
   439  		if ou.MspIdentifier != msp.name {
   440  			return errors.Errorf("the identity is a member of a different MSP (expected %s, got %s)", ou.MspIdentifier, id.GetMSPIdentifier())
   441  		}
   442  
   443  		if ou.OrganizationalUnitIdentifier != id.(*idemixidentity).OU.OrganizationalUnitIdentifier {
   444  			return errors.Errorf("user is not part of the desired organizational unit")
   445  		}
   446  
   447  		return nil
   448  	case m.MSPPrincipal_COMBINED:
   449  		if msp.version <= MSPv1_1 {
   450  			return errors.Errorf("Combined MSP Principals are unsupported in MSPv1_1")
   451  		}
   452  
   453  		// Principal is a combination of multiple principals.
   454  		principals := &m.CombinedPrincipal{}
   455  		err := proto.Unmarshal(principal.Principal, principals)
   456  		if err != nil {
   457  			return errors.Wrap(err, "could not unmarshal CombinedPrincipal from principal")
   458  		}
   459  		// Return an error if there are no principals in the combined principal.
   460  		if len(principals.Principals) == 0 {
   461  			return errors.New("no principals in CombinedPrincipal")
   462  		}
   463  		// Recursively call msp.SatisfiesPrincipal for all combined principals.
   464  		// There is no limit for the levels of nesting for the combined principals.
   465  		for _, cp := range principals.Principals {
   466  			err = msp.satisfiesPrincipalValidated(id, cp)
   467  			if err != nil {
   468  				return err
   469  			}
   470  		}
   471  		// The identity satisfies all the principals
   472  		return nil
   473  	case m.MSPPrincipal_ANONYMITY:
   474  		if msp.version <= MSPv1_1 {
   475  			return errors.Errorf("Anonymity MSP Principals are unsupported in MSPv1_1")
   476  		}
   477  
   478  		anon := &m.MSPIdentityAnonymity{}
   479  		err := proto.Unmarshal(principal.Principal, anon)
   480  		if err != nil {
   481  			return errors.Wrap(err, "could not unmarshal MSPIdentityAnonymity from principal")
   482  		}
   483  		switch anon.AnonymityType {
   484  		case m.MSPIdentityAnonymity_ANONYMOUS:
   485  			return nil
   486  		case m.MSPIdentityAnonymity_NOMINAL:
   487  			return errors.New("principal is nominal, but idemix MSP is anonymous")
   488  		default:
   489  			return errors.Errorf("unknown principal anonymity type: %d", anon.AnonymityType)
   490  		}
   491  	default:
   492  		return errors.Errorf("invalid principal type %d", int32(principal.PrincipalClassification))
   493  	}
   494  }
   495  
   496  // IsWellFormed checks if the given identity can be deserialized into its provider-specific .
   497  // In this MSP implementation, an identity is considered well formed if it contains a
   498  // marshaled SerializedIdemixIdentity protobuf message.
   499  func (id *idemixmsp) IsWellFormed(identity *m.SerializedIdentity) error {
   500  	sId := new(m.SerializedIdemixIdentity)
   501  	err := proto.Unmarshal(identity.IdBytes, sId)
   502  	if err != nil {
   503  		return errors.Wrap(err, "not an idemix identity")
   504  	}
   505  	return nil
   506  }
   507  
   508  func (msp *idemixmsp) GetTLSRootCerts() [][]byte {
   509  	// TODO
   510  	return nil
   511  }
   512  
   513  func (msp *idemixmsp) GetTLSIntermediateCerts() [][]byte {
   514  	// TODO
   515  	return nil
   516  }
   517  
   518  type idemixidentity struct {
   519  	NymPublicKey bccsp.Key
   520  	msp          *idemixmsp
   521  	id           *IdentityIdentifier
   522  	Role         *m.MSPRole
   523  	OU           *m.OrganizationUnit
   524  	// associationProof contains cryptographic proof that this identity
   525  	// belongs to the MSP id.msp, i.e., it proves that the pseudonym
   526  	// is constructed from a secret key on which the CA issued a credential.
   527  	associationProof []byte
   528  }
   529  
   530  func (id *idemixidentity) Anonymous() bool {
   531  	return true
   532  }
   533  
   534  func newIdemixIdentity(msp *idemixmsp, NymPublicKey bccsp.Key, role *m.MSPRole, ou *m.OrganizationUnit, proof []byte) *idemixidentity {
   535  	id := &idemixidentity{}
   536  	id.NymPublicKey = NymPublicKey
   537  	id.msp = msp
   538  	id.Role = role
   539  	id.OU = ou
   540  	id.associationProof = proof
   541  
   542  	raw, err := NymPublicKey.Bytes()
   543  	if err != nil {
   544  		panic(fmt.Sprintf("unexpected condition, failed marshalling nym public key [%s]", err))
   545  	}
   546  	id.id = &IdentityIdentifier{
   547  		Mspid: msp.name,
   548  		Id:    bytes.NewBuffer(raw).String(),
   549  	}
   550  
   551  	return id
   552  }
   553  
   554  func (id *idemixidentity) ExpiresAt() time.Time {
   555  	// Idemix MSP currently does not use expiration dates or revocation,
   556  	// so we return the zero time to indicate this.
   557  	return time.Time{}
   558  }
   559  
   560  func (id *idemixidentity) GetIdentifier() *IdentityIdentifier {
   561  	return id.id
   562  }
   563  
   564  func (id *idemixidentity) GetMSPIdentifier() string {
   565  	mspid, _ := id.msp.GetIdentifier()
   566  	return mspid
   567  }
   568  
   569  func (id *idemixidentity) GetOrganizationalUnits() []*OUIdentifier {
   570  	// we use the (serialized) public key of this MSP as the CertifiersIdentifier
   571  	certifiersIdentifier, err := id.msp.ipk.Bytes()
   572  	if err != nil {
   573  		mspIdentityLogger.Errorf("Failed to marshal ipk in GetOrganizationalUnits: %s", err)
   574  		return nil
   575  	}
   576  
   577  	return []*OUIdentifier{{certifiersIdentifier, id.OU.OrganizationalUnitIdentifier}}
   578  }
   579  
   580  func (id *idemixidentity) Validate() error {
   581  	return id.msp.Validate(id)
   582  }
   583  
   584  func (id *idemixidentity) Verify(msg []byte, sig []byte) error {
   585  	if mspIdentityLogger.IsEnabledFor(zapcore.DebugLevel) {
   586  		mspIdentityLogger.Debugf("Verify Idemix sig: msg = %s", hex.Dump(msg))
   587  		mspIdentityLogger.Debugf("Verify Idemix sig: sig = %s", hex.Dump(sig))
   588  	}
   589  
   590  	_, err := id.msp.csp.Verify(
   591  		id.NymPublicKey,
   592  		sig,
   593  		msg,
   594  		&bccsp.IdemixNymSignerOpts{
   595  			IssuerPK: id.msp.ipk,
   596  		},
   597  	)
   598  	return err
   599  }
   600  
   601  func (id *idemixidentity) SatisfiesPrincipal(principal *m.MSPPrincipal) error {
   602  	return id.msp.SatisfiesPrincipal(id, principal)
   603  }
   604  
   605  func (id *idemixidentity) Serialize() ([]byte, error) {
   606  	serialized := &m.SerializedIdemixIdentity{}
   607  
   608  	raw, err := id.NymPublicKey.Bytes()
   609  	if err != nil {
   610  		return nil, errors.Wrapf(err, "could not serialize nym of identity %s", id.id)
   611  	}
   612  	// This is an assumption on how the underlying idemix implementation work.
   613  	// TODO: change this in future version
   614  	serialized.NymX = raw[:len(raw)/2]
   615  	serialized.NymY = raw[len(raw)/2:]
   616  	ouBytes, err := proto.Marshal(id.OU)
   617  	if err != nil {
   618  		return nil, errors.Wrapf(err, "could not marshal OU of identity %s", id.id)
   619  	}
   620  
   621  	roleBytes, err := proto.Marshal(id.Role)
   622  	if err != nil {
   623  		return nil, errors.Wrapf(err, "could not marshal role of identity %s", id.id)
   624  	}
   625  
   626  	serialized.Ou = ouBytes
   627  	serialized.Role = roleBytes
   628  	serialized.Proof = id.associationProof
   629  
   630  	idemixIDBytes, err := proto.Marshal(serialized)
   631  	if err != nil {
   632  		return nil, err
   633  	}
   634  
   635  	sID := &m.SerializedIdentity{Mspid: id.GetMSPIdentifier(), IdBytes: idemixIDBytes}
   636  	idBytes, err := proto.Marshal(sID)
   637  	if err != nil {
   638  		return nil, errors.Wrapf(err, "could not marshal a SerializedIdentity structure for identity %s", id.id)
   639  	}
   640  
   641  	return idBytes, nil
   642  }
   643  
   644  type idemixSigningIdentity struct {
   645  	*idemixidentity
   646  	Cred         []byte
   647  	UserKey      bccsp.Key
   648  	NymKey       bccsp.Key
   649  	enrollmentId string
   650  }
   651  
   652  func (id *idemixSigningIdentity) Sign(msg []byte) ([]byte, error) {
   653  	mspLogger.Debugf("Idemix identity %s is signing", id.GetIdentifier())
   654  
   655  	sig, err := id.msp.csp.Sign(
   656  		id.UserKey,
   657  		msg,
   658  		&bccsp.IdemixNymSignerOpts{
   659  			Nym:      id.NymKey,
   660  			IssuerPK: id.msp.ipk,
   661  		},
   662  	)
   663  	if err != nil {
   664  		return nil, err
   665  	}
   666  	return sig, nil
   667  }
   668  
   669  func (id *idemixSigningIdentity) GetPublicVersion() Identity {
   670  	return id.idemixidentity
   671  }