Skip to content

Commit

Permalink
Include hash in example client connection code
Browse files Browse the repository at this point in the history
When using non-ECDSA private keys, such as ed25519, it can be necessary
to specify an alternative hash algorithm. Highlight that a hash can (and
probably should) be explicitly specified when creating a Gateway
connection by including this in the client code examples.

Signed-off-by: Mark S. Lewis <[email protected]>
  • Loading branch information
bestbeforetoday committed Oct 6, 2024
1 parent 050e807 commit 0e7d3d9
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 16 deletions.
4 changes: 2 additions & 2 deletions java/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ A suitable gRPC channel service provider must also be specified (as described in
<dependency>
<groupId>io.grpc</groupId>
<artifactId>grpc-netty-shaded</artifactId>
<version>1.68.0</version>
<version>1.67.1</version>
<scope>runtime</scope>
</dependency>
```
Expand All @@ -54,7 +54,7 @@ implementation 'org.hyperledger.fabric:fabric-gateway:1.6.0'
A suitable gRPC channel service provider must also be specified (as described in the [gRPC security documentation](https://github.com/grpc/grpc-java/blob/master/SECURITY.md#transport-security-tls)), such as:

```groovy
runtimeOnly 'io.grpc:grpc-netty-shaded:1.68.0'
runtimeOnly 'io.grpc:grpc-netty-shaded:1.67.1'
```

## Compatibility
Expand Down
48 changes: 38 additions & 10 deletions java/src/main/javadoc/overview.html
Original file line number Diff line number Diff line change
Expand Up @@ -34,45 +34,73 @@
</p>

<pre><code>
import io.grpc.Grpc;
import io.grpc.ManagedChannel;
import io.grpc.TlsChannelCredentials;
import org.hyperledger.fabric.client.*;
import org.hyperledger.fabric.client.identity.*;
import io.grpc.ChannelCredentials;
import io.grpc.Grpc;
import io.grpc.ManagedChannel;
import io.grpc.TlsChannelCredentials;
import java.io.IOException;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.InvalidKeyException;
import java.security.PrivateKey;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.LocalDateTime;
import java.util.concurrent.TimeUnit;
import org.hyperledger.fabric.client.identity.Identities;
import org.hyperledger.fabric.client.identity.Identity;
import org.hyperledger.fabric.client.identity.Signer;
import org.hyperledger.fabric.client.identity.Signers;
import org.hyperledger.fabric.client.identity.X509Identity;

public static void main(final String[] args) throws CommitException, GatewayException, InterruptedException {
Reader certReader = Files.newBufferedReader(certificatePath);
public final class Example {
public static void main(final String[] args)
throws IOException, CertificateException, InvalidKeyException, GatewayException, CommitException,
InterruptedException {
// Create client identity based on X.509 certificate.
Reader certReader = Files.newBufferedReader(Paths.get("path/to/certificate.pem"));
X509Certificate certificate = Identities.readX509Certificate(certReader);
Identity identity = new X509Identity("mspId", certificate);

Reader keyReader = Files.newBufferedReader(privateKeyPath);
// Create signing implementation based on private key.
Reader keyReader = Files.newBufferedReader(Paths.get("path/to/private-key.pem"));
PrivateKey privateKey = Identities.readPrivateKey(keyReader);
Signer signer = Signers.newPrivateKeySigner(privateKey);

// Create gRPC client connection, which should be shared by all gateway connections to this endpoint.
ChannelCredentials tlsCredentials = TlsChannelCredentials.newBuilder()
.trustManager(Paths.get(tlsRootCertPath).toFile())
.trustManager(Paths.get("path/to/tls-CA-certificate.pem").toFile())
.build();
ManagedChannel grpcChannel = Grpc.newChannelBuilder("gateway.example.org:1337", tlsCredentials)
.build();

// Create a Gateway connection for a specific client identity.
Gateway.Builder builder = Gateway.newInstance()
.identity(identity)
.signer(signer)
.hash(Hash.SHA256)
.connection(grpcChannel);

try (Gateway gateway = builder.connect()) {
// Obtain smart contract deployed on the network.
Network network = gateway.getNetwork("channelName");
Contract contract = network.getContract("chaincodeName");

byte[] putResult = contract.submitTransaction("put", "time", LocalDateTime.now().toString());
// Submit transactions that store state to the ledger.
byte[] putResult = contract.submitTransaction(
"put", "time", LocalDateTime.now().toString());
System.out.println(new String(putResult, StandardCharsets.UTF_8));

// Evaluate transactions that query state from the ledger.
byte[] getResult = contract.evaluateTransaction("get", "time");
System.out.println(new String(getResult, StandardCharsets.UTF_8));
} finally {
grpcChannel.shutdownNow().awaitTermination(5, TimeUnit.SECONDS);
}
}
}
</code></pre>
</body>
</html>
11 changes: 8 additions & 3 deletions node/src/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,15 @@ The following complete example shows how to connect to a Fabric network, submit

```TypeScript
import * as grpc from '@grpc/grpc-js';
import { connect, hash, signers } from '@hyperledger/fabric-gateway';
import * as crypto from 'node:crypto';
import { connect, Identity, signers } from '@hyperledger/fabric-gateway';
import { promises as fs } from 'node:fs';
import { TextDecoder } from 'node:util';

const utf8Decoder = new TextDecoder();

async function main(): Promise<void> {
const credentials = await fs.readFile('path/to/certificate.pem');
const identity: Identity = { mspId: 'myorg', credentials };

const privateKeyPem = await fs.readFile('path/to/privateKey.pem');
const privateKey = crypto.createPrivateKey(privateKeyPem);
Expand All @@ -34,7 +33,13 @@ async function main(): Promise<void> {
const tlsRootCert = await fs.readFile('path/to/tlsRootCertificate.pem');
const client = new grpc.Client('gateway.example.org:1337', grpc.credentials.createSsl(tlsRootCert));

const gateway = connect({ identity, signer, client });
const gateway = connect({
identity: { mspId: 'myorg', credentials },
signer,
hash: hash.sha256,
client,
});

try {
const network = gateway.getNetwork('channelName');
const contract = network.getContract('chaincodeName');
Expand Down
4 changes: 3 additions & 1 deletion pkg/client/example_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import (
"os"

"github.com/hyperledger/fabric-gateway/pkg/client"
"github.com/hyperledger/fabric-gateway/pkg/hash"
"github.com/hyperledger/fabric-gateway/pkg/identity"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
Expand All @@ -25,7 +26,8 @@ func Example() {
sign := NewSign()

// Create a Gateway connection for a specific client identity.
gateway, err := client.Connect(id, client.WithSign(sign), client.WithClientConnection(clientConnection))
gateway, err := client.Connect(id, client.WithSign(sign), client.WithHash(hash.SHA256),
client.WithClientConnection(clientConnection))
panicOnError(err)
defer gateway.Close()

Expand Down

0 comments on commit 0e7d3d9

Please sign in to comment.