mirror of
https://github.com/hyperledger/fabric-samples.git
synced 2026-06-23 01:55:10 +00:00
code refactor
Signed-off-by: sapthasurendran <saptha.surendran@ibm.com>
This commit is contained in:
parent
90cf860e50
commit
1019c9800b
14 changed files with 909 additions and 8 deletions
|
|
@ -109,10 +109,10 @@ echo 'go install pkcs11 enabled fabric-ca-client'
|
|||
go install -tags pkcs11 github.com/hyperledger/fabric-ca/cmd/fabric-ca-client@latest
|
||||
createNetwork
|
||||
print "Initializing Typescript HSM gateway application"
|
||||
pushd ../hsm-gateway-applications/scripts/
|
||||
pushd ../hardware-security-module/scripts/
|
||||
print "Enroll and register User in HSM"
|
||||
./generate-hsm-user.sh HSMUser
|
||||
pushd ../node/
|
||||
pushd ../application-typescript/
|
||||
print "install dependencies and prepare for running"
|
||||
npm install
|
||||
print "Running the output app"
|
||||
|
|
@ -124,12 +124,12 @@ stopNetwork
|
|||
# Run Go HSM gateway application
|
||||
createNetwork
|
||||
print "Initializing Go HSM gateway application"
|
||||
pushd ../hsm-gateway-applications/scripts/
|
||||
pushd ../hardware-security-module/scripts/
|
||||
print "Register and enroll user in HSM"
|
||||
./generate-hsm-user.sh HSMUser
|
||||
pushd ../go
|
||||
pushd ../application-go
|
||||
print "Running the output app"
|
||||
go run -tags pkcs11 hsm-sample.go
|
||||
go run -tags pkcs11 .
|
||||
popd
|
||||
popd
|
||||
stopNetwork
|
||||
|
|
|
|||
1
hardware-security-module/.gitignore
vendored
Normal file
1
hardware-security-module/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
crypto-material
|
||||
127
hardware-security-module/README.md
Normal file
127
hardware-security-module/README.md
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
# Fabric Gateway HSM Samples
|
||||
|
||||
The samples show how to create client applications that invoke transactions with HSM Identities using the
|
||||
new embedded Gateway in Fabric.
|
||||
|
||||
The samples will only run against Fabric v2.4 and higher.
|
||||
|
||||
Sample client applications are available to demonstrate the features of the Fabric Gateway and associated SDKs using this network.
|
||||
|
||||
## Installations
|
||||
|
||||
### C Compilers
|
||||
|
||||
In order for the client application to run successfully you must ensure you have C compilers and Python 3 (Note that Python 2 may still work however Python 2 is out of support and could stop working in the future) installed otherwise the node dependency `pkcs11js` will not be built and the application will fail. The failure will have an error such as
|
||||
|
||||
```
|
||||
Error: Cannot find module 'pkcs11js'
|
||||
```
|
||||
|
||||
how to install the required C Compilers and Python will depend on your operating system and version.
|
||||
|
||||
### SoftHSM
|
||||
|
||||
In order to run the application in the absence of a real HSM, a software
|
||||
emulator of the PKCS#11 interface is required.
|
||||
For more information please refer to [SoftHSM](https://www.opendnssec.org/softhsm/).
|
||||
|
||||
SoftHSM can either be installed using the package manager for your host system:
|
||||
|
||||
* Ubuntu: `sudo apt install softhsm2`
|
||||
* macOS: `brew install softhsm`
|
||||
* Windows: **unsupported**
|
||||
|
||||
Or compiled and installed from source:
|
||||
|
||||
1. install openssl 1.0.0+ or botan 1.10.0+
|
||||
2. download the source code from <https://dist.opendnssec.org/source/softhsm-2.5.0.tar.gz>
|
||||
3. `tar -xvf softhsm-2.5.0.tar.gz`
|
||||
4. `cd softhsm-2.5.0`
|
||||
5. `./configure --disable-gost` (would require additional libraries, turn it off unless you need 'gost' algorithm support for the Russian market)
|
||||
6. `make`
|
||||
7. `sudo make install`
|
||||
|
||||
### PKCS#11 enabled fabric-ca-client binary
|
||||
To be able to register and enroll identities using an HSM you need a PKCS#11 enabled version of `fabric-ca-client`
|
||||
To install this use the following command
|
||||
|
||||
```bash
|
||||
go install -tags 'pkcs11' github.com/hyperledger/fabric-ca/cmd/fabric-ca-client@latest
|
||||
```
|
||||
|
||||
## Running the sample
|
||||
|
||||
The Fabric test network is used to deploy and run this sample. Follow these steps in order:
|
||||
|
||||
1. Create the test network and a channel (from the `test-network` folder).
|
||||
```
|
||||
./network.sh up createChannel -ca
|
||||
```
|
||||
|
||||
2. Deploy one of the smart contract implementations (from the `test-network` folder).
|
||||
```
|
||||
# To deploy the TypeScript chaincode implementation
|
||||
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-typescript/ -ccl typescript
|
||||
|
||||
# To deploy the Go chaincode implementation
|
||||
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-go/ -ccl go
|
||||
|
||||
# To deploy the Java chaincode implementation
|
||||
./network.sh deployCC -ccn basic -ccp ../asset-transfer-basic/chaincode-java/ -ccl java
|
||||
```
|
||||
|
||||
## Initialize a token to store keys in SoftHSM
|
||||
|
||||
If you have not initialized a token previously (or it has been deleted) then you will need to perform this one time operation
|
||||
|
||||
```bash
|
||||
echo directories.tokendir = /tmp > $HOME/softhsm2.conf
|
||||
export SOFTHSM2_CONF=$HOME/softhsm2.conf
|
||||
softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
||||
```
|
||||
|
||||
This will create a SoftHSM configuration file called `softhsm2.conf` and will be stored in the home directory. This is
|
||||
where the sample expects to find a SoftHSM configuration file
|
||||
|
||||
The Security Officer PIN, specified with the `--so-pin` flag, can be used to re-initialize the token,
|
||||
and the user PIN (see below), specified with the `--pin` flag, is used by applications to access the token for
|
||||
generating and retrieving keys.
|
||||
|
||||
## Enroll the HSM User
|
||||
|
||||
A user, `HSMUser`, who is HSM managed needs to be registered then enrolled for the sample.
|
||||
|
||||
If the "standard" PKCS11 library locations checked for by the script don't include the library(libsofthsm2.so) location for your environment set the `PKCS11_LIB` environment variable to define the library location.
|
||||
|
||||
```bash
|
||||
PKCS11_LIB='<path to PKCS11 library location>' scripts/generate-hsm-user.sh HSMUser
|
||||
```
|
||||
|
||||
This will register a user `HSMUser` with the CA in Org1 (if not already registered) and then enroll that user which will
|
||||
generate a certificate on the file system for use by the sample. The private key is stored in SoftHSM
|
||||
|
||||
### Go SDK
|
||||
|
||||
For HSM support you need to ensure you include the `pkcs11` build tag.
|
||||
Mention the PKCS11_LIB environment variable in case of a non-standard library location
|
||||
|
||||
```
|
||||
cd hardware-security-module/application-go
|
||||
go run -tags pkcs11 PKCS11_LIB=<path to PKCS11 library location> .
|
||||
```
|
||||
|
||||
### Node SDK
|
||||
|
||||
Mention the PKCS11_LIB environment variable in case of a non-standard library location
|
||||
```
|
||||
export PKCS11_LIB=<path to PKCS11 library location>
|
||||
cd hardware-security-module/application-typescript
|
||||
npm install
|
||||
npm start
|
||||
```
|
||||
|
||||
When you are finished running the samples, the local test-network can be brought down with the following command (from the `test-network` folder):
|
||||
|
||||
```
|
||||
./network.sh down
|
||||
```
|
||||
19
hardware-security-module/application-go/go.mod
Normal file
19
hardware-security-module/application-go/go.mod
Normal file
|
|
@ -0,0 +1,19 @@
|
|||
module github.com/hyperledger/fabric-samples/asset-transfer-basic/application-gateway-hsm/go
|
||||
|
||||
go 1.18
|
||||
|
||||
require (
|
||||
github.com/hyperledger/fabric-gateway v1.1.0
|
||||
google.golang.org/grpc v1.47.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/golang/protobuf v1.5.2 // indirect
|
||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7 // indirect
|
||||
github.com/miekg/pkcs11 v1.1.1 // indirect
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 // indirect
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a // indirect
|
||||
golang.org/x/text v0.3.7 // indirect
|
||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 // indirect
|
||||
google.golang.org/protobuf v1.28.0 // indirect
|
||||
)
|
||||
143
hardware-security-module/application-go/go.sum
Normal file
143
hardware-security-module/application-go/go.sum
Normal file
|
|
@ -0,0 +1,143 @@
|
|||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
|
||||
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
|
||||
github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
|
||||
github.com/cncf/udpa/go v0.0.0-20210930031921-04548b0d99d4/go.mod h1:6pvJx4me5XPnfI9Z40ddWsdw2W/uZgQLFXToKeRcDiI=
|
||||
github.com/cncf/xds/go v0.0.0-20210922020428-25de7278fc84/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211001041855-01bcc9b48dfe/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/cncf/xds/go v0.0.0-20211011173535-cb28da3451f1/go.mod h1:eXthEFrGJvWHgFFCl3hGmgk+/aYT6PnTQLykKQRLhEs=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.9.9-0.20201210154907-fd9021fe5dad/go.mod h1:cXg6YxExXjJnVBQHBLXeUAgxn2UodCpnH306RInaBQk=
|
||||
github.com/envoyproxy/go-control-plane v0.10.2-0.20220325020618-49ff273808a1/go.mod h1:KJwIaB5Mv44NWtYuAOFCVOjcI94vtpEz2JU/D2v6IjE=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/mock v1.1.1/go.mod h1:oTYuIxOrZwtPieC+H1uAHpcLFnEyAGVDL/k47Jfbm0A=
|
||||
github.com/golang/protobuf v1.2.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||
github.com/golang/protobuf v1.3.3/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
|
||||
github.com/golang/protobuf v1.4.0-rc.1/go.mod h1:ceaxUfeHdC40wWswd/P6IGgMaK3YpKi5j83Wpe3EHw8=
|
||||
github.com/golang/protobuf v1.4.0-rc.1.0.20200221234624-67d41d38c208/go.mod h1:xKAWHe0F5eneWXFV3EuXVDTCmh+JuBKY0li0aMyXATA=
|
||||
github.com/golang/protobuf v1.4.0-rc.2/go.mod h1:LlEzMj4AhA7rCAGe4KMBDvJI+AwstrUpVNzEA03Pprs=
|
||||
github.com/golang/protobuf v1.4.0-rc.4.0.20200313231945-b860323f09d0/go.mod h1:WU3c8KckQ9AFe+yFwt9sWVRKCVIyN9cPHBJSNnbL67w=
|
||||
github.com/golang/protobuf v1.4.0/go.mod h1:jodUvKwWbYaEsadDk5Fwe5c77LiNKVO9IDvqG2KuDX0=
|
||||
github.com/golang/protobuf v1.4.1/go.mod h1:U8fpvMrcmy5pZrNK1lt4xCsGvpyWQ/VVv6QDs8UjoX8=
|
||||
github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw735rRwI=
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/grpc-ecosystem/grpc-gateway v1.16.0/go.mod h1:BDjrQk3hbvj6Nolgz8mAMFbcEtjT1g+wF4CSlocrBnw=
|
||||
github.com/hyperledger/fabric-gateway v1.1.0 h1:zQ6BjUCBCUUbPQNI/B/rzBD6QRvaqWxEIYAI6gtUZ14=
|
||||
github.com/hyperledger/fabric-gateway v1.1.0/go.mod h1:A+MuROWOKhmUsYVO2PREggHLPgPAXaudwCoZRpuSeqs=
|
||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7 h1:loYDK6Vrf7z3fff6YBVKFkFeCGCoKr8O2ed02CESBUQ=
|
||||
github.com/hyperledger/fabric-protos-go-apiv2 v0.0.0-20220615102044-467be1c7b2e7/go.mod h1:smwq1q6eKByqQAp0SYdVvE1MvDoneF373j11XwWajgA=
|
||||
github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU=
|
||||
github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/rogpeppe/fastuuid v1.2.0/go.mod h1:jVj6XXZzXRy/MSR5jhDC/2q6DgLz+nrA6LYCDYWNEvQ=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190108225652-1e06a53dbb7e/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20200822124328-c89045814202/go.mod h1:/O7V0waA8r7cgGh81Ro3o1hOxt32SMVPicZroKQ2sZA=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37 h1:lUkvobShwKsOesNfWWlCS5q7fnbG1MEliIzwu886fn8=
|
||||
golang.org/x/net v0.0.0-20220526153639-5463443f8c37/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.0.0-20200107190931-bf48bf16ab8d/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a h1:dGzPydgVsqGcTRVwiLJ1jVbufYwmzD3LfVPLKsKg+0k=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200513103714-09dca8ec2884/go.mod h1:55QSHmfGQM9UVYDPBsyGGes0y52j32PQ3BqQfXhyH3c=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58 h1:a221mAAEAzq4Lz6ZWRkcS8ptb2mxoxYSt4N68aRyQHM=
|
||||
google.golang.org/genproto v0.0.0-20220527130721-00d5c0f3be58/go.mod h1:yKyY4AMRwFiC8yMMNaMi+RkCnjZJt9LoWuvhXjMs+To=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.1/go.mod h1:fr5YgcSWrqhRRxogOsw7RzIpsmvOZ6IcH4kBYTpR3n0=
|
||||
google.golang.org/grpc v1.36.0/go.mod h1:qjiiYl8FncCW8feJPdyg3v6XW24KsRHe+dy9BAGRRjU=
|
||||
google.golang.org/grpc v1.46.2/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/grpc v1.47.0 h1:9n77onPX5F3qfFCqjy9dhn8PbNQsIKeVU04J9G7umt8=
|
||||
google.golang.org/grpc v1.47.0/go.mod h1:vN9eftEi1UMyUsIF80+uQXhHjbXYbm0uXoFCACuMGWk=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
google.golang.org/protobuf v1.20.1-0.20200309200217-e05f789c0967/go.mod h1:A+miEFZTKqfCUM6K7xSMQL9OKL/b6hQv+e19PK+JZNE=
|
||||
google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzikPIcrTAo=
|
||||
google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.28.0 h1:w43yiav+6bVFTBQFZX0r7ipe9JQ1QsbMgHwbBziscLw=
|
||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.3/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
|
||||
203
hardware-security-module/application-go/hsm-sample.go
Normal file
203
hardware-security-module/application-go/hsm-sample.go
Normal file
|
|
@ -0,0 +1,203 @@
|
|||
//go:build pkcs11
|
||||
// +build pkcs11
|
||||
|
||||
/*
|
||||
Copyright IBM Corp. All Rights Reserved.
|
||||
|
||||
SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/ecdsa"
|
||||
"crypto/elliptic"
|
||||
"crypto/sha256"
|
||||
"encoding/json"
|
||||
"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"
|
||||
certPath = "../crypto-material/hsm/HSMUser/signcerts/cert.pem"
|
||||
tlsCertPath = "../../test-network/organizations/peerOrganizations/org1.example.com/peers/peer0.org1.example.com/tls/ca.crt"
|
||||
peerEndpoint = "localhost:7051"
|
||||
)
|
||||
|
||||
var now = time.Now()
|
||||
var assetId = fmt.Sprintf("asset%d", now.Unix()*1e3+int64(now.Nanosecond())/1e6)
|
||||
|
||||
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()
|
||||
|
||||
exampleTransaction(gateway)
|
||||
fmt.Println()
|
||||
fmt.Println("Go HSM Sample completed successfully")
|
||||
fmt.Println()
|
||||
}
|
||||
|
||||
func exampleTransaction(gateway *client.Gateway) {
|
||||
network := gateway.GetNetwork("mychannel")
|
||||
contract := network.GetContract("basic")
|
||||
|
||||
fmt.Printf("Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments \n")
|
||||
|
||||
_, err := contract.SubmitTransaction("CreateAsset", assetId, "yellow", "5", "Tom", "1300")
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to submit transaction: %w", err))
|
||||
}
|
||||
|
||||
fmt.Printf("*** Transaction committed successfully\n")
|
||||
|
||||
fmt.Printf("Evaluate Transaction: ReadAsset, function returns asset attributes\n")
|
||||
|
||||
evaluateResult, err := contract.EvaluateTransaction("ReadAsset", assetId)
|
||||
if err != nil {
|
||||
panic(fmt.Errorf("failed to evaluate transaction: %w", err))
|
||||
}
|
||||
result := formatJSON(evaluateResult)
|
||||
|
||||
fmt.Printf("*** Result:%s\n", result)
|
||||
}
|
||||
|
||||
// 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",
|
||||
}
|
||||
pkcs11lib := os.Getenv("PKCS11_LIB")
|
||||
if pkcs11lib != "" {
|
||||
libraryLocations = append(libraryLocations, pkcs11lib)
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
// Format JSON data
|
||||
func formatJSON(data []byte) string {
|
||||
var prettyJSON bytes.Buffer
|
||||
if err := json.Indent(&prettyJSON, data, " ", ""); err != nil {
|
||||
panic(fmt.Errorf("failed to parse JSON: %w", err))
|
||||
}
|
||||
return prettyJSON.String()
|
||||
}
|
||||
|
|
@ -0,0 +1,29 @@
|
|||
env:
|
||||
node: true
|
||||
es2020: true
|
||||
root: true
|
||||
ignorePatterns:
|
||||
- dist/
|
||||
extends:
|
||||
- eslint:recommended
|
||||
rules:
|
||||
indent:
|
||||
- error
|
||||
- 4
|
||||
quotes:
|
||||
- error
|
||||
- single
|
||||
overrides:
|
||||
- files:
|
||||
- "**/*.ts"
|
||||
parser: "@typescript-eslint/parser"
|
||||
parserOptions:
|
||||
sourceType: module
|
||||
ecmaFeatures:
|
||||
impliedStrict: true
|
||||
plugins:
|
||||
- "@typescript-eslint"
|
||||
extends:
|
||||
- eslint:recommended
|
||||
- plugin:@typescript-eslint/eslint-recommended
|
||||
- plugin:@typescript-eslint/recommended
|
||||
3
hardware-security-module/application-typescript/.gitignore
vendored
Normal file
3
hardware-security-module/application-typescript/.gitignore
vendored
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
dist/
|
||||
node_modules/
|
||||
package-lock.json
|
||||
35
hardware-security-module/application-typescript/package.json
Normal file
35
hardware-security-module/application-typescript/package.json
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
{
|
||||
"name": "gateway-hsm-sample",
|
||||
"version": "0.0.1",
|
||||
"description": "",
|
||||
"main": "dist/hsm-sample.js",
|
||||
"engines": {
|
||||
"node": "^14.15.0 || ^16.13.0"
|
||||
},
|
||||
"scripts": {
|
||||
"build": "tsc",
|
||||
"prepare": "npm run build",
|
||||
"clean": "rimraf dist",
|
||||
"lint": "eslint . --ext .ts",
|
||||
"start": "SOFTHSM2_CONF=${HOME}/softhsm2.conf node dist/hsm-sample.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@grpc/grpc-js": "~1.6.7",
|
||||
"@hyperledger/fabric-gateway": "^1.1.0",
|
||||
"jsrsasign": "^10.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@tsconfig/node14": "^1.0.1",
|
||||
"@types/jsrsasign": "^9.0.3",
|
||||
"@types/node": "^14.17.32",
|
||||
"@typescript-eslint/eslint-plugin": "^5.3.0",
|
||||
"@typescript-eslint/parser": "^5.3.0",
|
||||
"eslint": "^8.1.0",
|
||||
"npm-run-all": "^4.1.5",
|
||||
"rimraf": "^3.0.2",
|
||||
"typescript": "~4.5.4"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,154 @@
|
|||
/*
|
||||
* Copyright IBM Corp. All Rights Reserved.
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
import * as grpc from '@grpc/grpc-js';
|
||||
import * as crypto from 'crypto';
|
||||
import { connect, Gateway, HSMSigner, HSMSignerFactory, HSMSignerOptions, signers } from '@hyperledger/fabric-gateway';
|
||||
import * as fs from 'fs';
|
||||
import * as jsrsa from 'jsrsasign';
|
||||
import * as path from 'path';
|
||||
import { TextDecoder } from 'util';
|
||||
|
||||
const mspId = 'Org1MSP';
|
||||
const user = 'HSMUser';
|
||||
const assetId = `asset${Date.now()}`;
|
||||
const utf8Decoder = new TextDecoder();
|
||||
|
||||
// Sample uses fabric-ca-client generated HSM identities, certificate is located in the signcerts directory
|
||||
// and has been stored in a directory of the name given to the identity.
|
||||
|
||||
const certPath = path.resolve(__dirname, '..', '..', 'crypto-material', 'hsm', user, 'signcerts', 'cert.pem');
|
||||
|
||||
const tlsCertPath = path.resolve('..', '..', 'test-network','organizations','peerOrganizations', 'org1.example.com', 'peers', 'peer0.org1.example.com', 'tls', 'ca.crt');
|
||||
const peerEndpoint = 'localhost:7051';
|
||||
|
||||
async function main() {
|
||||
console.log('\nRunning the Node HSM sample');
|
||||
|
||||
// The gRPC client connection should be shared by all Gateway connections to this endpoint
|
||||
const client = await newGrpcConnection();
|
||||
|
||||
// get an HSMSigner Factory. You only need to do this once for the application
|
||||
const hsmSignerFactory = signers.newHSMSignerFactory(findSoftHSMPKCS11Lib());
|
||||
const credentials = await fs.promises.readFile(certPath);
|
||||
|
||||
// Get the signer function and a close function. The close function closes the signer
|
||||
// once there is no further need for it.
|
||||
const {signer, close} = await newHSMSigner(hsmSignerFactory, credentials.toString());
|
||||
|
||||
const gateway = connect({
|
||||
client,
|
||||
identity: {mspId, credentials},
|
||||
signer,
|
||||
});
|
||||
|
||||
try {
|
||||
await exampleTransaction(gateway);
|
||||
console.log();
|
||||
console.log('Node HSM sample completed successfully');
|
||||
} finally {
|
||||
gateway.close();
|
||||
client.close();
|
||||
|
||||
// close the HSM Signer
|
||||
close();
|
||||
}
|
||||
}
|
||||
|
||||
async function exampleTransaction(gateway: Gateway):Promise<void> {
|
||||
const network = gateway.getNetwork('mychannel');
|
||||
const contract = network.getContract('basic');
|
||||
|
||||
console.log('\n--> Submit Transaction: CreateAsset, creates new asset with ID, Color, Size, Owner and AppraisedValue arguments');
|
||||
|
||||
await contract.submitTransaction(
|
||||
'CreateAsset',
|
||||
assetId,
|
||||
'yellow',
|
||||
'5',
|
||||
'Tom',
|
||||
'1300',
|
||||
);
|
||||
|
||||
console.log('*** Transaction committed successfully');
|
||||
|
||||
console.log('\n--> Evaluate Transaction: ReadAsset, function returns asset attributes');
|
||||
|
||||
const resultBytes = await contract.evaluateTransaction('ReadAsset', assetId);
|
||||
|
||||
const resultJson = utf8Decoder.decode(resultBytes);
|
||||
const result = JSON.parse(resultJson);
|
||||
console.log('*** Result:', result);
|
||||
}
|
||||
|
||||
async function newGrpcConnection(): Promise<grpc.Client> {
|
||||
const tlsRootCert = await fs.promises.readFile(tlsCertPath);
|
||||
const tlsCredentials = grpc.credentials.createSsl(tlsRootCert);
|
||||
|
||||
return new grpc.Client(peerEndpoint, tlsCredentials, {
|
||||
'grpc.ssl_target_name_override': 'peer0.org1.example.com'
|
||||
});
|
||||
}
|
||||
|
||||
// Create a new HSM Signer
|
||||
async function newHSMSigner(hsmSignerFactory: HSMSignerFactory, certificatePEM: string): Promise<HSMSigner> {
|
||||
const ski = getSKIFromCertificate(certificatePEM);
|
||||
|
||||
// Options for the signer based on using SoftHSM with Token initialized as follows
|
||||
// softhsm2-util --init-token --slot 0 --label "ForFabric" --pin 98765432 --so-pin 1234
|
||||
const hsmSignerOptions: HSMSignerOptions = {
|
||||
label: 'ForFabric',
|
||||
pin: '98765432',
|
||||
identifier: ski
|
||||
}
|
||||
return hsmSignerFactory.newSigner(hsmSignerOptions);
|
||||
}
|
||||
|
||||
// Utility to find the SoftHSM PKCS11 library as it's location can vary based on
|
||||
// operating system and version
|
||||
function findSoftHSMPKCS11Lib(): string {
|
||||
const commonSoftHSMPathNames = [
|
||||
'/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',
|
||||
];
|
||||
const pkcs11lib = process.env['PKCS11_LIB'];
|
||||
if (pkcs11lib) {
|
||||
commonSoftHSMPathNames.push(pkcs11lib);
|
||||
}
|
||||
for (const pathnameToTry of commonSoftHSMPathNames) {
|
||||
if (fs.existsSync(pathnameToTry)) {
|
||||
return pathnameToTry
|
||||
}
|
||||
}
|
||||
|
||||
throw new Error('Unable to find PKCS11 library')
|
||||
}
|
||||
|
||||
// fabric-ca-client set's the CKA_ID of the public/private keys in the HSM to a generated SKI
|
||||
// value. This function replicates that calculation from a certificate PEM so that the HSM
|
||||
// object associated with the certificate can be found
|
||||
function getSKIFromCertificate(certificatePEM: string): Buffer {
|
||||
const key = jsrsa.KEYUTIL.getKey(certificatePEM);
|
||||
const uncompressedPoint = getUncompressedPointOnCurve(key as jsrsa.KJUR.crypto.ECDSA);
|
||||
const hashBuffer = crypto.createHash('sha256');
|
||||
hashBuffer.update(uncompressedPoint);
|
||||
|
||||
const digest = hashBuffer.digest('hex');
|
||||
return Buffer.from(digest, 'hex');
|
||||
}
|
||||
|
||||
function getUncompressedPointOnCurve(key: jsrsa.KJUR.crypto.ECDSA): Buffer {
|
||||
const xyhex = key.getPublicKeyXYHex();
|
||||
const xBuffer = Buffer.from(xyhex.x, 'hex');
|
||||
const yBuffer = Buffer.from(xyhex.y, 'hex');
|
||||
const uncompressedPrefix = Buffer.from('04', 'hex');
|
||||
const uncompressedPoint = Buffer.concat([uncompressedPrefix, xBuffer, yBuffer]);
|
||||
return uncompressedPoint;
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
{
|
||||
"$schema": "https://json.schemastore.org/tsconfig",
|
||||
"extends": "@tsconfig/node14/tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"declaration": true,
|
||||
"declarationMap": true,
|
||||
"sourceMap": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "src",
|
||||
"strict": true,
|
||||
"noUnusedLocals": true,
|
||||
"noImplicitReturns": true,
|
||||
"forceConsistentCasingInFileNames": true
|
||||
},
|
||||
"include": [
|
||||
"src/"
|
||||
]
|
||||
}
|
||||
1
hardware-security-module/ca-client-config/.gitignore
vendored
Normal file
1
hardware-security-module/ca-client-config/.gitignore
vendored
Normal file
|
|
@ -0,0 +1 @@
|
|||
fabric-ca-client-config.yaml
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
|
||||
#############################################################################
|
||||
# This is a configuration file for the fabric-ca-client command.
|
||||
#
|
||||
# COMMAND LINE ARGUMENTS AND ENVIRONMENT VARIABLES
|
||||
# ------------------------------------------------
|
||||
# Each configuration element can be overridden via command line
|
||||
# arguments or environment variables. The precedence for determining
|
||||
# the value of each element is as follows:
|
||||
# 1) command line argument
|
||||
# Examples:
|
||||
# a) --url https://localhost:7054
|
||||
# To set the fabric-ca server url
|
||||
# b) --tls.client.certfile certfile.pem
|
||||
# To set the client certificate for TLS
|
||||
# 2) environment variable
|
||||
# Examples:
|
||||
# a) FABRIC_CA_CLIENT_URL=https://localhost:7054
|
||||
# To set the fabric-ca server url
|
||||
# b) FABRIC_CA_CLIENT_TLS_CLIENT_CERTFILE=certfile.pem
|
||||
# To set the client certificate for TLS
|
||||
# 3) configuration file
|
||||
# 4) default value (if there is one)
|
||||
# All default values are shown beside each element below.
|
||||
#
|
||||
# FILE NAME ELEMENTS
|
||||
# ------------------
|
||||
# The value of all fields whose name ends with "file" or "files" are
|
||||
# name or names of other files.
|
||||
# For example, see "tls.certfiles" and "tls.client.certfile".
|
||||
# The value of each of these fields can be a simple filename, a
|
||||
# relative path, or an absolute path. If the value is not an
|
||||
# absolute path, it is interpreted as being relative to the location
|
||||
# of this configuration file.
|
||||
#
|
||||
#############################################################################
|
||||
|
||||
#############################################################################
|
||||
# Client Configuration
|
||||
#############################################################################
|
||||
|
||||
# URL of the Fabric-ca-server (default: http://localhost:7054)
|
||||
url: http://localhost:7054
|
||||
|
||||
# Membership Service Provider (MSP) directory
|
||||
# This is useful when the client is used to enroll a peer or orderer, so
|
||||
# that the enrollment artifacts are stored in the format expected by MSP.
|
||||
mspdir: caadmin
|
||||
|
||||
#############################################################################
|
||||
# TLS section for secure socket connection
|
||||
#
|
||||
# certfiles - PEM-encoded list of trusted root certificate files
|
||||
# client:
|
||||
# certfile - PEM-encoded certificate file for when client authentication
|
||||
# is enabled on server
|
||||
# keyfile - PEM-encoded key file for when client authentication
|
||||
# is enabled on server
|
||||
#############################################################################
|
||||
tls:
|
||||
# TLS section for secure socket connection
|
||||
certfiles:
|
||||
client:
|
||||
certfile:
|
||||
keyfile:
|
||||
|
||||
#############################################################################
|
||||
# Certificate Signing Request section for generating the CSR for an
|
||||
# enrollment certificate (ECert)
|
||||
#
|
||||
# cn - Used by CAs to determine which domain the certificate is to be generated for
|
||||
#
|
||||
# keyrequest - Properties to use when generating a private key.
|
||||
# algo - key generation algorithm to use
|
||||
# size - size of key to generate
|
||||
# reusekey - reuse existing key during reenrollment
|
||||
#
|
||||
# serialnumber - The serialnumber field, if specified, becomes part of the issued
|
||||
# certificate's DN (Distinguished Name). For example, one use case for this is
|
||||
# a company with its own CA (Certificate Authority) which issues certificates
|
||||
# to its employees and wants to include the employee's serial number in the DN
|
||||
# of its issued certificates.
|
||||
# WARNING: The serialnumber field should not be confused with the certificate's
|
||||
# serial number which is set by the CA but is not a component of the
|
||||
# certificate's DN.
|
||||
#
|
||||
# names - A list of name objects. Each name object should contain at least one
|
||||
# "C", "L", "O", or "ST" value (or any combination of these) where these
|
||||
# are abbreviations for the following:
|
||||
# "C": country
|
||||
# "L": locality or municipality (such as city or town name)
|
||||
# "O": organization
|
||||
# "OU": organizational unit, such as the department responsible for owning the key;
|
||||
# it can also be used for a "Doing Business As" (DBS) name
|
||||
# "ST": the state or province
|
||||
#
|
||||
# Note that the "OU" or organizational units of an ECert are always set according
|
||||
# to the values of the identities type and affiliation. OUs are calculated for an enroll
|
||||
# as OU=<type>, OU=<affiliationRoot>, ..., OU=<affiliationLeaf>. For example, an identity
|
||||
# of type "client" with an affiliation of "org1.dept2.team3" would have the following
|
||||
# organizational units: OU=client, OU=org1, OU=dept2, OU=team3
|
||||
#
|
||||
# hosts - A list of host names for which the certificate should be valid
|
||||
#
|
||||
#############################################################################
|
||||
csr:
|
||||
cn: admin
|
||||
keyrequest:
|
||||
algo: ecdsa
|
||||
size: 256
|
||||
reusekey: false
|
||||
serialnumber:
|
||||
names:
|
||||
- C: US
|
||||
ST: North Carolina
|
||||
L:
|
||||
O: Hyperledger
|
||||
OU: Fabric
|
||||
hosts:
|
||||
- tryfabric
|
||||
|
||||
#############################################################################
|
||||
# Registration section used to register a new identity with fabric-ca server
|
||||
#
|
||||
# name - Unique name of the identity
|
||||
# type - Type of identity being registered (e.g. 'peer, app, user')
|
||||
# affiliation - The identity's affiliation
|
||||
# maxenrollments - The maximum number of times the secret can be reused to enroll.
|
||||
# Specially, -1 means unlimited; 0 means to use CA's max enrollment
|
||||
# value.
|
||||
# attributes - List of name/value pairs of attribute for identity
|
||||
#############################################################################
|
||||
id:
|
||||
name:
|
||||
type:
|
||||
affiliation:
|
||||
maxenrollments: 0
|
||||
attributes:
|
||||
# - name:
|
||||
# value:
|
||||
|
||||
#############################################################################
|
||||
# Enrollment section used to enroll an identity with fabric-ca server
|
||||
#
|
||||
# profile - Name of the signing profile to use in issuing the certificate
|
||||
# label - Label to use in HSM operations
|
||||
#############################################################################
|
||||
enrollment:
|
||||
profile:
|
||||
label:
|
||||
|
||||
#############################################################################
|
||||
# Name of the CA to connect to within the fabric-ca server
|
||||
#############################################################################
|
||||
caname:
|
||||
|
||||
#############################################################################
|
||||
# BCCSP (BlockChain Crypto Service Provider) section allows to select which
|
||||
# crypto implementation library to use
|
||||
#############################################################################
|
||||
bccsp:
|
||||
default: PKCS11
|
||||
PKCS11:
|
||||
Library: REPLACE_ME_HSMLIB
|
||||
Pin: 98765432
|
||||
Label: ForFabric
|
||||
hash: SHA2
|
||||
security: 256
|
||||
|
|
@ -38,8 +38,8 @@ HSM2_CONF=$HOME/softhsm2.conf
|
|||
# Update the client config file to point to the softhsm pkcs11 library
|
||||
# which must be in $HOME/softhsm directory
|
||||
|
||||
CLIENT_CONFIG_TEMPLATE=../ca-client-config/fabric-ca-client-config-template.yaml
|
||||
CLIENT_CONFIG=../ca-client-config/fabric-ca-client-config.yaml
|
||||
CLIENT_CONFIG_TEMPLATE=${SCRIPT_DIR}/../ca-client-config/fabric-ca-client-config-template.yaml
|
||||
CLIENT_CONFIG=${SCRIPT_DIR}/../ca-client-config/fabric-ca-client-config.yaml
|
||||
cp $CLIENT_CONFIG_TEMPLATE $CLIENT_CONFIG
|
||||
|
||||
if [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
|
|
@ -49,7 +49,7 @@ else
|
|||
fi
|
||||
|
||||
# create the users, remove any existing users
|
||||
CRYPTO_PATH=$PWD/../crypto-material/hsm
|
||||
CRYPTO_PATH=$SCRIPT_DIR/../crypto-material/hsm
|
||||
[ -d "$CRYPTO_PATH" ] && rm -fr "$CRYPTO_PATH"
|
||||
|
||||
# user passed in as parameter
|
||||
|
|
|
|||
Loading…
Reference in a new issue