Introduction
In this article, we will illustrate our solution and problems we faced when developing a blockchain system in Quorum that leverages Hardware Security Module (HSM) [1] for generating private keys and signing transactions that would be executed on the blockchain. Furthermore, we will present a simple use case of asset transferring where we will showcase an architecture that presents how HSM can be integrated into the system.
Caveat emptor, this article is technology-heavy. Unfortunately, this article assumes that you have a basic understanding and idea of the following topics: blockchain, public key infrastructure (PKI) and knowing that Quorum is a permission-based blockchain version of Ethereum, as they will not be explained.
Problem introduction
The blockchain system that we were designing and implementing had one really interesting requirement, that multiple users in an organization have to be able to concurrently transact with the Quorum blockchain from the same account. Remember this, as this sets the one for the rest of the post.
Let’s take a step back and explain how Quorum handles accounts. Traditionally when interacting with Quorum users would be responsible for creating their account, by generating private and public key pairs and transacting with the blockchain network which would result in the account being created on the Quorum. Private keys and the user’s ability to interact with the network are stored on the user’s side in the application usually called wallet (e.g MetaMask [2]). This way the user has full ownership of the account and interaction with the blockchain.
As said earlier in the article we had a little bit different requirements, that the multiple users could be able to transact on the same Quorum account simultaneously. This brought a lot of implications due to the fact of how Quorum stores accounts if they are registered on the system rather than generated and registered outside on the client’s wallet.
When accounts are registered on the Quorum directly, you have to choose a peer (Quorum node) which will generate private and public keys for the account. Now this doesn’t sound too bad, right? But it is, private keys are not securely stored and if the users want to transact with the network we have to target this node when sending the request to the network. This is bad as we lose the ability to do load balancing (albeit all nodes in the Quorum have to execute the transaction) and if for some reason this node is not available we cannot sign transactions and transact on the network. And of course, let’s not forget the possibility of a catastrophic failure where we lose all peer data and then users are forever locked out of their accounts.
Considering that this platform would have been used as SaaS it is not reasonable for each organization to manage and host their own peers and manage their private keys and account access.
Our solution
The solution had to meet our following criteria: secure storage of private keys, the secure signing of transactions, data redundancy, organizations’ trust that only their users can use the account securely.
Enter the stage, Hardware Security Module. HSM is a system that logically and physically protects cryptographic keys and cryptographic processes. HSM devices have built-in mechanisms that detect physical attempts of system breakage. For our purposes, we are using HSM for generating private and public key pairs and signing of transactions in a secure environment.
We have chosen and used the following technologies for developing our solution:
- Quorum Blockchain – as underlying blockchain platform for transacting among organizations
- NodeJS – because we love NodeJS and felt that it is a good fit for this use case, and it turned out that it is.
Components that are implemented in NodeJS are: Application Server and Crypto Server - PostgreSQL for storage of user and organization related data
- Graphene [3] for interacting with the PKCS#11 interface. Shoutout to Graphene as it is a very well written and documented library.
- Docker
- CloudHSM in production
- SoftHSM [4] while in development
Now is a good time to introduce components in the architecture shown on the image below, that are responsible for this:
- Application server – is used to communicate with the Quorum nodes, sends transactions and receives transaction results and queries to the ledger. It is also responsible for communication with the database and retrieving/storing of user or organizational related data.
- Crypto Server – is used to communicate with the HSM using the standard PKCS#11 interface
When transferring tokens, the client application must submit the required parameters for one account to transfer funds to another. The process of transferring tokens consists of these steps:
- Client application initiates the token transfer and sends these parameters:
- amount – the amount of tokens that you are transferring
- addressTo – token receiver’s address
- password – password used for data encryption needed in communication with HSM
- JWT (JSON Web Token) – Contains necessary parameters for identifying the client after authentication
- After it receives the message, the application server decodes and validates the JWT and, together with pulled parameters, gets encrypted data from the database.
- The symmetric key used for encryption is created using PBKDF2 (Password-Based Key Derivation Function 2) algorithm
- Encrypted data is decrypted with the symmetric key and you get the data needed for communication with HSM:
- userPin – user’s PIN on the token which stores private keys
- tokenID – token identifier
- tokenSerial – a serial number assigned to the token after the creation
- The application server sends the request to the smart contract to check if the sender has enough funds to do the transfer. If the sender has enough funds, the process proceeds to the next step. If not, it will return an error message. The application server sends the request for transferring the token on the crypto server.
- After receiving the message, the crypto server forms a transaction object and sends it to the HSM for signing with the organization’s private key.
- And now for the fun stuff. With the given parameters HSM finds an appropriate slot and token that is storing the private key needed for signature and unlocks it with the given userPin. HSM uses this private key to create a signature using private key and transaction data sent from the application server, the result is a signed transaction. HSM sends a signed transaction to the crypto server, and the crypto server forwards it to the application server.
- Application server sends signed transaction for execution on Quorum
- Result of smart contract execution is sent back to check if the transfer was successful or not
- The result with the positive or negative outcome is sent on the client application
Problems we faced
If you are not keen on spending a lot of money to pay for a production-grade HSM while in the development phase you will most likely use SoftHSM like we did. Don’t feel bad, SoftHSM is a great piece of software made by OpenDNSSEC guys, so thanks to them we can easily test our APIs against what would be an HSM through the PKCS#11 interface.
You should be aware that there is a slight difference in the implementation of the transaction signing function in the implementation of the secp256k1 algorithm of elliptic curves between OpenSSL and the algorithm that Quorum uses. Because SoftHSM uses OpenSSL for its underlying cryptographic operations, like signature creation, key pair generation, etc. OpenSSL can generate one of the parameters of the elliptic curve to be beyond the acceptable limits defined by the implementation of the secp256k1 algorithm that Quorum uses.
To fix this, we had to scale and normalize the parameters of the elliptic curve. You can imagine the amount of stress and frustrations until we have finally figured out what the underlying problem was.
Conclusion
In the end, we have managed to meet our criteria for securely storing organizational private keys, that multiple users can concurrently transact on the same account and data redundancy. Although bringing in a component like HSM into architecture can increase its complexity and costs it is an integral part of securing private keys in a system like ours.