Skip to content

Commit 8cbae04

Browse files
author
Manu Drijvers
committed
[FAB-8810] Extend idemix cred with enrollment IDs
This commit extends the idemix certificates with attributes enrollment id and revocation handle, to allow for auditing and revocation features that are planned. Change-Id: I921de0a383d76132fe07d49f2179161a40f97810 Signed-off-by: Manu Drijvers <mdr@zurich.ibm.com>
1 parent 9015790 commit 8cbae04

25 files changed

+147
-87
lines changed

common/tools/idemixgen/idemixca/idemixca.go

+21-12
Original file line numberDiff line numberDiff line change
@@ -15,17 +15,19 @@ import (
1515
"github.com/pkg/errors"
1616
)
1717

18-
// GenerateIssuerKey invokes Idemix library to generate an issuer (CA) signing key pair
19-
// currently two attributes are supported by the issuer:
18+
// GenerateIssuerKey invokes Idemix library to generate an issuer (CA) signing key pair.
19+
// Currently four attributes are supported by the issuer:
2020
// AttributeNameOU is the organization unit name
2121
// AttributeNameRole is the role (member or admin) name
22-
// Generated keys are serialized to bytes
22+
// AttributeNameEnrollmentId is the enrollment id
23+
// AttributeNameRevocationHandle contains the revocation handle, which can be used to revoke this user
24+
// Generated keys are serialized to bytes.
2325
func GenerateIssuerKey() ([]byte, []byte, error) {
2426
rng, err := idemix.GetRand()
2527
if err != nil {
2628
return nil, nil, err
2729
}
28-
AttributeNames := []string{msp.AttributeNameOU, msp.AttributeNameRole}
30+
AttributeNames := []string{msp.AttributeNameOU, msp.AttributeNameRole, msp.AttributeNameEnrollmentId, msp.AttributeNameRevocationHandle}
2931
key, err := idemix.NewIssuerKey(AttributeNames, rng)
3032
if err != nil {
3133
return nil, nil, errors.WithMessage(err, "cannot generate CA key")
@@ -35,29 +37,35 @@ func GenerateIssuerKey() ([]byte, []byte, error) {
3537
return key.ISk, ipkSerialized, err
3638
}
3739

38-
// GenerateMSPConfig creates a new MSP config
40+
// GenerateMSPConfig creates a new MSP config.
3941
// If the new MSP config contains a signer then
4042
// it generates a fresh user secret and issues a credential
41-
// with two attributes (described above)
42-
// using the CA's key pair from the file
43+
// with four attributes (described above)
44+
// using the CA's key pair from the file.
4345
// If the new MSP config does not contain a signer
4446
// (meaning it is used only for verification)
45-
// then only a public key of the CA (issuer) is added to the MSP config (besides the name)
46-
func GenerateSignerConfig(isAdmin bool, ouString string, key *idemix.IssuerKey) ([]byte, error) {
47-
attrs := make([]*FP256BN.BIG, 2)
47+
// then only a public key of the CA (issuer) is added to the MSP config (besides the name).
48+
func GenerateSignerConfig(isAdmin bool, ouString string, enrollmentId string, revocationHandle int, key *idemix.IssuerKey) ([]byte, error) {
49+
attrs := make([]*FP256BN.BIG, 4)
4850

4951
if ouString == "" {
5052
return nil, errors.Errorf("the OU attribute value is empty")
5153
}
5254

55+
if enrollmentId == "" {
56+
return nil, errors.Errorf("the enrollment id value is empty")
57+
}
58+
5359
role := m.MSPRole_MEMBER
5460

5561
if isAdmin {
5662
role = m.MSPRole_ADMIN
5763
}
5864

59-
attrs[0] = idemix.HashModOrder([]byte(ouString))
60-
attrs[1] = FP256BN.NewBIGint(int(role))
65+
attrs[msp.AttributeIndexOU] = idemix.HashModOrder([]byte(ouString))
66+
attrs[msp.AttributeIndexRole] = FP256BN.NewBIGint(int(role))
67+
attrs[msp.AttributeIndexEnrollmentId] = idemix.HashModOrder([]byte(enrollmentId))
68+
attrs[msp.AttributeIndexRevocationHandle] = FP256BN.NewBIGint(revocationHandle)
6169

6270
rng, err := idemix.GetRand()
6371
if err != nil {
@@ -81,6 +89,7 @@ func GenerateSignerConfig(isAdmin bool, ouString string, key *idemix.IssuerKey)
8189
idemix.BigToBytes(sk),
8290
ouString,
8391
isAdmin,
92+
enrollmentId,
8493
}
8594
return proto.Marshal(signer)
8695
}

common/tools/idemixgen/idemixca/idemixca_test.go

+6-3
Original file line numberDiff line numberDiff line change
@@ -36,13 +36,13 @@ func TestIdemixCa(t *testing.T) {
3636

3737
key := &idemix.IssuerKey{isk, ipk}
3838

39-
conf, err := GenerateSignerConfig(false, "OU1", key)
39+
conf, err := GenerateSignerConfig(false, "OU1", "enrollmentid1", 1, key)
4040
assert.NoError(t, err)
4141
cleanupSigner()
4242
assert.NoError(t, writeSignerToFile(conf))
4343
assert.NoError(t, setupMSP())
4444

45-
conf, err = GenerateSignerConfig(true, "OU1", key)
45+
conf, err = GenerateSignerConfig(true, "OU1", "enrollmentid2", 1234, key)
4646
assert.NoError(t, err)
4747
cleanupSigner()
4848
assert.NoError(t, writeSignerToFile(conf))
@@ -52,8 +52,11 @@ func TestIdemixCa(t *testing.T) {
5252
cleanupVerifier()
5353
assert.Error(t, setupMSP())
5454

55-
_, err = GenerateSignerConfig(true, "", key)
55+
_, err = GenerateSignerConfig(true, "", "enrollmentid", 1, key)
5656
assert.EqualError(t, err, "the OU attribute value is empty")
57+
58+
_, err = GenerateSignerConfig(true, "OU1", "", 1, key)
59+
assert.EqualError(t, err, "the enrollment id value is empty")
5760
}
5861

5962
func cleanup() error {

common/tools/idemixgen/idemixgen.go

+7-5
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ const (
3535
var (
3636
app = kingpin.New("idemixgen", "Utility for generating key material to be used with the Identity Mixer MSP in Hyperledger Fabric")
3737

38-
genIssuerKey = app.Command("ca-keygen", "Generate CA key material")
39-
genSignerConfig = app.Command("signerconfig", "Generate a default signer for this Idemix MSP")
40-
genCredOU = genSignerConfig.Flag("org-unit", "The Organizational Unit of the default signer").Short('u').String()
41-
genCredIsAdmin = genSignerConfig.Flag("admin", "Make the default signer admin").Short('a').Bool()
38+
genIssuerKey = app.Command("ca-keygen", "Generate CA key material")
39+
genSignerConfig = app.Command("signerconfig", "Generate a default signer for this Idemix MSP")
40+
genCredOU = genSignerConfig.Flag("org-unit", "The Organizational Unit of the default signer").Short('u').String()
41+
genCredIsAdmin = genSignerConfig.Flag("admin", "Make the default signer admin").Short('a').Bool()
42+
genCredEnrollmentId = genSignerConfig.Flag("enrollmentId", "The enrollment id of the default signer").Short('e').String()
43+
genCredRevocationHandle = genSignerConfig.Flag("revocationHandle", "The handle used to revoke this signer").Short('r').Int()
4244

4345
version = app.Command("version", "Show version information")
4446
)
@@ -67,7 +69,7 @@ func main() {
6769
writeFile(filepath.Join(msp.IdemixConfigDirMsp, msp.IdemixConfigFileIssuerPublicKey), ipk)
6870

6971
case genSignerConfig.FullCommand():
70-
config, err := idemixca.GenerateSignerConfig(*genCredIsAdmin, *genCredOU, readIssuerKey())
72+
config, err := idemixca.GenerateSignerConfig(*genCredIsAdmin, *genCredOU, *genCredEnrollmentId, *genCredRevocationHandle, readIssuerKey())
7173
handleError(err)
7274

7375
path := msp.IdemixConfigDirUser

msp/idemixmsp.go

+50-17
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,38 @@ import (
2020
"github.com/pkg/errors"
2121
)
2222

23+
const (
24+
// AttributeIndexOU contains the index of the OU attribute in the idemix credential attributes
25+
AttributeIndexOU = iota
26+
27+
// AttributeIndexRole contains the index of the Role attribute in the idemix credential attributes
28+
AttributeIndexRole
29+
30+
// AttributeIndexEnrollmentId contains the index of the Enrollment ID attribute in the idemix credential attributes
31+
AttributeIndexEnrollmentId
32+
33+
// AttributeIndexRevocationHandle contains the index of the Revocation Handle attribute in the idemix credential attributes
34+
AttributeIndexRevocationHandle
35+
)
36+
2337
const (
2438
// AttributeNameOU is the attribute name of the Organization Unit attribute
2539
AttributeNameOU = "OU"
2640

2741
// AttributeNameRole is the attribute name of the Role attribute
2842
AttributeNameRole = "Role"
43+
44+
// AttributeNameEnrollmentId is the attribute name of the Enrollment ID attribute
45+
AttributeNameEnrollmentId = "EnrollmentID"
46+
47+
// AttributeNameRevocationHandle is the attribute name of the revocation handle attribute
48+
AttributeNameRevocationHandle = "RevocationHandle"
2949
)
3050

3151
// discloseFlags will be passed to the idemix signing and verification routines.
32-
// It informs idemix to disclose both attributes (OU and Role) when signing.
33-
var discloseFlags = []byte{1, 1}
52+
// It informs idemix to disclose both attributes (OU and Role) when signing,
53+
// while hiding attributes EnrollmentID and RevocationHandle.
54+
var discloseFlags = []byte{1, 1, 0, 0}
3455

3556
type idemixmsp struct {
3657
ipk *idemix.IssuerPublicKey
@@ -77,8 +98,12 @@ func (msp *idemixmsp) Setup(conf1 *m.MSPConfig) error {
7798
return errors.WithMessage(err, "setting the hash of the issuer public key failed")
7899
}
79100

80-
if len(ipk.AttributeNames) < 2 || ipk.AttributeNames[0] != AttributeNameOU || ipk.AttributeNames[1] != AttributeNameRole {
81-
return errors.Errorf("ipk must have have attributes OU and Role")
101+
if len(ipk.AttributeNames) < 4 ||
102+
ipk.AttributeNames[AttributeIndexOU] != AttributeNameOU ||
103+
ipk.AttributeNames[AttributeIndexRole] != AttributeNameRole ||
104+
ipk.AttributeNames[AttributeIndexEnrollmentId] != AttributeNameEnrollmentId ||
105+
ipk.AttributeNames[AttributeIndexRevocationHandle] != AttributeNameRevocationHandle {
106+
return errors.Errorf("issuer public key must have have attributes OU, Role, EnrollmentId, and RevocationHandle")
82107
}
83108

84109
err = ipk.Check()
@@ -124,22 +149,29 @@ func (msp *idemixmsp) Setup(conf1 *m.MSPConfig) error {
124149
CertifiersIdentifier: ipk.Hash,
125150
}
126151

127-
// Check if credential contains the right amount of attribute values (Role and OU)
128-
if len(cred.Attrs) != 2 {
129-
return errors.Errorf("Credential contains %d attribute values, but expected 2", len(cred.Attrs))
152+
enrollmentId := conf.Signer.EnrollmentId
153+
154+
// Check if credential contains the right amount of attribute values (Role, OU, EnrollmentId, RevocationHandle)
155+
if len(cred.Attrs) != 4 {
156+
return errors.Errorf("Credential contains %d attribute values, but expected 4", len(cred.Attrs))
130157
}
131158

132159
// Check if credential contains the correct OU attribute value
133160
ouBytes := []byte(conf.Signer.OrganizationalUnitIdentifier)
134-
if !bytes.Equal(idemix.BigToBytes(idemix.HashModOrder(ouBytes)), cred.Attrs[0]) {
161+
if !bytes.Equal(idemix.BigToBytes(idemix.HashModOrder(ouBytes)), cred.Attrs[AttributeIndexOU]) {
135162
return errors.New("Credential does not contain the correct OU attribute value")
136163
}
137164

138-
// Check if credential contains the correct OU attribute value
139-
if !bytes.Equal(idemix.BigToBytes(FP256BN.NewBIGint(int(role.Role))), cred.Attrs[1]) {
165+
// Check if credential contains the correct Role attribute value
166+
if !bytes.Equal(idemix.BigToBytes(FP256BN.NewBIGint(int(role.Role))), cred.Attrs[AttributeIndexRole]) {
140167
return errors.New("Credential does not contain the correct Role attribute value")
141168
}
142169

170+
// Check if credential contains the correct Enrollment ID attribute value
171+
if !bytes.Equal(idemix.BigToBytes(idemix.HashModOrder([]byte(enrollmentId))), cred.Attrs[AttributeIndexEnrollmentId]) {
172+
return errors.New("Credential does not contain the correct enrollment id attribute value")
173+
}
174+
143175
// Verify that the credential is cryptographically valid
144176
err = cred.Ver(sk, msp.ipk)
145177
if err != nil {
@@ -153,7 +185,7 @@ func (msp *idemixmsp) Setup(conf1 *m.MSPConfig) error {
153185
}
154186

155187
// Set up default signer
156-
msp.signer = &idemixSigningIdentity{newIdemixIdentity(msp, Nym, role, ou, proof), rng, cred, sk, RandNym}
188+
msp.signer = &idemixSigningIdentity{newIdemixIdentity(msp, Nym, role, ou, proof), rng, cred, sk, RandNym, enrollmentId}
157189

158190
return nil
159191
}
@@ -295,8 +327,8 @@ func (msp *idemixmsp) SatisfiesPrincipal(id Identity, principal *m.MSPPrincipal)
295327
default:
296328
return errors.Errorf("invalid MSP role type %d", int32(mspRole.Role))
297329
}
298-
// in this case we have to serialize this instance
299-
// and compare it byte-by-byte with Principal
330+
// in this case we have to serialize this instance
331+
// and compare it byte-by-byte with Principal
300332
case m.MSPPrincipal_IDENTITY:
301333
mspLogger.Debugf("Checking if identity satisfies IDENTITY principal")
302334
idBytes, err := id.Serialize()
@@ -473,10 +505,11 @@ func (id *idemixidentity) Serialize() ([]byte, error) {
473505

474506
type idemixSigningIdentity struct {
475507
*idemixidentity
476-
rng *amcl.RAND
477-
Cred *idemix.Credential
478-
Sk *FP256BN.BIG
479-
RandNym *FP256BN.BIG
508+
rng *amcl.RAND
509+
Cred *idemix.Credential
510+
Sk *FP256BN.BIG
511+
RandNym *FP256BN.BIG
512+
enrollmentId string
480513
}
481514

482515
func (id *idemixSigningIdentity) Sign(msg []byte) ([]byte, error) {
172 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
172 Bytes
Binary file not shown.
76 Bytes
Binary file not shown.
172 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
172 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
172 Bytes
Binary file not shown.
76 Bytes
Binary file not shown.
172 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
172 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
��z1�~��(q>�7(UQ�������11�
1+
.H[��N��B�.X���� ��B}e��_�O
172 Bytes
Binary file not shown.
76 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)