Skip to content

Commit fb9890d

Browse files
author
Manu Drijvers
committedMay 17, 2018
[FAB-7615] idemixmsp supports anon+combined principals
The identity mixer based MSP now supports anonymity principals and combined principals. Change-Id: Ib703d47d8729e697c351379d64da67bd022a5b34 Signed-off-by: Manu Drijvers <mdr@zurich.ibm.com>
1 parent 56f2ebf commit fb9890d

File tree

2 files changed

+187
-13
lines changed

2 files changed

+187
-13
lines changed
 

‎msp/idemixmsp.go

+47-13
Original file line numberDiff line numberDiff line change
@@ -289,6 +289,17 @@ func (id *idemixidentity) verifyProof() error {
289289
}
290290

291291
func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal) error {
292+
err := msp.Validate(id)
293+
if err != nil {
294+
return errors.Wrap(err, "identity is not valid with respect to this MSP")
295+
}
296+
297+
return msp.satisfiesPrincipalValidated(id, principal)
298+
}
299+
300+
// satisfiesPrincipalValidated performs all the tasks of satisfiesPrincipal except the identity validation,
301+
// such that combined principals will not cause multiple expensive identity validations.
302+
func (msp *idemixmsp) satisfiesPrincipalValidated(id Identity, principal *m.MSPPrincipal) error {
292303
switch principal.PrincipalClassification {
293304
// in this case, we have to check whether the
294305
// identity has a role in the msp - member or admin
@@ -306,11 +317,6 @@ func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal)
306317
return errors.Errorf("the identity is a member of a different MSP (expected %s, got %s)", mspRole.MspIdentifier, id.GetMSPIdentifier())
307318
}
308319

309-
// check whether this identity is valid
310-
err = msp.Validate(id)
311-
if err != nil {
312-
return errors.Wrap(err, "identity is not valid with respect to this MSP")
313-
}
314320
// now we validate the different msp roles
315321
switch mspRole.Role {
316322
case m.MSPRole_MEMBER:
@@ -357,18 +363,46 @@ func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal)
357363
return errors.Errorf("the identity is a member of a different MSP (expected %s, got %s)", ou.MspIdentifier, id.GetMSPIdentifier())
358364
}
359365

360-
// we then check if the identity is valid with this MSP
361-
// and fail if it is not
362-
err = msp.Validate(id)
363-
if err != nil {
364-
return err
365-
}
366-
367366
if ou.OrganizationalUnitIdentifier != id.(*idemixidentity).OU.OrganizationalUnitIdentifier {
368367
return errors.Errorf("user is not part of the desired organizational unit")
369368
}
370369

371370
return nil
371+
case m.MSPPrincipal_COMBINED:
372+
// Principal is a combination of multiple principals.
373+
principals := &m.CombinedPrincipal{}
374+
err := proto.Unmarshal(principal.Principal, principals)
375+
if err != nil {
376+
return errors.Wrap(err, "could not unmarshal CombinedPrincipal from principal")
377+
}
378+
// Return an error if there are no principals in the combined principal.
379+
if len(principals.Principals) == 0 {
380+
return errors.New("no principals in CombinedPrincipal")
381+
}
382+
// Recursively call msp.SatisfiesPrincipal for all combined principals.
383+
// There is no limit for the levels of nesting for the combined principals.
384+
for _, cp := range principals.Principals {
385+
err = msp.satisfiesPrincipalValidated(id, cp)
386+
if err != nil {
387+
return err
388+
}
389+
}
390+
// The identity satisfies all the principals
391+
return nil
392+
case m.MSPPrincipal_ANONYMITY:
393+
anon := &m.MSPIdentityAnonymity{}
394+
err := proto.Unmarshal(principal.Principal, anon)
395+
if err != nil {
396+
return errors.Wrap(err, "could not unmarshal MSPIdentityAnonymity from principal")
397+
}
398+
switch anon.AnonymityType {
399+
case m.MSPIdentityAnonymity_ANONYMOUS:
400+
return nil
401+
case m.MSPIdentityAnonymity_NOMINAL:
402+
return errors.New("principal is nominal, but idemix MSP is anonymous")
403+
default:
404+
return errors.Errorf("unknown principal anonymity type: %d", anon.AnonymityType)
405+
}
372406
default:
373407
return errors.Errorf("invalid principal type %d", int32(principal.PrincipalClassification))
374408
}
@@ -409,7 +443,7 @@ type idemixidentity struct {
409443
}
410444

411445
func (id *idemixidentity) Anonymous() bool {
412-
return false
446+
return true
413447
}
414448

415449
func newIdemixIdentity(msp *idemixmsp, nym *FP256BN.ECP, role *m.MSPRole, ou *m.OrganizationUnit, proof *idemix.Signature) *idemixidentity {

‎msp/idemixmsp_test.go

+140
Original file line numberDiff line numberDiff line change
@@ -63,23 +63,27 @@ func TestSetup(t *testing.T) {
6363
func TestSetupBad(t *testing.T) {
6464
_, err := setup("testdata/idemix/badpath", "MSPID")
6565
assert.Error(t, err)
66+
assert.Contains(t, err.Error(), "Getting MSP config failed")
6667

6768
msp1, err := newIdemixMsp()
6869
assert.NoError(t, err)
6970

7071
// Setup with nil config
7172
err = msp1.Setup(nil)
7273
assert.Error(t, err)
74+
assert.Contains(t, err.Error(), "setup error: nil conf reference")
7375

7476
// Setup with incorrect MSP type
7577
conf := &msp.MSPConfig{Type: 1234, Config: nil}
7678
err = msp1.Setup(conf)
7779
assert.Error(t, err)
80+
assert.Contains(t, err.Error(), "setup error: config is not of type IDEMIX")
7881

7982
// Setup with bad idemix config bytes
8083
conf = &msp.MSPConfig{Type: int32(IDEMIX), Config: []byte("barf")}
8184
err = msp1.Setup(conf)
8285
assert.Error(t, err)
86+
assert.Contains(t, err.Error(), "failed unmarshalling idemix msp config")
8387

8488
conf, err = GetIdemixMspConfig("testdata/idemix/MSP1OU1", "IdemixMSP1")
8589
idemixconfig := &msp.IdemixMSPConfig{}
@@ -101,6 +105,7 @@ func TestSetupBad(t *testing.T) {
101105

102106
err = msp1.Setup(conf)
103107
assert.Error(t, err)
108+
assert.Contains(t, err.Error(), "issuer public key must have have attributes OU, Role, EnrollmentId, and RevocationHandle")
104109

105110
// Create MSP config with bad IPK bytes
106111
ipkBytes = []byte("barf")
@@ -112,6 +117,7 @@ func TestSetupBad(t *testing.T) {
112117

113118
err = msp1.Setup(conf)
114119
assert.Error(t, err)
120+
assert.Contains(t, err.Error(), "failed to unmarshal ipk from idemix msp config")
115121
}
116122

117123
func TestSigning(t *testing.T) {
@@ -130,13 +136,15 @@ func TestSigning(t *testing.T) {
130136

131137
err = id.Verify([]byte("OtherMessage"), sig)
132138
assert.Error(t, err)
139+
assert.Contains(t, err.Error(), "pseudonym signature invalid: zero-knowledge proof is invalid")
133140

134141
verMsp, err := setup("testdata/idemix/MSP1Verifier", "MSP1")
135142
assert.NoError(t, err)
136143
err = verMsp.Validate(id)
137144
assert.NoError(t, err)
138145
_, err = verMsp.GetDefaultSigningIdentity()
139146
assert.Error(t, err)
147+
assert.Contains(t, err.Error(), "no default signer setup")
140148
}
141149

142150
func TestSigningBad(t *testing.T) {
@@ -151,6 +159,7 @@ func TestSigningBad(t *testing.T) {
151159

152160
err = id.Verify(msg, sig)
153161
assert.Error(t, err)
162+
assert.Contains(t, err.Error(), "error unmarshalling signature")
154163
}
155164

156165
func TestIdentitySerialization(t *testing.T) {
@@ -179,6 +188,7 @@ func TestIdentitySerializationBad(t *testing.T) {
179188

180189
_, err = msp.DeserializeIdentity([]byte("barf"))
181190
assert.Error(t, err, "DeserializeIdentity should have failed for bad input")
191+
assert.Contains(t, err.Error(), "could not deserialize a SerializedIdentity")
182192
}
183193

184194
func TestIdentitySerializationWrongMSP(t *testing.T) {
@@ -194,6 +204,7 @@ func TestIdentitySerializationWrongMSP(t *testing.T) {
194204

195205
_, err = msp1.DeserializeIdentity(idBytes)
196206
assert.Error(t, err, "DeserializeIdentity should have failed for ID of other MSP")
207+
assert.Contains(t, err.Error(), "expected MSP ID MSP1OU1, received MSP2OU1")
197208
}
198209

199210
func TestPrincipalIdentity(t *testing.T) {
@@ -236,6 +247,8 @@ func TestPrincipalIdentityWrongIdentity(t *testing.T) {
236247

237248
err = id2.SatisfiesPrincipal(principal)
238249
assert.Error(t, err, "Identity MSP principal for different user should fail")
250+
assert.Contains(t, err.Error(), "the identities do not match")
251+
239252
}
240253

241254
func TestPrincipalIdentityBadIdentity(t *testing.T) {
@@ -253,6 +266,44 @@ func TestPrincipalIdentityBadIdentity(t *testing.T) {
253266

254267
err = id1.SatisfiesPrincipal(principal)
255268
assert.Error(t, err, "Identity MSP principal for a bad principal should fail")
269+
assert.Contains(t, err.Error(), "the identities do not match")
270+
}
271+
272+
func TestAnonymityPrincipal(t *testing.T) {
273+
msp1, err := setup("testdata/idemix/MSP1OU1", "MSP1OU1")
274+
assert.NoError(t, err)
275+
276+
id1, err := getDefaultSigner(msp1)
277+
assert.NoError(t, err)
278+
279+
principalBytes, err := proto.Marshal(&msp.MSPIdentityAnonymity{AnonymityType: msp.MSPIdentityAnonymity_ANONYMOUS})
280+
assert.NoError(t, err)
281+
282+
principal := &msp.MSPPrincipal{
283+
PrincipalClassification: msp.MSPPrincipal_ANONYMITY,
284+
Principal: principalBytes}
285+
286+
err = id1.SatisfiesPrincipal(principal)
287+
assert.NoError(t, err)
288+
}
289+
290+
func TestAnonymityPrincipalBad(t *testing.T) {
291+
msp1, err := setup("testdata/idemix/MSP1OU1", "MSP1OU1")
292+
assert.NoError(t, err)
293+
294+
id1, err := getDefaultSigner(msp1)
295+
assert.NoError(t, err)
296+
297+
principalBytes, err := proto.Marshal(&msp.MSPIdentityAnonymity{AnonymityType: msp.MSPIdentityAnonymity_NOMINAL})
298+
assert.NoError(t, err)
299+
300+
principal := &msp.MSPPrincipal{
301+
PrincipalClassification: msp.MSPPrincipal_ANONYMITY,
302+
Principal: principalBytes}
303+
304+
err = id1.SatisfiesPrincipal(principal)
305+
assert.Error(t, err, "Idemix identity is anonymous and should not pass NOMINAL anonymity principal")
306+
assert.Contains(t, err.Error(), "principal is nominal, but idemix MSP is anonymous")
256307
}
257308

258309
func TestIdemixIsWellFormed(t *testing.T) {
@@ -319,6 +370,8 @@ func TestPrincipalOUWrongOU(t *testing.T) {
319370

320371
err = id1.SatisfiesPrincipal(principal)
321372
assert.Error(t, err, "OU MSP principal should have failed for user of different OU")
373+
assert.Contains(t, err.Error(), "user is not part of the desired organizational unit")
374+
322375
}
323376

324377
func TestPrincipalOUWrongMSP(t *testing.T) {
@@ -342,6 +395,8 @@ func TestPrincipalOUWrongMSP(t *testing.T) {
342395

343396
err = id1.SatisfiesPrincipal(principal)
344397
assert.Error(t, err, "OU MSP principal should have failed for user of different MSP")
398+
assert.Contains(t, err.Error(), "the identity is a member of a different MSP")
399+
345400
}
346401

347402
func TestPrincipalOUBad(t *testing.T) {
@@ -360,6 +415,7 @@ func TestPrincipalOUBad(t *testing.T) {
360415

361416
err = id1.SatisfiesPrincipal(principal)
362417
assert.Error(t, err, "OU MSP principal should have failed for a bad OU principal")
418+
assert.Contains(t, err.Error(), "could not unmarshal OU from principal")
363419
}
364420

365421
func TestPrincipalRoleMember(t *testing.T) {
@@ -425,6 +481,7 @@ func TestPrincipalRoleNotAdmin(t *testing.T) {
425481

426482
err = id1.SatisfiesPrincipal(principal)
427483
assert.Error(t, err, "Member should not satisfy Admin principal")
484+
assert.Contains(t, err.Error(), "user is not an admin")
428485
}
429486

430487
func TestPrincipalRoleWrongMSP(t *testing.T) {
@@ -443,6 +500,7 @@ func TestPrincipalRoleWrongMSP(t *testing.T) {
443500

444501
err = id1.SatisfiesPrincipal(principal)
445502
assert.Error(t, err, "Role MSP principal should have failed for user of different MSP")
503+
assert.Contains(t, err.Error(), "the identity is a member of a different MSP")
446504
}
447505

448506
func TestPrincipalRoleBadRole(t *testing.T) {
@@ -462,6 +520,7 @@ func TestPrincipalRoleBadRole(t *testing.T) {
462520

463521
err = id1.SatisfiesPrincipal(principal)
464522
assert.Error(t, err, "Role MSP principal should have failed for a bad Role")
523+
assert.Contains(t, err.Error(), "invalid MSP role type")
465524
}
466525

467526
func TestPrincipalBad(t *testing.T) {
@@ -477,4 +536,85 @@ func TestPrincipalBad(t *testing.T) {
477536

478537
err = id1.SatisfiesPrincipal(principal)
479538
assert.Error(t, err, "Principal with bad Classification should fail")
539+
assert.Contains(t, err.Error(), "invalid principal type")
540+
}
541+
542+
func TestPrincipalCombined(t *testing.T) {
543+
msp1, err := setup("testdata/idemix/MSP1OU1", "MSP1OU1")
544+
assert.NoError(t, err)
545+
546+
id1, err := getDefaultSigner(msp1)
547+
assert.NoError(t, err)
548+
549+
ou := &msp.OrganizationUnit{
550+
OrganizationalUnitIdentifier: id1.GetOrganizationalUnits()[0].OrganizationalUnitIdentifier,
551+
MspIdentifier: id1.GetMSPIdentifier(),
552+
CertifiersIdentifier: nil,
553+
}
554+
principalBytes, err := proto.Marshal(ou)
555+
assert.NoError(t, err)
556+
557+
principalOU := &msp.MSPPrincipal{
558+
PrincipalClassification: msp.MSPPrincipal_ORGANIZATION_UNIT,
559+
Principal: principalBytes}
560+
561+
principalBytes, err = proto.Marshal(&msp.MSPRole{Role: msp.MSPRole_MEMBER, MspIdentifier: id1.GetMSPIdentifier()})
562+
assert.NoError(t, err)
563+
564+
principalRole := &msp.MSPPrincipal{
565+
PrincipalClassification: msp.MSPPrincipal_ROLE,
566+
Principal: principalBytes}
567+
568+
principals := []*msp.MSPPrincipal{principalOU, principalRole}
569+
570+
combinedPrincipal := &msp.CombinedPrincipal{Principals: principals}
571+
combinedPrincipalBytes, err := proto.Marshal(combinedPrincipal)
572+
573+
assert.NoError(t, err)
574+
575+
principalsCombined := &msp.MSPPrincipal{PrincipalClassification: msp.MSPPrincipal_COMBINED, Principal: combinedPrincipalBytes}
576+
577+
err = id1.SatisfiesPrincipal(principalsCombined)
578+
assert.NoError(t, err)
579+
}
580+
581+
func TestPrincipalCombinedBad(t *testing.T) {
582+
msp1, err := setup("testdata/idemix/MSP1OU1", "MSP1OU1")
583+
assert.NoError(t, err)
584+
585+
id1, err := getDefaultSigner(msp1)
586+
assert.NoError(t, err)
587+
588+
// create combined principal requiring membership of OU1 in MSP1 and requiring admin role
589+
ou := &msp.OrganizationUnit{
590+
OrganizationalUnitIdentifier: id1.GetOrganizationalUnits()[0].OrganizationalUnitIdentifier,
591+
MspIdentifier: id1.GetMSPIdentifier(),
592+
CertifiersIdentifier: nil,
593+
}
594+
principalBytes, err := proto.Marshal(ou)
595+
assert.NoError(t, err)
596+
597+
principalOU := &msp.MSPPrincipal{
598+
PrincipalClassification: msp.MSPPrincipal_ORGANIZATION_UNIT,
599+
Principal: principalBytes}
600+
601+
principalBytes, err = proto.Marshal(&msp.MSPRole{Role: msp.MSPRole_ADMIN, MspIdentifier: id1.GetMSPIdentifier()})
602+
assert.NoError(t, err)
603+
604+
principalRole := &msp.MSPPrincipal{
605+
PrincipalClassification: msp.MSPPrincipal_ROLE,
606+
Principal: principalBytes}
607+
608+
principals := []*msp.MSPPrincipal{principalOU, principalRole}
609+
610+
combinedPrincipal := &msp.CombinedPrincipal{Principals: principals}
611+
combinedPrincipalBytes, err := proto.Marshal(combinedPrincipal)
612+
613+
assert.NoError(t, err)
614+
615+
principalsCombined := &msp.MSPPrincipal{PrincipalClassification: msp.MSPPrincipal_COMBINED, Principal: combinedPrincipalBytes}
616+
617+
err = id1.SatisfiesPrincipal(principalsCombined)
618+
assert.Error(t, err, "non-admin member of OU1 in MSP1 should not satisfy principal admin and OU1 in MSP1")
619+
assert.Contains(t, err.Error(), "user is not an admin")
480620
}

0 commit comments

Comments
 (0)
Please sign in to comment.