github.com/true-sqn/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 }