我正在尝试使用 Hyperledger Fabric Java SDK 来调用链代码事务,但在 channel.initialize() 中出现以下错误:
Exception in thread "main" org.hyperledger.fabric.sdk.exception.TransactionException: org.hyperledger.fabric.sdk.exception.EventHubException: org.hyperledger.fabric.sdk.exception.CryptoException: Could not sign the message using private key
at org.hyperledger.fabric.sdk.Channel.initialize(Channel.java:1158)
at HLFJavaClient.getChannel(HLFJavaClient.java:231)
at HLFJavaClient.main(HLFJavaClient.java:84)
Caused by: org.hyperledger.fabric.sdk.exception.EventHubException: org.hyperledger.fabric.sdk.exception.CryptoException: Could not sign the message using private key
at org.hyperledger.fabric.sdk.EventHub.connect(EventHub.java:322)
at org.hyperledger.fabric.sdk.EventHub.connect(EventHub.java:200)
at org.hyperledger.fabric.sdk.Channel.initialize(Channel.java:1127)
... 2 more
Caused by: org.hyperledger.fabric.sdk.exception.CryptoException: Could not sign the message using private key
at org.hyperledger.fabric.sdk.security.CryptoPrimitives.ecdsaSignToBytes(CryptoPrimitives.java:747)
at org.hyperledger.fabric.sdk.security.CryptoPrimitives.sign(CryptoPrimitives.java:757)
at org.hyperledger.fabric.sdk.identity.X509SigningIdentity.sign(X509SigningIdentity.java:23)
at org.hyperledger.fabric.sdk.transaction.TransactionContext.sign(TransactionContext.java:180)
at org.hyperledger.fabric.sdk.transaction.TransactionContext.signByteString(TransactionContext.java:184)
at org.hyperledger.fabric.sdk.EventHub.blockListen(EventHub.java:389)
at org.hyperledger.fabric.sdk.EventHub.connect(EventHub.java:320)
... 4 more
Caused by: java.security.InvalidKeyException: cannot identify EC private key: java.lang.NullPointerException
at org.bouncycastle.jcajce.provider.asymmetric.util.ECUtil.generatePrivateKeyParameter(Unknown Source)
at org.bouncycastle.jcajce.provider.asymmetric.ec.SignatureSpi.engineInitSign(Unknown Source)
at java.security.Signature$Delegate.engineInitSign(Signature.java:1177)
at java.security.Signature.initSign(Signature.java:530)
at org.hyperledger.fabric.sdk.security.CryptoPrimitives.ecdsaSignToBytes(CryptoPrimitives.java:729)
... 10 more
我的网络与 4 个对等节点(peer0.org1.mydomain.com、peer0.org2...、peer0.org3... 和 peer0.org4...)和一个排序节点(orderer.mydomain.com)一起运行。
Java SDK 客户端代码:
public class HLFJavaClient {
public static final String HLF_USER_NAME = "User1@org1.mydomain.com";
public static final String HLF_CLIENT_ORG = "Org1";
public static final String HLF_CLIENT_MSPID = "Org1MSP";
public static final String HLF_CLIENT_CRT_PATH = "../crypto-config/peerOrganizations/org1.mydomain.com/users/User1@org1.mydomain.com/msp/signcerts/User1@org1.mydomain.com-cert.pem";
public static final String HLF_CLIENT_KEY_PATH = "../crypto-config/peerOrganizations/org1.mydomain.com/users/User1@org1.mydomain.com/msp/keystore/User1@org1.mydomain.com-priv.pem";
public static final String HLF_CHANNEL_NAME = "mychannel";
public static final String HLF_CHAINCODE_NAME = "pkicc";
private static final Logger log = Logger.getLogger(HLFJavaClient.class);
public static void main(String[] args) throws Exception {
AppUser appUser = getUser(HLF_CLIENT_CRT_PATH, HLF_CLIENT_KEY_PATH, HLF_USER_NAME);
HFClient client = getHfClient();
client.setUserContext(appUser);
Channel channel = getChannel(client);
addProperty(client, new String[] {"1","w"});
}
static void addProperty(HFClient client, String[] property) throws ProposalException, InvalidArgumentException {
Channel channel = client.getChannel(HLF_CHANNEL_NAME);
TransactionProposalRequest tpr = client.newTransactionProposalRequest();
ChaincodeID CCId = ChaincodeID.newBuilder().setName(HLF_CHAINCODE_NAME).build();
tpr.setChaincodeID(CCId);
tpr.setFcn("createWallet");
tpr.setArgs(property);
Collection<ProposalResponse> res = channel.sendTransactionProposal(tpr);
for (ProposalResponse pres : res) {
String stringResponse = "Response from endorser is: " + pres.getChaincodeActionResponseStatus();
log.info(stringResponse);
System.out.println(stringResponse);
}
channel.sendTransaction(res);
System.out.println("Transaction sent.");
}
static Channel getChannel(HFClient client) throws InvalidArgumentException, TransactionException {
Channel channel = client.newChannel(HLF_CHANNEL_NAME);
class PeerOrgPort {
public String org;
public int port;
public PeerOrgPort(String org, int port) {
this.org = org;
this.port = port;
}
}
PeerOrgPort[] peers = new PeerOrgPort[] {
new PeerOrgPort("1", 7051),
new PeerOrgPort("2", 8051),
new PeerOrgPort("3", 9051),
new PeerOrgPort("4", 10051),
};
for (int i = 0; i < peers.length; i++) {
File tlsCrt = Paths.get("../crypto-config/peerOrganizations/org" + peers[i].org + ".mydomain.com/tlsca", "tlsca.org" + peers[i].org + ".mydomain.com-cert.pem").toFile();
if (!tlsCrt.exists())
throw new RuntimeException("Missing TLS cert files");
Properties secPeerProperties = new Properties();
secPeerProperties.setProperty("hostnameOverride", "peer0.org" + peers[i].org + ".mydomain.com");
secPeerProperties.setProperty("sslProvider", "openSSL");
secPeerProperties.setProperty("negotiationType", "TLS");
secPeerProperties.setProperty("pemFile", tlsCrt.getAbsolutePath());
Peer peer = client.newPeer("peer0.org" + peers[i].org + ".mydomain.com", "grpcs://localhost:" + peers[i].port, secPeerProperties);
channel.addPeer(peer);
if (peers[i].org.equals("1")) {
EventHub eventHub = client.newEventHub("eventhub01", "grpcs://localhost:7053", secPeerProperties);
channel.addEventHub(eventHub);
}
}
File tlsOrdCrt = Paths.get("../crypto-config/ordererOrganizations/mydomain.com/tlsca", "tlsca.mydomain.com-cert.pem").toFile();
if (!tlsOrdCrt.exists())
throw new RuntimeException("Missing TLS cert files");
Properties secOrdererProperties = new Properties();
secOrdererProperties.setProperty("hostnameOverride", "orderer.mydomain.com");
secOrdererProperties.setProperty("sslProvider", "openSSL");
secOrdererProperties.setProperty("negotiationType", "TLS");
secOrdererProperties.setProperty("pemFile", tlsOrdCrt.getAbsolutePath());
Orderer orderer = client.newOrderer("orderer.mydomain.com", "grpcs://localhost:7050", secOrdererProperties);
channel.addOrderer(orderer);
channel.initialize();
return channel;
}
static HFClient getHfClient() throws Exception {
CryptoSuite cryptoSuite = CryptoSuite.Factory.getCryptoSuite();
HFClient client = HFClient.createNewInstance();
client.setCryptoSuite(cryptoSuite);
return client;
}
static AppUser getUser(String certPath, String keyPath, String userId) throws Exception {
AppUser appUser = null;//tryDeserialize(userId);
if (appUser == null) {
appUser = new AppUser(userId, HLF_CLIENT_ORG, HLF_CLIENT_MSPID, certPath, keyPath);
}
return appUser;
}
应用用户:
public class AppUser implements User, Serializable {
private static final long serializationId = 1L;
private static final long serialVersionUID = -6287264119837208213L;
private String name;
private Set<String> roles;
private String account;
private String affiliation;
private Enrollment enrollment;
private String mspId;
public AppUser() {
// no-arg constructor
}
public AppUser(String name, String affiliation, String mspId, String certPath, String keyPath) {
this.name = name;
this.affiliation = affiliation;
this.enrollment = getEnrollmentFromCertPath(certPath, keyPath);
this.mspId = mspId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public Set<String> getRoles() {
return roles;
}
public void setRoles(Set<String> roles) {
this.roles = roles;
}
public String getAccount() {
return account;
}
public void setAccount(String account) {
this.account = account;
}
public String getAffiliation() {
return affiliation;
}
public void setAffiliation(String affiliation) {
this.affiliation = affiliation;
}
public Enrollment getEnrollment() {
return enrollment;
}
public void setEnrollment(Enrollment enrollment) {
this.enrollment = enrollment;
}
public String getMspId() {
return mspId;
}
public void setMspId(String mspId) {
this.mspId = mspId;
}
@Override
public String toString() {
return "AppUser{" +
"name='" + name + '\'' +
"\n, roles=" + roles +
"\n, account='" + account + '\'' +
"\n, affiliation='" + affiliation + '\'' +
"\n, enrollment=" + enrollment +
"\n, mspId='" + mspId + '\'' +
'}';
}
private Enrollment getEnrollmentFromCertPath(final String certPath, final String keyPath) {
return new Enrollment() {
public PrivateKey getKey() {
try {
return loadPrivateKey(Paths.get(keyPath));
} catch (Exception e) {
return null;
}
}
public String getCert() {
try {
return new String(Files.readAllBytes(Paths.get(certPath)));
} catch (Exception e) {
return "";
}
}
};
}
private static PrivateKey loadPrivateKey(Path fileName) throws IOException, GeneralSecurityException {
PrivateKey key = null;
InputStream is = null;
BufferedReader br = null;
try {
is = new FileInputStream(fileName.toString());
br = new BufferedReader(new InputStreamReader(is));
StringBuilder builder = new StringBuilder();
boolean inKey = false;
for (String line = br.readLine(); line != null; line = br.readLine()) {
if (!inKey) {
if (line.startsWith("-----BEGIN ") && line.endsWith(" PRIVATE KEY-----")) {
inKey = true;
}
continue;
} else {
if (line.startsWith("-----END ") && line.endsWith(" PRIVATE KEY-----")) {
inKey = false;
break;
}
builder.append(line);
}
}
byte[] encoded = DatatypeConverter.parseBase64Binary(builder.toString());
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
KeyFactory kf = KeyFactory.getInstance("ECDSA", "BC");
key = kf.generatePrivate(keySpec);
} finally {
br.close();
is.close();
}
return key;
}
}
我究竟做错了什么?
谢谢