Skip to content

Commit 4ad504a

Browse files
author
Manu Drijvers
committed
[FAB-8921] include idemix revocation data in conf
The idemix signer config now includes the idemix credential revocation information, which it will use to create non-revoked proofs. The idemixgen tool has been updated accordingly. Change-Id: I02fe60c5fa5157fd266b2a1e2b6c3acb905c8d30 Signed-off-by: Manu Drijvers <mdr@zurich.ibm.com>
1 parent 9570d47 commit 4ad504a

36 files changed

+140
-72
lines changed

common/tools/idemixgen/idemixca/idemixca.go

+18-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ SPDX-License-Identifier: Apache-2.0
77
package idemixca
88

99
import (
10+
"crypto/ecdsa"
11+
1012
"github.com/golang/protobuf/proto"
1113
"github.com/hyperledger/fabric-amcl/amcl/FP256BN"
1214
"github.com/hyperledger/fabric/idemix"
@@ -37,15 +39,10 @@ func GenerateIssuerKey() ([]byte, []byte, error) {
3739
return key.ISk, ipkSerialized, err
3840
}
3941

40-
// GenerateMSPConfig creates a new MSP config.
41-
// If the new MSP config contains a signer then
42-
// it generates a fresh user secret and issues a credential
43-
// with four attributes (described above)
44-
// using the CA's key pair from the file.
45-
// If the new MSP config does not contain a signer
46-
// (meaning it is used only for verification)
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) {
42+
// GenerateSignerConfig creates a new signer config.
43+
// It generates a fresh user secret and issues a credential
44+
// with four attributes (described above) using the CA's key pair.
45+
func GenerateSignerConfig(isAdmin bool, ouString string, enrollmentId string, revocationHandle int, key *idemix.IssuerKey, revKey *ecdsa.PrivateKey) ([]byte, error) {
4946
attrs := make([]*FP256BN.BIG, 4)
5047

5148
if ouString == "" {
@@ -84,12 +81,24 @@ func GenerateSignerConfig(isAdmin bool, ouString string, enrollmentId string, re
8481
return nil, errors.WithMessage(err, "failed to marshal credential")
8582
}
8683

84+
// NOTE currently, idemixca creates CRI's with "ALG_NO_REVOCATION"
85+
cri, err := idemix.CreateCRI(revKey, []*FP256BN.BIG{FP256BN.NewBIGint(revocationHandle)}, 0, idemix.ALG_NO_REVOCATION, rng)
86+
if err != nil {
87+
return nil, err
88+
}
89+
criBytes, err := proto.Marshal(cri)
90+
if err != nil {
91+
return nil, errors.WithMessage(err, "failed to marshal CRI")
92+
}
93+
8794
signer := &m.IdemixMSPSignerConfig{
8895
credBytes,
8996
idemix.BigToBytes(sk),
9097
ouString,
9198
isAdmin,
9299
enrollmentId,
100+
criBytes,
93101
}
102+
94103
return proto.Marshal(signer)
95104
}

common/tools/idemixgen/idemixca/idemixca_test.go

+21-7
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ import (
1212
"path/filepath"
1313
"testing"
1414

15+
"crypto/elliptic"
16+
1517
"github.com/golang/protobuf/proto"
1618
"github.com/hyperledger/fabric/idemix"
1719
m "github.com/hyperledger/fabric/msp"
@@ -28,21 +30,24 @@ func TestIdemixCa(t *testing.T) {
2830
isk, ipkBytes, err := GenerateIssuerKey()
2931
assert.NoError(t, err)
3032

33+
revocationkey, err := idemix.GenerateLongTermRevocationKey()
34+
assert.NoError(t, err)
35+
3136
ipk := &idemix.IssuerPublicKey{}
3237
err = proto.Unmarshal(ipkBytes, ipk)
3338
assert.NoError(t, err)
3439

35-
writeVerifierToFile(ipkBytes)
40+
writeVerifierToFile(ipkBytes, elliptic.Marshal(elliptic.P384(), revocationkey.X, revocationkey.Y))
3641

3742
key := &idemix.IssuerKey{isk, ipk}
3843

39-
conf, err := GenerateSignerConfig(false, "OU1", "enrollmentid1", 1, key)
44+
conf, err := GenerateSignerConfig(false, "OU1", "enrollmentid1", 1, key, revocationkey)
4045
assert.NoError(t, err)
4146
cleanupSigner()
4247
assert.NoError(t, writeSignerToFile(conf))
4348
assert.NoError(t, setupMSP())
4449

45-
conf, err = GenerateSignerConfig(true, "OU1", "enrollmentid2", 1234, key)
50+
conf, err = GenerateSignerConfig(true, "OU1", "enrollmentid2", 1234, key, revocationkey)
4651
assert.NoError(t, err)
4752
cleanupSigner()
4853
assert.NoError(t, writeSignerToFile(conf))
@@ -52,10 +57,10 @@ func TestIdemixCa(t *testing.T) {
5257
cleanupVerifier()
5358
assert.Error(t, setupMSP())
5459

55-
_, err = GenerateSignerConfig(true, "", "enrollmentid", 1, key)
60+
_, err = GenerateSignerConfig(true, "", "enrollmentid", 1, key, revocationkey)
5661
assert.EqualError(t, err, "the OU attribute value is empty")
5762

58-
_, err = GenerateSignerConfig(true, "OU1", "", 1, key)
63+
_, err = GenerateSignerConfig(true, "OU1", "", 1, key, revocationkey)
5964
assert.EqualError(t, err, "the enrollment id value is empty")
6065
}
6166

@@ -76,12 +81,17 @@ func cleanupVerifier() {
7681
os.RemoveAll(filepath.Join(testDir, m.IdemixConfigDirMsp))
7782
}
7883

79-
func writeVerifierToFile(ipkBytes []byte) error {
84+
func writeVerifierToFile(ipkBytes []byte, revpkBytes []byte) error {
8085
err := os.Mkdir(filepath.Join(testDir, m.IdemixConfigDirMsp), os.ModePerm)
8186
if err != nil {
8287
return err
8388
}
84-
return ioutil.WriteFile(filepath.Join(testDir, m.IdemixConfigDirMsp, m.IdemixConfigFileIssuerPublicKey), ipkBytes, 0644)
89+
err = ioutil.WriteFile(filepath.Join(testDir, m.IdemixConfigDirMsp, m.IdemixConfigFileIssuerPublicKey), ipkBytes, 0644)
90+
if err != nil {
91+
return err
92+
}
93+
94+
return ioutil.WriteFile(filepath.Join(testDir, m.IdemixConfigDirMsp, m.IdemixConfigFileRevocationPublicKey), revpkBytes, 0644)
8595
}
8696

8797
func writeSignerToFile(signerBytes []byte) error {
@@ -102,5 +112,9 @@ func setupMSP() error {
102112
}
103113
mspConfig, err := m.GetIdemixMspConfig(testDir, "TestName")
104114

115+
if err != nil {
116+
return err
117+
}
118+
105119
return msp.Setup(mspConfig)
106120
}

common/tools/idemixgen/idemixgen.go

+27-1
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,16 @@ package main
1212
// the Identity Mixer MSP
1313

1414
import (
15+
"crypto/x509"
1516
"fmt"
1617
"io/ioutil"
1718
"os"
1819
"path/filepath"
1920

21+
"crypto/elliptic"
22+
23+
"crypto/ecdsa"
24+
2025
"github.com/golang/protobuf/proto"
2126
"github.com/hyperledger/fabric/common/tools/idemixgen/idemixca"
2227
"github.com/hyperledger/fabric/idemix"
@@ -29,6 +34,7 @@ import (
2934
const (
3035
IdemixDirIssuer = "ca"
3136
IdemixConfigIssuerSecretKey = "IssuerSecretKey"
37+
IdemixConfigRevocationKey = "RevocationKey"
3238
)
3339

3440
// command line flags
@@ -54,6 +60,12 @@ func main() {
5460
isk, ipk, err := idemixca.GenerateIssuerKey()
5561
handleError(err)
5662

63+
revocationKey, err := idemix.GenerateLongTermRevocationKey()
64+
handleError(err)
65+
revocationKeyBytes, err := x509.MarshalECPrivateKey(revocationKey)
66+
handleError(err)
67+
revocationPkBytes := elliptic.Marshal(elliptic.P384(), revocationKey.X, revocationKey.Y)
68+
5769
// Prevent overwriting the existing key
5870
path := filepath.Join(IdemixDirIssuer)
5971
checkDirectoryNotExists(path, fmt.Sprintf("Directory %s already exists", path))
@@ -65,11 +77,13 @@ func main() {
6577
handleError(os.Mkdir(IdemixDirIssuer, 0770))
6678
handleError(os.Mkdir(msp.IdemixConfigDirMsp, 0770))
6779
writeFile(filepath.Join(IdemixDirIssuer, IdemixConfigIssuerSecretKey), isk)
80+
writeFile(filepath.Join(IdemixDirIssuer, IdemixConfigRevocationKey), revocationKeyBytes)
6881
writeFile(filepath.Join(IdemixDirIssuer, msp.IdemixConfigFileIssuerPublicKey), ipk)
82+
writeFile(filepath.Join(msp.IdemixConfigDirMsp, msp.IdemixConfigFileRevocationPublicKey), revocationPkBytes)
6983
writeFile(filepath.Join(msp.IdemixConfigDirMsp, msp.IdemixConfigFileIssuerPublicKey), ipk)
7084

7185
case genSignerConfig.FullCommand():
72-
config, err := idemixca.GenerateSignerConfig(*genCredIsAdmin, *genCredOU, *genCredEnrollmentId, *genCredRevocationHandle, readIssuerKey())
86+
config, err := idemixca.GenerateSignerConfig(*genCredIsAdmin, *genCredOU, *genCredEnrollmentId, *genCredRevocationHandle, readIssuerKey(), readRevocationKey())
7387
handleError(err)
7488

7589
path := msp.IdemixConfigDirUser
@@ -112,6 +126,18 @@ func readIssuerKey() *idemix.IssuerKey {
112126
return key
113127
}
114128

129+
func readRevocationKey() *ecdsa.PrivateKey {
130+
path := filepath.Join(IdemixDirIssuer, IdemixConfigRevocationKey)
131+
keyBytes, err := ioutil.ReadFile(path)
132+
if err != nil {
133+
handleError(errors.Wrapf(err, "failed to open revocation secret key file: %s", path))
134+
}
135+
key, err := x509.ParseECPrivateKey(keyBytes)
136+
handleError(err)
137+
138+
return key
139+
}
140+
115141
// checkDirectoryNotExists checks whether a directory with the given path already exists and exits if this is the case
116142
func checkDirectoryNotExists(path string, errorMessage string) {
117143
_, err := os.Stat(path)

idemix/revocation_authority.go

+2
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ func GenerateLongTermRevocationKey() (*ecdsa.PrivateKey, error) {
3939

4040
// CreateCRI creates the Credential Revocation Information for a certain time period (epoch).
4141
// Users can use the CRI to prove that they are not revoked.
42+
// Note that when not using revocation (i.e., alg = ALG_NO_REVOCATION), the entered unrevokedHandles are not used,
43+
// and the resulting CRI can be used by any signer.
4244
func CreateCRI(key *ecdsa.PrivateKey, unrevokedHandles []*FP256BN.BIG, epoch int, alg RevocationAlgorithm, rng *amcl.RAND) (*CredentialRevocationInformation, error) {
4345
if key == nil || rng == nil {
4446
return nil, errors.Errorf("CreateCRI received nil input")

msp/configbuilder.go

+5-4
Original file line numberDiff line numberDiff line change
@@ -358,10 +358,11 @@ func getMspConfig(dir string, ID string, sigid *msp.SigningIdentityInfo) (*msp.M
358358
}
359359

360360
const (
361-
IdemixConfigDirMsp = "msp"
362-
IdemixConfigDirUser = "user"
363-
IdemixConfigFileIssuerPublicKey = "IssuerPublicKey"
364-
IdemixConfigFileSigner = "SignerConfig"
361+
IdemixConfigDirMsp = "msp"
362+
IdemixConfigDirUser = "user"
363+
IdemixConfigFileIssuerPublicKey = "IssuerPublicKey"
364+
IdemixConfigFileRevocationPublicKey = "RevocationPublicKey"
365+
IdemixConfigFileSigner = "SignerConfig"
365366
)
366367

367368
// GetIdemixMspConfig returns the configuration for the Idemix MSP
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
167 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
Binary file not shown.
243 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
167 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
238 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
167 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.
Binary file not shown.
243 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
167 Bytes
Binary file not shown.
Binary file not shown.
Binary file not shown.
0 Bytes
Binary file not shown.
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
.H[��N��B�.X���� ��B}e��_�O�
1+
"�B�ݢxʱL���\tybõC<d.��!
167 Bytes
Binary file not shown.
0 Bytes
Binary file not shown.

msp/testdata/idemix/MSP2OU1/msp/RevocationPublicKey

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
~��g ��,Ȗ����ӽ��ݚv(]�M�@�~6����:~�,k��p����9''�8��vDx�>U�?Z�(
2+
�%� 5�������V*������
243 Bytes
Binary file not shown.

protos/msp/msp_config.pb.go

+61-50
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)