fabric-samples/hsm-samples-gateway/go/hsm-sample.go
sapthasurendran ce8d1ddc5b Added hsmm Samples using Gateway
Signed-off-by: sapthasurendran <saptha.surendran@ibm.com>
2022-06-07 22:10:24 +05:30

187 lines
4.8 KiB
Go

//go:build pkcs11
// +build pkcs11
/*
Copyright IBM Corp. All Rights Reserved.
SPDX-License-Identifier: Apache-2.0
*/
package main
import (
"crypto/ecdsa"
"crypto/elliptic"
"crypto/sha256"
"encoding/pem"
"errors"
"os"
"crypto/x509"
"fmt"
"io/ioutil"
"time"
"github.com/hyperledger/fabric-gateway/pkg/client"
"github.com/hyperledger/fabric-gateway/pkg/identity"
"google.golang.org/grpc"
"google.golang.org/grpc/credentials"
)
const (
mspID = "Org1MSP"
cryptoPath = "../../scenario/fixtures/crypto-material/"
certPath = cryptoPath + "hsm/HSMUser/signcerts/cert.pem"
tlsCertPath = cryptoPath + "crypto-config/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
peerEndpoint = "localhost:7051"
)
func main() {
fmt.Println("Running the GO HSM Sample")
// The gRPC client connection should be shared by all Gateway connections to this endpoint
clientConnection := newGrpcConnection()
defer clientConnection.Close()
hsmSignerFactory, err := identity.NewHSMSignerFactory(findSoftHSMLibrary())
if err != nil {
panic(err)
}
defer hsmSignerFactory.Dispose()
certificatePEM, err := ioutil.ReadFile(certPath)
if err != nil {
panic(err)
}
id := newIdentity(certificatePEM)
ski := getSKI(certificatePEM)
hsmSign, hsmSignClose := newHSMSign(hsmSignerFactory, ski)
defer hsmSignClose()
// Create a Gateway connection for a specific client identity
gateway, err := client.Connect(id, client.WithSign(hsmSign), client.WithClientConnection(clientConnection))
if err != nil {
panic(err)
}
defer gateway.Close()
exampleSubmit(gateway)
fmt.Println()
fmt.Println("Go HSM Sample Completed Successfully")
fmt.Println()
}
func exampleSubmit(gateway *client.Gateway) {
network := gateway.GetNetwork("mychannel")
contract := network.GetContract("basic")
timestamp := time.Now().String()
fmt.Printf("Submitting \"put\" transaction with arguments: time, %s\n", timestamp)
// Submit transaction, blocking until the transaction has been committed on the ledger
submitResult, err := contract.SubmitTransaction("put", "time", timestamp)
if err != nil {
panic(fmt.Errorf("failed to submit transaction: %w", err))
}
fmt.Printf("Submit result: %s\n", string(submitResult))
fmt.Println("Evaluating \"get\" query with arguments: time")
evaluateResult, err := contract.EvaluateTransaction("get", "time")
if err != nil {
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
}
fmt.Printf("Query result = %s\n", string(evaluateResult))
}
// newGrpcConnection creates a gRPC connection to the Gateway server.
func newGrpcConnection() *grpc.ClientConn {
certificate, err := loadCertificate(tlsCertPath)
if err != nil {
panic(fmt.Errorf("failed to obtain commit status: %w", err))
}
certPool := x509.NewCertPool()
certPool.AddCert(certificate)
transportCredentials := credentials.NewClientTLSFromCert(certPool, "peer0.org1.example.com")
connection, err := grpc.Dial(peerEndpoint, grpc.WithTransportCredentials(transportCredentials))
if err != nil {
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
}
return connection
}
// newIdentity creates a client identity for this Gateway connection using an X.509 certificate.
func newIdentity(certificatePEM []byte) *identity.X509Identity {
cert, err := identity.CertificateFromPEM(certificatePEM)
if err != nil {
panic(err)
}
id, err := identity.NewX509Identity(mspID, cert)
if err != nil {
panic(err)
}
return id
}
// newHSMSign creates a function that generates a digital signature from a message digest using a private key.
func newHSMSign(h *identity.HSMSignerFactory, certPEM []byte) (identity.Sign, identity.HSMSignClose) {
opt := identity.HSMSignerOptions{
Label: "ForFabric",
Pin: "98765432",
Identifier: string(certPEM),
}
sign, close, err := h.NewHSMSigner(opt)
if err != nil {
panic(err)
}
return sign, close
}
func loadCertificate(filename string) (*x509.Certificate, error) {
certificatePEM, err := ioutil.ReadFile(filename) //#nosec G304
if err != nil {
return nil, err
}
return identity.CertificateFromPEM(certificatePEM)
}
func getSKI(certPEM []byte) []byte {
block, _ := pem.Decode(certPEM)
x590cert, _ := x509.ParseCertificate(block.Bytes)
pk := x590cert.PublicKey
return skiForKey(pk.(*ecdsa.PublicKey))
}
func skiForKey(pk *ecdsa.PublicKey) []byte {
ski := sha256.Sum256(elliptic.Marshal(pk.Curve, pk.X, pk.Y))
return ski[:]
}
func findSoftHSMLibrary() string {
libraryLocations := []string{
"/usr/lib/softhsm/libsofthsm2.so",
"/usr/lib/x86_64-linux-gnu/softhsm/libsofthsm2.so",
"/usr/local/lib/softhsm/libsofthsm2.so",
"/usr/lib/libacsp-pkcs11.so",
}
for _, libraryLocation := range libraryLocations {
if _, err := os.Stat(libraryLocation); !errors.Is(err, os.ErrNotExist) {
return libraryLocation
}
}
panic("No SoftHSM library can be found. The Sample requires SoftHSM to be installed")
}