Ethereum Blockchain
This guide outlines step-by-step instructions for seamlessly integrating Ethereum Blockchain with a Luna HSM device or Luna Cloud HSM service. Ethereum accounts are essentially files containing public and private key pairs, which act as unique identities on the blockchain. The HSM wallet provides the capability to create and safeguard ECDSA/BIP32 key pairs using Luna HSM. Subsequently, these key pairs can be employed for signing Ethereum transactions with the added layer of security provided by Luna HSM. The HSM wallet communicates with Luna HSM through a PKCS#11 API, and each PKCS#11 partition corresponds to a distinct HSM wallet.
The key benefits of this integration are:
-
Secure generation, storage, and protection of the identity signing private keys using either FIPS 140-2 or FIPS 140-3 Level 3 validated hardware.
-
Full life cycle management of the keys to ensure their integrity and reliability throughout their usage.
-
Maintenance of a comprehensive HSM audit trail for transparency and accountability in key operations. It's important to note that Luna Cloud HSM service does not have access to this secure audit trail.
-
Significant performance enhancements by offloading cryptographic operations from application servers.
Supported Platforms
This integration has been tested and verified on the following platforms:
HSM Type | Platform Tested |
---|---|
Luna HSM | RHEL Ubuntu |
Luna Cloud HSM | RHEL Ubuntu |
Prerequisites
The prerequisites for this integration are:
Set up Luna HSM
As the first step to accomplish this integration, you need to set up either On-Premise Luna HSM or Luna Cloud HSM.
Set up On-Premise Luna HSM
Follow these steps to set up your on-premise Luna HSM:
Ensure that the HSM is set up, initialized, provisioned, and ready for deployment. For more information, refer to Luna HSM documentation.
Create a partition that will be later on used by HSM Wallet.
Create and exchange certificate between the Luna Network HSM and client system. Register client and assign partition to create an NTLS connection.
Initialize Crypto Officer and Crypto User roles for the registered partition.
Refer to Luna HSM documentation for detailed steps on creating NTLS connection, initializing the partitions, and assigning various user roles.
Set up Luna HSM High-Availability Group
Refer to Luna HSM documentation for HA steps and details regarding configuring and setting up two or more HSM boxes on host systems. You must enable the HAOnly setting in HA for failover to work so that if the primary goes down due to any reason, all calls get automatically routed to the secondary until the primary recovers and starts up.
Set up Luna HSM in FIPS mode
To configure Luna HSM in FIPS Mode, update the configuration file by adding or modifying the following setting within the [Misc]
section:
RSAKeyGenMechRemap=1
This setting ensures that older calling mechanisms are redirected to the approved RSA key generation methods (186-3 with primes and 186-3 with aux primes) required for FIPS compliance. By making this configuration change, Luna HSM will be properly set up to operate in FIPS mode, adhering to the approved RSA key generation standards.
The configuration setting mentioned above, RSAKeyGenMechRemap=1
, is not required for the Universal Client. It is applicable only for Luna Client 7.x.
Set up Luna Cloud HSM
Follow these steps to set up your Luna Cloud HSM:
Transfer the downloaded .zip file to your client workstation using pscp, scp, or other secure means
This integration has been certified on the RHEL platform.
Extract the .zip file into a directory on your client workstation.
Extract or untar the appropriate client package for your operating system. Do not extract to a new subdirectory; place the files in the client install directory.
tar -xvf cvclient-min.tar
Run the setenv script to create a new configuration file containing information required by the Luna Cloud HSM service.
source ./setenv
To add the configuration to an already installed UC client, use the –addcloudhsm option when running the setenv script.
Run the LunaCM utility and verify that the Cloud HSM service is listed.
If your organization requires non-FIPS algorithms for your operations, ensure that the Allow non-FIPS approved algorithms check box is checked. For more information, refer to Supported Mechanisms.
Set up Go-Ethereum
Follow these steps to set up Go-Ethereum on a Linux operating system:
Install Prerequisite Libraries
You'll need to install some necessary libraries on your Linux operating system. Use the appropriate command for your distribution:
For Red Hat Enterprise Linux (RHEL):
sudo yum install git python3-pip libtool-ltdl-devel
For Ubuntu:
sudo apt-get install git alien python3-pip libltdl-dev
Install and configure Golang
Go-Ethereum relies on the Go programming language for many of its components. To install Golang, follow the instructions provided in the official installation guide. Alternatively, you can download the Golang binaries directly from the official Golang website.
Install and set up Docker and Docker-compose
Ensure that you have Docker and Docker-compose installed on the platform where you intend to run Go-Ethereum. To install Docker, visit the official Docker website. After successfully installing Docker, proceed to install Docker-compose using the following command:
sudo pip3 install docker-compose
For optimal compatibility and security, it is advisable to always utilize the most up-to-date versions of Docker and Docker-compose.
Prepare Luna HSM for integration with Ethereum Blockchain
Adopt one of the following approaches to prepare your HSM for integration with Ethereum Blockchain:
Prepare On-Premise Luna HSM for integration
To prepare On-Premise Luna HSM for integration with Ethereum Blockchain, follow these steps:
Ensure that your Luna HSM is set up, initialized, provisioned, and ready for deployment.
Create two HSM partitions, for example, TPA01 and TPA02. These partitions will be used by the Ethereum Blockchain nodes, geth1 and geth2. You can choose to use the same HSM or different HSMs for each partition, and you are free to define partition names.
Create the necessary directories on your client machine:
mkdir -p /usr/local/lunaclient mkdir -p /etc/geth/lunaconf1 mkdir -p /etc/geth/lunaconf2
Extract the Luna Client minimal package installer into the /usr/local/lunaclient
directory:
tar -C /usr/local/lunaclient --strip 1 -xvf LunaClient-Minimal-[release_version].x86_64.tar
Set the ChrystokiConfigurationPath
variable to point to the /etc/geth/lunaconf1
directory:
export ChrystokiConfigurationPath=/etc/geth/lunaconf1
Copy the Chrystoki-template.conf
to the /etc/geth/lunaconf1
directory:
cp /usr/local/lunaclient/Chrystoki-template.conf /etc/geth/lunaconf1/Chrystoki.conf
Modify the Chrystoki2
section in /etc/geth/lunaconf1/Chrystoki.conf
as follows:
Chrystoki2 = { LibUNIX = /usr/local/lunaclient/libs/64/libCryptoki2.so; LibUNIX64 = /usr/local/lunaclient/libs/64/libCryptoki2_64.so; }
Update the LunaSA Client
section in /etc/geth/lunaconf1/Chrystoki.conf
with the following configurations:
LunaSA Client = { SSLConfigFile = /usr/local/lunaclient/openssl.cnf; ClientPrivKeyFile = /etc/geth/lunaconf1/; ClientCertFile = /etc/geth/lunaconf1/; ServerCAFile = /etc/geth/lunaconf1/CAFile.pem; }
Modify the Secure Trusted Channel
section in /etc/geth/lunaconf1/Chrystoki.conf
as follows:
Secure Trusted Channel = { ClientTokenLib = /usr/local/lunaclient/libs/64/libSoftToken.so; SoftTokenDir = /usr/local/lunaclient/stc/token; ClientIdentitiesDir = /usr/local/lunaclient/client_identities; PartitionIdentitiesDir = /usr/local/lunaclient/partition_identities; }
You can skip this step if STC is not enabled.
Copy the server certificate from the Luna HSM to the current directory:
scp admin@:server.pem .
Add the Luna HSM server certificate on the client:
/usr/local/lunaclient/bin/64/vtl addServer -n [HSM-IP] -c server.pem
Create the client certificate:
/usr/local/lunaclient/bin/64/vtl createCert -n geth1
Transfer the client certificate to the Luna HSM:
scp /etc/geth/lunaconf1/geth1.pem admin@[HSM-IP]:
Log in to the Luna HSM and register the client, then assign the TPA01 partition to the client.
Utilize the lunacm
utility from the client machine to initialize the partition and assign the Crypto Officer role.
If you are using PED-authenticated HSM, enable partition policies 22 and 23 to allow activation and auto-activation.
Refer to the Luna HSM documentation for detailed steps on creating NTLS connections, initializing partitions, and assigning various user roles.
Repeat steps 5 to 16 for the second HSM partition, replacing references to lunaconf1, geth1, and TPA01 with lunaconf2, geth2, and TPA02, respectively. Make sure to use the actual partition label.
Prepare Luna Cloud HSM for integration
To prepare Luna Cloud HSM for integration with Ethereum Blockchain, follow these steps:
In the Data Protection on Demand platform, create two Luna Cloud HSM Services within the Data Protection category. For detailed instructions on provisioning the HSM on Demand service and initializing the service client, please consult the Data Protection on Demand Application Owner Quick Start Guide.
For each Luna Cloud HSM Service created in Step 1, set up a client and download the client zip files to your host system.
Create the following directories on your client machine:
mkdir -p /etc/geth/lunaconf1 mkdir -p /etc/geth/lunaconf2
Unzip the downloaded client zip files into the corresponding directories, lunaconf1 and lunaconf2:
unzip /home/setup-.zip -d /etc/geth/lunaconf1 unzip /home/setup- .zip -d /etc/geth/lunaconf2
Navigate to the lunaconf1 and lunaconf2 directories and extract the cvclient-min.tar file in both directories:
cd /etc/geth/lunaconf1 tar -xvf cvclient-min.tar cd /etc/geth/lunaconf2 tar -xvf cvclient-min.tar
After initializing the partition and assigning the required roles, use the lunacm utility to verify that each partition is visible from the client.
To initialize both partitions and establish the Security Officer and Crypto Officer roles, please refer to the instructions provided in the Data Protection on Demand Application Owner Quick Start Guide.
Integrate Ethereum Blockchain with Luna HSM
Integrating Go-Ethereum with Luna HSM enables the generation of two distinct types of keys for signing Ethereum transactions: BIP32 and ECDSA. Luna HSM plays a pivotal role in safeguarding these critical account signing keys, ensuring that only authorized users possess the ability to access and employ them for executing secure transactions on the Ethereum Blockchain. In this section, you'll learn how to create these essential account signing keys using Luna HSM and subsequently, harness these Luna HSM-generated keys to sign Ethereum transactions securely.
-
Integrate Ethereum Blockchain with Luna HSM using BIP32 Keys
-
Integrate Ethereum Blockchain with Luna HSM using ECDSA Keys
Integrate Ethereum Blockchain with Luna HSM using BIP32 Keys
Follow these steps to integrate Ethereum with Luna HSM using BIP32 keys:
Ensure that Luna HSM or Luna Cloud HSM is operating in Non-FIPS mode. This mode is required because the BIP32 mechanism is not compatible with FIPS mode.
Ensure that the go
executable is in your system's PATH. You can do this with the following command:
export PATH=/usr/local/go/bin:$PATH
Clone the Go-Ethereum git repository onto your client machine:
git clone https://github.com/ThalesGroup/go-ethereum
Change your current directory to the cloned repository:
cd go-ethereum
Build the Geth binary:
make geth
Build a Docker image for a Geth node. Navigate to the example
directory:
cd example
Build the Docker image:
make build
Ensure that the Docker images have been built successfully:
docker images
Create a Geth configuration file in the go-ethereum/example
directory:
../build/bin/geth --networkid 8000 dumpconfig > config.toml
In the config.toml
file, add the following flags to the [Node]
section:
NoPKCS11BIP32 = false PKCS11Lib = "/usr/local/lunaclient/libs/64/libCryptoki2.so"
Create two ethash
directories for the Directed Acyclic Graph (DAG) in the go-ethereum/example
directory:
mkdir ethash1 mkdir ethash2
Initialize the data directories:
make clean make init
If you are using Luna Cloud HSM, you'll need to update the docker-compose.yaml
file in the go-ethereum/example
directory. Please make the following changes:
Please skip this step if you are using Luna HSM
-
Remove the line
/usr/local/lunaclient:/usr/local/lunaclient
from thevolumes
section ofgeth1
. -
Update the volume section of
geth1
by changing./config.toml:/etc/geth/config.toml
to./config1.toml:/etc/geth/config.toml
. -
Remove the line
/usr/local/lunaclient:/usr/local/lunaclient
from thevolumes
section ofgeth2
. -
Update the volume section of
geth2
by changing./config.toml:/etc/geth/config.toml
to./config2.toml:/etc/geth/config.toml
.
After making these changes, please ensure that your docker-compose.yaml
looks as specified.
Create two Docker containers, geth1
and geth2
, running the Geth image:
docker-compose up
Open a new terminal and attach to Node 1:
./console.sh 1
Initially, the wallet is closed. You can check the closed status by running the following command in console 1:
personal.listWallets
Open the wallet in console 1, providing the partition password when prompted:
personal.openWallet("hsm://[partition1]")
When you open the wallet for the first time, it will generate a master seed and derive a master key pair. A child key pair will be derived for the path m/44'/60'/0'/0/0
by the Self-Derive background task. Self-derivation will run in the background, automatically deriving new keys starting at path m/44'/60'/0'/0/0
. To see the account, you can run the personal.listWallets
command.
The background thread monitors the blockchain to determine whether the last derived key is part of a transaction and added to a block. If that's the case, the background thread will derive the next account, such as m/44'/60'/0'/1/0
, when listing accounts in the next step.
Derive an account with the following command:
personal.deriveAccount("hsm://[partition1]", "m/44'/60'/0'/1/0", true)
In this command, m/44'/60'/0'/1/0
refers to the path of the child key, and true
indicates that you want to keep track of the account for signing later on.
Set the coinbase to the new derived account:
miner.setEtherbase("[derived_account_address]")
Fund the account by starting the miner:
miner.start()
Wait for Generating DAG in progress
to complete. This activity can be observed in the docker-compose up
terminal. This process may take some time to finish. Wait for a few blocks to be mined before proceeding.
Check the balance for the derived account address:
eth.getBalance("[derived_account_address]")
Stop the miner after some blocks have been mined:
miner.stop()
Derive another account:
personal.deriveAccount("hsm://[partition1]", "m/44'/60'/0'/1/1", true)
Send funds from the first account to the second account:
eth.sendTransaction({from: sender, to: receiver, value: amount})
Resume mining to confirm the transaction:
miner.start()
Wait for some blocks to be mined in the "docker-compose up" terminal and then stop mining:
miner.stop()
Check the balance for the receiver's address. It should be 500000000000000000 Wei:
eth.getBalance("0x3f1947217ee231e02d203a81ebeee73db3248435")
This completes the integration of Ethereum Blockchain with Luna HSM using BIP32 keys. Please note that if you close the HSM wallet, you won't be able to perform any transactions until the wallet is opened again, and the account keys from Luna HSM are available for signing transactions.
Integrate Ethereum Blockchain with Luna HSM using ECDSA Keys
Follow these steps to integrate Ethereum with Luna HSM using ECDSA Keys:
Ensure that you have Go installed and accessible in your PATH.
Clone the Go-Ethereum Repository.
git clone https://github.com/ThalesGroup/go-ethereum cd go-ethereum
Build the Geth Binary.
make geth
Build a Docker Image for Geth.
cd example make build
Check Docker Images.
Verify that the Docker images are built successfully:
docker images
Create Geth Configuration in the go-ethereum/example
directory:
cd /opt/go-ethereum/example ../build/bin/geth --networkid 8000 dumpconfig > config.toml
For Luna Cloud HSM, create two config files as there are two different service clients:
../build/bin/geth --networkid 8000 dumpconfig > config1.toml ../build/bin/geth --networkid 8000 dumpconfig > config2.toml
Add the following configurations to the [Node]
section in config.toml
:
NoPKCS11BIP32 = true PKCS11Lib = "/usr/local/lunaclient/libs/64/libCryptoki2.so"
For Luna Cloud HSM, update config1.toml
and config2.toml
with similar configurations.
Create two directories for Ethash DAG data:
mkdir ethash1 mkdir ethash2
Initialize the data directories for Ethereum:
make clean make init
If using Luna Cloud HSM, update the docker-compose.yaml
file in the go-ethereum/example
directory with the following changes:
Skip this step if you are using Luna HSM.
-
Remove the line
/usr/local/lunaclient:/usr/local/lunaclient
from the[volumes]
section ofgeth1
. -
Update the volume section of
geth1
by changing./config.toml:/etc/geth/config.toml
to./config1.toml:/etc/geth/config.toml
. -
Remove the line
/usr/local/lunaclient:/usr/local/lunaclient
from the[volumes]
section ofgeth2
. -
Update the volume section of
geth2
by changing./config.toml:/etc/geth/config.toml
to./config2.toml:/etc/geth/config.toml
. -
Ensure that your
docker-compose.yaml
file is correctly updated.
Start two Docker containers (geth1
and geth2
) running the Geth image:
docker-compose up
In two separate terminals, attach to geth1
and geth2
nodes:
In Terminal 1:
./console.sh 1
In Terminal 2:
./console.sh 2
In both geth1
and geth2
consoles, open the wallet. Provide the partition password when prompted:
In Terminal 1:
personal.openWallet("hsm://[partition1]")
In Terminal 2:
personal.openWallet("hsm://[partition2]")
Check the wallet status in both terminals:
personal.listWallets
In both geth1
and geth2
consoles, create accounts:
In Terminal 1:
personal.newHsmAccount("hsm://[partition1]")
In Terminal 2:
personal.newHsmAccount("hsm://[partition2]")
You can also create accounts outside of the geth
node using the command:
geth --config config.toml account newhsm [partition]
In Terminal 2 (geth2 console), find the node address of the geth2
account:
admin.nodeInfo
The output will display the enode
field containing the node address.
In Terminal 1 (geth1 console), add geth2
as a peer using the enode
address obtained in the previous step. Replace the IP of the geth2
container with "10.8.0.4":
admin.addPeer("[geth2-enode-address]")
For example:
admin.addPeer("enode://b5f7e23f47277e34c8d7cefe066473e0b522eecce5407f2a5f13a6c794ae9964bf0dc5805a0cd4a8d93abd390d1535c1a7bea9e914f0c63f6c57e715aaf84910@10.8.0.4:30304")
Confirm that each node recognizes the other as peers by running the following command in each terminal:
admin.peers
Once both nodes are added as peers, you can start mining.
Start the miner in Terminal 1 (geth1 console):
miner.start()
Wait for the completion of the DAG generation process, which can take some time. You will see blocks being mined in the "docker-compose up" terminal.
Stop the miner in Terminal 1 (geth1 console) after the DAG generation process is completed and some blocks have been mined:
miner.stop()
In Terminal 1 (geth1 console), find the geth1
account address:
personal.listAccounts
Get the balance of the geth1
account in either Terminal 1 or Terminal 2. The account should show some ether:
eth.getBalance("")
Perform a transaction from the geth1
account to the geth2
account. Find the geth1
account address by executing personal.listAccounts
in Terminal 1 (geth1 console) and use it as the sender account address. Find the geth2
account address by executing personal.listAccounts
in Terminal 2 (geth2 console) and use it as the receiver account address to transfer ethers.
In Terminal 1:
eth.sendTransaction({from: sender, to: receiver, value: amount})
For example:
eth.sendTransaction({from: "0x8babb7fbb843d3300faf22ef61db4520982ae3e0", to: "0x13fb9c7967edf15759be769f143de81187b5cbef", value: web3.toWei(0.5, "ether")})
View the transaction by executing the following command in Terminal 1:
eth.pendingTransactions
Mine some more blocks in Terminal 1:
miner.start()
Wait for some blocks to be mined in the docker-compose up
terminal, then stop mining:
miner.stop()
In any terminal, observe the balance of the geth2
account:
eth.getBalance("[geth2-account-address]")
Observe the balance transferred in the transaction performed. As per the transaction, the balance in the geth2
account should be 500000000000000000.
Close the wallets.
In Terminal 1:
personal.closeWallet("hsm://[partition1]")
In Terminal 2:
personal.closeWallet("hsm://[partition2]")
After closing the wallet, you cannot perform any transactions as the signing keys from HSM are not available.