Skip to content
This repository was archived by the owner on Apr 22, 2025. It is now read-only.

Commit 3a600c2

Browse files
adecaroSaad Karim
authored andcommitted
[FAB-6843] Adding IdemixUser
This change-set does the following: - It introduces an Idemix implementation of the User interface called IdemixUser. - An IdemixUserStore class have been added to load instances of IdemixUser. - Support tests Change-Id: I9b8c4f2aacb132e6cb0b74c0ea3ccbeb61ef63be Signed-off-by: Angelo De Caro <adc@zurich.ibm.com> Signed-off-by: Manu Drijvers (mdr@zurich.ibm.com)
1 parent 5721b15 commit 3a600c2

File tree

15 files changed

+310
-54
lines changed

15 files changed

+310
-54
lines changed

src/main/java/org/hyperledger/fabric/sdk/User.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
2020
import org.hyperledger.fabric.sdk.helper.Utils;
21-
import org.hyperledger.fabric.sdk.identity.SigningIdentity;
2221

2322
import static java.lang.String.format;
2423

src/main/java/org/hyperledger/fabric/sdk/identity/IdemixEnrollment.java

Lines changed: 57 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,25 +2,77 @@
22

33
import java.security.KeyPair;
44
import java.security.PrivateKey;
5+
import java.security.PublicKey;
56

7+
import org.apache.milagro.amcl.FP256BN.BIG;
8+
import org.hyperledger.fabric.protos.idemix.Idemix.CredentialRevocationInformation;
69
import org.hyperledger.fabric.sdk.Enrollment;
10+
import org.hyperledger.fabric.sdk.idemix.IdemixCredential;
11+
import org.hyperledger.fabric.sdk.idemix.IdemixIssuerPublicKey;
712

813
public class IdemixEnrollment implements Enrollment {
914

15+
16+
protected final IdemixIssuerPublicKey ipk;
17+
protected final PublicKey revocationPk;
18+
protected final String mspId;
19+
protected final BIG sk;
20+
protected final IdemixCredential cred;
21+
protected final CredentialRevocationInformation cri;
22+
protected final String ou;
23+
protected final boolean role;
24+
1025
private KeyPair key;
1126
private String cert;
1227

13-
public IdemixEnrollment(KeyPair signingKeyPair, String signedPem) {
14-
this.key = signingKeyPair;
15-
this.cert = signedPem;
28+
public IdemixEnrollment(IdemixIssuerPublicKey ipk, PublicKey revocationPk, String mspId, BIG sk, IdemixCredential cred, CredentialRevocationInformation cri, String ou, boolean role) {
29+
this.ipk = ipk;
30+
this.revocationPk = revocationPk;
31+
this.mspId = mspId;
32+
this.sk = sk;
33+
this.cred = cred;
34+
this.cri = cri;
35+
this.ou = ou;
36+
this.role = role;
1637
}
1738

1839
public PrivateKey getKey() {
19-
return key.getPrivate();
40+
return null;
2041
}
2142

2243
public String getCert() {
23-
return cert;
44+
return null;
2445
}
2546

47+
public IdemixIssuerPublicKey getIpk() {
48+
return this.ipk;
49+
}
50+
51+
public PublicKey getRevocationPk() {
52+
return this.revocationPk;
53+
}
54+
55+
public String getMspId() {
56+
return this.mspId;
57+
}
58+
59+
public BIG getSk() {
60+
return this.sk;
61+
}
62+
63+
public IdemixCredential getCred() {
64+
return this.cred;
65+
}
66+
67+
public CredentialRevocationInformation getCri() {
68+
return this.cri;
69+
}
70+
71+
public String getOu() {
72+
return this.ou;
73+
}
74+
75+
public boolean getRole() {
76+
return this.role;
77+
}
2678
}

src/main/java/org/hyperledger/fabric/sdk/identity/IdemixIdentity.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ public class IdemixIdentity implements Identity {
4545
// MSP identifier
4646
private final String mspId;
4747

48+
// Issuer public key hash
4849
private final byte[] ipkHash;
4950

5051
// Idemix Pseudonym

src/main/java/org/hyperledger/fabric/sdk/identity/IdemixSigningIdentity.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,11 @@ public class IdemixSigningIdentity implements SigningIdentity {
7878

7979
private static final Log logger = LogFactory.getLog(IdemixSigningIdentity.class);
8080

81+
public IdemixSigningIdentity(IdemixEnrollment enrollment) throws CryptoException, InvalidArgumentException {
82+
this(enrollment.ipk, enrollment.revocationPk, enrollment.mspId, enrollment.sk, enrollment.cred,
83+
enrollment.cri, enrollment.ou, enrollment.role);
84+
}
85+
8186
/**
8287
* Create new Idemix Signing Identity with a fresh pseudonym
8388
*

src/main/java/org/hyperledger/fabric/sdk/identity/IdentityFactory.java

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package org.hyperledger.fabric.sdk.identity;
22

3+
import org.apache.commons.logging.Log;
4+
import org.apache.commons.logging.LogFactory;
35
import org.hyperledger.fabric.sdk.Enrollment;
46
import org.hyperledger.fabric.sdk.User;
57
import org.hyperledger.fabric.sdk.security.CryptoSuite;
@@ -12,11 +14,19 @@ private IdentityFactory() {
1214
public static SigningIdentity getSigningIdentity(CryptoSuite cryptoSuite, User user) {
1315
Enrollment enrollment = user.getEnrollment();
1416

15-
if (enrollment instanceof X509Enrollment) {
16-
return new X509SigningIdentity(cryptoSuite, user);
17+
try {
18+
if (enrollment instanceof X509Enrollment) {
19+
return new X509SigningIdentity(cryptoSuite, user);
20+
}
21+
22+
if (enrollment instanceof IdemixEnrollment) {
23+
return new IdemixSigningIdentity((IdemixEnrollment) enrollment);
24+
}
25+
} catch (Exception e) {
26+
throw new IllegalStateException(e.getMessage(), e);
1727
}
1828

19-
throw new IllegalStateException("Invalid enrollment. Expected X509Enrollment. " + enrollment);
29+
throw new IllegalStateException("Invalid enrollment. Expected either X509Enrollment or IdemixEnrollment." + enrollment);
2030
}
2131

2232
}

src/main/java/org/hyperledger/fabric/sdk/identity/X509Enrollment.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,11 @@
88

99
public class X509Enrollment implements Enrollment, Serializable {
1010

11-
private PrivateKey key;
12-
private String cert;
11+
private final PrivateKey key;
12+
private final String cert;
1313

1414
public X509Enrollment(KeyPair signingKeyPair, String signedPem) {
15-
key = signingKeyPair.getPrivate();
15+
this.key = signingKeyPair.getPrivate();
1616
this.cert = signedPem;
1717
}
1818

src/main/java/org/hyperledger/fabric/sdk/identity/X509Identity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
public class X509Identity implements Identity {
88

9-
protected User user;
9+
protected final User user;
1010

1111
public X509Identity(User user) {
1212
if (user == null) {

src/main/java/org/hyperledger/fabric/sdk/identity/X509SigningIdentity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66

77
public class X509SigningIdentity extends X509Identity implements SigningIdentity {
88

9-
private CryptoSuite cryptoSuite;
9+
private final CryptoSuite cryptoSuite;
1010

1111
public X509SigningIdentity(CryptoSuite cryptoSuite, User user) {
1212
super(user);

src/main/java/org/hyperledger/fabric/sdk/transaction/TransactionContext.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -232,9 +232,7 @@ public ByteString[] signByteStrings(User[] users, ByteString... bs) throws Crypt
232232
}
233233

234234
public TransactionContext retryTransactionSameContext() {
235-
236235
return new TransactionContext(channel, user, cryptoPrimitives);
237-
238236
}
239237

240238
public Identities.SerializedIdentity getSerializedIdentity() {
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
package org.hyperledger.fabric.sdk.user;
2+
3+
import java.security.PublicKey;
4+
import java.util.Set;
5+
6+
import org.apache.milagro.amcl.FP256BN.BIG;
7+
import org.hyperledger.fabric.protos.idemix.Idemix;
8+
import org.hyperledger.fabric.sdk.Enrollment;
9+
import org.hyperledger.fabric.sdk.User;
10+
import org.hyperledger.fabric.sdk.exception.CryptoException;
11+
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
12+
import org.hyperledger.fabric.sdk.idemix.IdemixCredential;
13+
import org.hyperledger.fabric.sdk.idemix.IdemixIssuerPublicKey;
14+
import org.hyperledger.fabric.sdk.identity.IdemixEnrollment;
15+
import org.hyperledger.fabric.sdk.identity.IdemixSigningIdentity;
16+
import org.hyperledger.fabric.sdk.identity.SigningIdentity;
17+
18+
public class IdemixUser implements User {
19+
20+
protected final String name;
21+
protected final String mspId;
22+
protected final IdemixEnrollment enrollment;
23+
24+
public IdemixUser(String name, String mspId, IdemixEnrollment enrollment) {
25+
this.name = name;
26+
this.mspId = mspId;
27+
this.enrollment = enrollment;
28+
}
29+
30+
@Override
31+
public String getName() {
32+
return this.name;
33+
}
34+
35+
@Override
36+
public Set<String> getRoles() {
37+
return null;
38+
}
39+
40+
@Override
41+
public String getAccount() {
42+
return null;
43+
}
44+
45+
@Override
46+
public String getAffiliation() {
47+
return null;
48+
}
49+
50+
@Override
51+
public Enrollment getEnrollment() {
52+
return this.enrollment;
53+
}
54+
55+
@Override
56+
public String getMspId() {
57+
return this.mspId;
58+
}
59+
60+
public IdemixIssuerPublicKey getIpk() {
61+
return this.enrollment.getIpk();
62+
}
63+
64+
public IdemixCredential getIdemixCredential() {
65+
return this.enrollment.getCred();
66+
}
67+
68+
public Idemix.CredentialRevocationInformation getCri() {
69+
return this.enrollment.getCri();
70+
}
71+
72+
public BIG getSk() {
73+
return this.enrollment.getSk();
74+
}
75+
76+
public PublicKey getRevocationPk() {
77+
return this.enrollment.getRevocationPk();
78+
}
79+
80+
public String getOu() {
81+
return this.enrollment.getOu();
82+
}
83+
84+
public boolean getRole() {
85+
return this.enrollment.getRole();
86+
}
87+
}
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
package org.hyperledger.fabric.sdk.user;
2+
3+
import java.io.IOException;
4+
import java.nio.file.Files;
5+
import java.nio.file.Path;
6+
import java.nio.file.Paths;
7+
import java.security.KeyFactory;
8+
import java.security.NoSuchAlgorithmException;
9+
import java.security.PublicKey;
10+
import java.security.spec.InvalidKeySpecException;
11+
import java.security.spec.X509EncodedKeySpec;
12+
13+
import com.google.protobuf.InvalidProtocolBufferException;
14+
import org.apache.milagro.amcl.FP256BN.BIG;
15+
import org.hyperledger.fabric.protos.idemix.Idemix;
16+
import org.hyperledger.fabric.protos.msp.MspConfig;
17+
import org.hyperledger.fabric.sdk.User;
18+
import org.hyperledger.fabric.sdk.exception.CryptoException;
19+
import org.hyperledger.fabric.sdk.idemix.IdemixCredential;
20+
import org.hyperledger.fabric.sdk.idemix.IdemixIssuerPublicKey;
21+
import org.hyperledger.fabric.sdk.identity.IdemixEnrollment;
22+
23+
public class IdemixUserStore {
24+
25+
private static final String USER_PATH = "user";
26+
private static final String VERIFIER_PATH = "msp";
27+
private static final String IPK_CONFIG = "IssuerPublicKey";
28+
private static final String REVOCATION_PUBLIC_KEY = "RevocationPublicKey";
29+
30+
31+
protected final String storePath;
32+
protected final String mspId;
33+
protected final IdemixIssuerPublicKey ipk;
34+
35+
public IdemixUserStore(String storePath, String mspId) throws CryptoException {
36+
this.storePath = storePath;
37+
this.mspId = mspId;
38+
Idemix.IssuerPublicKey ipkProto = readIdemixIssuerPublicKey(Paths.get(mspId, VERIFIER_PATH + IPK_CONFIG).toString());
39+
this.ipk = new IdemixIssuerPublicKey(ipkProto);
40+
if (!this.ipk.check()) {
41+
throw new CryptoException("Failed verifying issuer public key.");
42+
}
43+
}
44+
45+
public User getUser(String id) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
46+
MspConfig.IdemixMSPSignerConfig signerConfig = readIdemixMSPConfig(Paths.get(this.mspId, USER_PATH + id).toString());
47+
PublicKey revocationPk = readIdemixRevocationPublicKey(this.mspId);
48+
BIG sk = BIG.fromBytes(signerConfig.getSk().toByteArray());
49+
IdemixCredential cred = new IdemixCredential(Idemix.Credential.parseFrom(signerConfig.getCred()));
50+
Idemix.CredentialRevocationInformation cri = Idemix.CredentialRevocationInformation.parseFrom(signerConfig.getCredentialRevocationInformation());
51+
52+
IdemixEnrollment enrollment = new IdemixEnrollment(this.ipk, revocationPk, this.mspId, sk, cred, cri, signerConfig.getOrganizationalUnitIdentifier(), signerConfig.getIsAdmin());
53+
return new IdemixUser(id, this.mspId, enrollment);
54+
}
55+
56+
/**
57+
* Helper function: parse Idemix MSP Signer config (is part of the MSPConfig proto) from path
58+
*
59+
* @param id
60+
* @return IdemixMSPSignerConfig proto
61+
*/
62+
protected MspConfig.IdemixMSPSignerConfig readIdemixMSPConfig(String id) throws IOException {
63+
Path path = Paths.get(this.storePath + id);
64+
return MspConfig.IdemixMSPSignerConfig.parseFrom(Files.readAllBytes(path));
65+
}
66+
67+
/**
68+
* Parse Idemix issuer public key from the config file
69+
*
70+
* @param id
71+
* @return Idemix IssuerPublicKey proto
72+
*/
73+
protected Idemix.IssuerPublicKey readIdemixIssuerPublicKey(String id) {
74+
Path path = Paths.get(this.storePath + id);
75+
byte[] data = null;
76+
try {
77+
data = Files.readAllBytes(path);
78+
} catch (IOException e) {
79+
e.printStackTrace();
80+
}
81+
82+
Idemix.IssuerPublicKey ipk = null;
83+
84+
try {
85+
ipk = Idemix.IssuerPublicKey.parseFrom(data);
86+
} catch (InvalidProtocolBufferException e) {
87+
e.printStackTrace();
88+
}
89+
90+
return ipk;
91+
}
92+
93+
/**
94+
* Parse Idemix long-term revocation public key
95+
*
96+
* @param id
97+
* @return idemix long-term revocation public key
98+
*/
99+
protected PublicKey readIdemixRevocationPublicKey(String id) throws IOException, NoSuchAlgorithmException, InvalidKeySpecException {
100+
Path path = Paths.get(this.mspId, VERIFIER_PATH + id);
101+
return KeyFactory.getInstance("EC").generatePublic(new X509EncodedKeySpec(Files.readAllBytes(path)));
102+
}
103+
}

0 commit comments

Comments
 (0)