Skip to content

Commit

Permalink
[FAB-6843] Integrating Signing Identity
Browse files Browse the repository at this point in the history
This change-set does the following:
- It integrates the SigningIdentity interface in the
TransactionContext class.
A SigningIdentity represents the capability of user to
sign messages. Indeed, a SigningIdentity instance can be
obtanied from an instance of the User interface.
This will simplify the integration of different signing
algorithms like those offered by idemix.

Change-Id: I78eed75938601d42586ac4988040d92896d73e76
Signed-off-by: Angelo De Caro <adc@zurich.ibm.com>
Signed-off-by: Manu Drijvers <mdr@zurich.ibm.com>
Signed-off-by: Rafa Torres <rtm@zurich.ibm.com>
  • Loading branch information
adecaro authored and Saad Karim committed Sep 4, 2018
1 parent 814bf79 commit 5721b15
Show file tree
Hide file tree
Showing 31 changed files with 318 additions and 176 deletions.
11 changes: 7 additions & 4 deletions src/main/java/org/hyperledger/fabric/sdk/Channel.java
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@
import org.hyperledger.fabric.sdk.helper.Config;
import org.hyperledger.fabric.sdk.helper.DiagnosticFileDumper;
import org.hyperledger.fabric.sdk.helper.Utils;
import org.hyperledger.fabric.sdk.identity.IdentityFactory;
import org.hyperledger.fabric.sdk.security.certgen.TLSCertificateBuilder;
import org.hyperledger.fabric.sdk.security.certgen.TLSCertificateKeyPair;
import org.hyperledger.fabric.sdk.transaction.GetConfigBlockBuilder;
Expand Down Expand Up @@ -2243,13 +2244,15 @@ public Collection<ProposalResponse> sendUpgradeProposal(UpgradeProposalRequest u
}
}

private SignedProposal getSignedProposal(TransactionContext transactionContext, FabricProposal.Proposal proposal) throws CryptoException {
private SignedProposal getSignedProposal(TransactionContext transactionContext, FabricProposal.Proposal proposal) throws CryptoException, InvalidArgumentException {

return SignedProposal.newBuilder()
SignedProposal sp;
sp = SignedProposal.newBuilder()
.setProposalBytes(proposal.toByteString())
.setSignature(transactionContext.signByteString(proposal.toByteArray()))
.build();

return sp;
}

private void checkChannelState() throws InvalidArgumentException {
Expand Down Expand Up @@ -4461,11 +4464,11 @@ private String getRespData(BroadcastResponse resp) {

}

private Envelope createTransactionEnvelope(Payload transactionPayload, User user) throws CryptoException {
private Envelope createTransactionEnvelope(Payload transactionPayload, User user) throws CryptoException, InvalidArgumentException {

return Envelope.newBuilder()
.setPayload(transactionPayload.toByteString())
.setSignature(ByteString.copyFrom(client.getCryptoSuite().sign(user.getEnrollment().getKey(), transactionPayload.toByteArray())))
.setSignature(ByteString.copyFrom(IdentityFactory.getSigningIdentity(client.getCryptoSuite(), user).sign(transactionPayload.toByteArray())))
.build();

}
Expand Down
4 changes: 2 additions & 2 deletions src/main/java/org/hyperledger/fabric/sdk/EventHub.java
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,7 @@ public void onCompleted() {
sender = events.chat(eventStreamLocal);
try {
blockListen(transactionContext);
} catch (CryptoException e) {
} catch (Exception e) {
throw new EventHubException(e);
}

Expand Down Expand Up @@ -338,7 +338,7 @@ private void reconnect() throws EventHubException {

}

private void blockListen(TransactionContext transactionContext) throws CryptoException {
private void blockListen(TransactionContext transactionContext) throws CryptoException, InvalidArgumentException {

this.transactionContext = transactionContext;

Expand Down
34 changes: 20 additions & 14 deletions src/main/java/org/hyperledger/fabric/sdk/NetworkConfig.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import java.io.InputStream;
import java.io.Reader;
import java.io.StringReader;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivateKey;
import java.util.ArrayList;
import java.util.Collection;
Expand Down Expand Up @@ -52,8 +53,13 @@
import org.bouncycastle.openssl.jcajce.JcaPEMKeyConverter;
import org.hyperledger.fabric.sdk.Channel.PeerOptions;
import org.hyperledger.fabric.sdk.Peer.PeerRole;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.exception.NetworkConfigurationException;
import org.hyperledger.fabric.sdk.identity.SigningIdentity;
import org.hyperledger.fabric.sdk.identity.X509Enrollment;
import org.hyperledger.fabric.sdk.identity.X509SigningIdentity;
import org.hyperledger.fabric.sdk.security.CryptoSuite;
import org.yaml.snakeyaml.Yaml;

import static java.lang.String.format;
Expand Down Expand Up @@ -851,18 +857,12 @@ private OrgInfo createOrg(String orgName, JsonObject jsonOrg, Map<String, JsonOb

final PrivateKey privateKeyFinal = privateKey;

org.peerAdmin = new UserInfo(mspId, "PeerAdmin_" + mspId + "_" + orgName, null);
org.peerAdmin.setEnrollment(new Enrollment() {
@Override
public PrivateKey getKey() {
return privateKeyFinal;
}

@Override
public String getCert() {
return signedCert;
}
});
try {
org.peerAdmin = new UserInfo(CryptoSuite.Factory.getCryptoSuite(), mspId, "PeerAdmin_" + mspId + "_" + orgName, null);
} catch (Exception e) {
throw new NetworkConfigurationException(e.getMessage(), e);
}
org.peerAdmin.setEnrollment(new X509Enrollment(privateKeyFinal, signedCert));

}

Expand Down Expand Up @@ -932,7 +932,11 @@ private CAInfo createCA(String name, JsonObject jsonCA, OrgInfo org) throws Netw
for (JsonObject reg : registrars) {
enrollId = getJsonValueAsString(reg.get("enrollId"));
enrollSecret = getJsonValueAsString(reg.get("enrollSecret"));
regUsers.add(new UserInfo(org.mspId, enrollId, enrollSecret));
try {
regUsers.add(new UserInfo(CryptoSuite.Factory.getCryptoSuite(), org.mspId, enrollId, enrollSecret));
} catch (Exception e) {
throw new NetworkConfigurationException(e.getMessage(), e);
}
}
}

Expand Down Expand Up @@ -1132,6 +1136,7 @@ public void setName(String name) {
private String account;
private String affiliation;
private Enrollment enrollment;
private CryptoSuite suite;

public void setEnrollSecret(String enrollSecret) {
this.enrollSecret = enrollSecret;
Expand Down Expand Up @@ -1161,7 +1166,8 @@ public void setEnrollment(Enrollment enrollment) {
this.enrollment = enrollment;
}

UserInfo(String mspid, String name, String enrollSecret) {
UserInfo(CryptoSuite suite, String mspid, String name, String enrollSecret) {
this.suite = suite;
this.name = name;
this.enrollSecret = enrollSecret;
this.mspid = mspid;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -392,7 +392,7 @@ void peerVent(TransactionContext transactionContext) throws TransactionException

clientTLSCertificateDigest);
connectEnvelope(envelope);
} catch (CryptoException e) {
} catch (Exception e) {
throw new TransactionException(e);
}

Expand Down
1 change: 1 addition & 0 deletions src/main/java/org/hyperledger/fabric/sdk/User.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.helper.Utils;
import org.hyperledger.fabric.sdk.identity.SigningIdentity;

import static java.lang.String.format;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -174,4 +174,4 @@ Idemix.Credential toProto() {

return builder.build();
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package org.hyperledger.fabric.sdk.identity;

import java.security.KeyPair;
import java.security.PrivateKey;

import org.hyperledger.fabric.sdk.Enrollment;

public class IdemixEnrollment implements Enrollment {

private KeyPair key;
private String cert;

public IdemixEnrollment(KeyPair signingKeyPair, String signedPem) {
this.key = signingKeyPair;
this.cert = signedPem;
}

public PrivateKey getKey() {
return key.getPrivate();
}

public String getCert() {
return cert;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package org.hyperledger.fabric.sdk.identity;

import org.hyperledger.fabric.sdk.Enrollment;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.security.CryptoSuite;

public class IdentityFactory {
private IdentityFactory() {
// private constructor for utility class
}

public static SigningIdentity getSigningIdentity(CryptoSuite cryptoSuite, User user) {
Enrollment enrollment = user.getEnrollment();

if (enrollment instanceof X509Enrollment) {
return new X509SigningIdentity(cryptoSuite, user);
}

throw new IllegalStateException("Invalid enrollment. Expected X509Enrollment. " + enrollment);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package org.hyperledger.fabric.sdk.identity;

import java.io.Serializable;
import java.security.KeyPair;
import java.security.PrivateKey;

import org.hyperledger.fabric.sdk.Enrollment;

public class X509Enrollment implements Enrollment, Serializable {

private PrivateKey key;
private String cert;

public X509Enrollment(KeyPair signingKeyPair, String signedPem) {
key = signingKeyPair.getPrivate();
this.cert = signedPem;
}

public X509Enrollment(PrivateKey key, String signedPem) {
this.key = key;
this.cert = signedPem;
}

public PrivateKey getKey() {
return key;
}

public String getCert() {
return cert;
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package org.hyperledger.fabric.sdk.identity;

import org.hyperledger.fabric.protos.msp.Identities;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.transaction.ProtoUtils;

public class X509Identity implements Identity {

protected User user;

public X509Identity(User user) {
if (user == null) {
throw new IllegalArgumentException("User is null");
}
if (user.getEnrollment() == null) {
throw new IllegalArgumentException("user.getEnrollment() is null");
}
if (user.getEnrollment().getCert() == null) {
throw new IllegalArgumentException("user.getEnrollment().getCert() is null");
}

this.user = user;
}

@Override
public Identities.SerializedIdentity createSerializedIdentity() {
return ProtoUtils.createSerializedIdentity(user);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
package org.hyperledger.fabric.sdk.identity;

import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.security.CryptoSuite;

public class X509SigningIdentity extends X509Identity implements SigningIdentity {

private CryptoSuite cryptoSuite;

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

if (cryptoSuite == null) {
throw new IllegalArgumentException("CryptoSuite is null");
}

this.cryptoSuite = cryptoSuite;
}

@Override
public byte[] sign(byte[] msg) throws CryptoException {
return cryptoSuite.sign(super.user.getEnrollment().getKey(), msg);
}

@Override
public boolean verifySignature(byte[] msg, byte[] sig) throws CryptoException {
throw new CryptoException("Not Implemented yet!!!");
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -713,6 +713,13 @@ private static BigInteger[] decodeECDSASignature(byte[] signature) throws Except
* @throws CryptoException
*/
private byte[] ecdsaSignToBytes(ECPrivateKey privateKey, byte[] data) throws CryptoException {
if (data == null) {
throw new CryptoException("Data that to be signed is null.");
}
if (data.length == 0) {
throw new CryptoException("Data to be signed was empty.");
}

try {
X9ECParameters params = ECNamedCurveTable.getByName(curveName);
BigInteger curveN = params.getN();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
import org.hyperledger.fabric.protos.peer.FabricProposal.ChaincodeHeaderExtension;
import org.hyperledger.fabric.sdk.User;
import org.hyperledger.fabric.sdk.exception.CryptoException;
import org.hyperledger.fabric.sdk.exception.InvalidArgumentException;
import org.hyperledger.fabric.sdk.security.CryptoPrimitives;
import org.hyperledger.fabric.sdk.security.CryptoSuite;

Expand Down Expand Up @@ -187,7 +188,7 @@ public static ByteString getSignatureHeaderAsByteString(TransactionContext trans

public static ByteString getSignatureHeaderAsByteString(User user, TransactionContext transactionContext) {

final Identities.SerializedIdentity identity = ProtoUtils.createSerializedIdentity(user);
final Identities.SerializedIdentity identity = transactionContext.getSerializedIdentity();

if (isDebugLevel) {

Expand Down Expand Up @@ -253,7 +254,7 @@ static Timestamp getTimestampFromDate(Date date) {
.setNanos((int) ((millis % 1000) * 1000000)).build();
}

public static Envelope createSeekInfoEnvelope(TransactionContext transactionContext, SeekInfo seekInfo, byte[] tlsCertHash) throws CryptoException {
public static Envelope createSeekInfoEnvelope(TransactionContext transactionContext, SeekInfo seekInfo, byte[] tlsCertHash) throws CryptoException, InvalidArgumentException {

ChannelHeader seekInfoHeader = createChannelHeader(Common.HeaderType.DELIVER_SEEK_INFO,
transactionContext.getTxID(), transactionContext.getChannelID(), transactionContext.getEpoch(),
Expand Down Expand Up @@ -282,7 +283,7 @@ public static Envelope createSeekInfoEnvelope(TransactionContext transactionCont

public static Envelope createSeekInfoEnvelope(TransactionContext transactionContext, SeekPosition startPosition,
SeekPosition stopPosition,
SeekBehavior seekBehavior, byte[] tlsCertHash) throws CryptoException {
SeekBehavior seekBehavior, byte[] tlsCertHash) throws CryptoException, InvalidArgumentException {

return createSeekInfoEnvelope(transactionContext, SeekInfo.newBuilder()
.setStart(startPosition)
Expand Down
Loading

0 comments on commit 5721b15

Please sign in to comment.