Innovating with BOLOS : building an Ethereum Hardware Wallet
In our previous article we introduced BOLOS : a platform to innovate around the edges of Personal Security Devices, making sure that your private data stays protected when using embedded third party applications. We’ll have a look today at an interesting example from the point of view of an Hardware Wallet designer : how to enhance the security of a significantly different blockchain, Ethereum.
This is of course in no way an investment advice — just a nice use case which is complex enough to make it hard to implement on a legacy Hardware Wallet, yet simple enough to use it as a BOLOS API training. Also we’re still large Ethereum newbies, so expect gross oversimplifications and a few mistakes. The cryptographic and protocol parts should make sense though.
An Ethereum primer for Bitcoin Hardware Wallet developers
On the easy side, Ethereum user accounts (Externally Owned Accounts) rely on transactions that are more simple than Bitcoin transactions (as the system maintains a state and balance, no inputs are involved) and use the same secp256k1 ECDSA signature scheme than Bitcoin. However the hash algorithm and transaction encoding used are slightly different. Ethereum also handles contract accounts which are managed directly by code and therefore out of scope of Hardware Wallet security as the state of the network guarantees that their execution is consistent.
The hash algorithm used is the pre-release version of SHA-3, Keccak-256 — this can be a bit confusing for newcomers as SHA-3 is released now, and it is quite important to use the right version of the algorithm as it is also used to generate Ethereum addresses, which have no checksum. It is fairly easy to add if your compiler supports 64 bits arithmetic for your platform.
Ethereum also doesn’t include information about the sender account in the transaction — the public key is recovered from the signature. This can be done by iterating on the 4 possible candidates on the client side if the Hardware Wallet API doesn’t support it (which is temporarily the case for BOLOS, because that specific functionality isn’t exposed) but it is more efficient to send back this information along with the signature if possible (e.g. as done in Fast_Sign_Verify)
Transactions include the following fields and are serialized using a proprietary algorithm named Recursive Length Prefix
- A Nonce, matching the state of the account. This field doesn’t need to be validated by the user
- Information about the resources offered to the network to process the transaction, set by the transaction itself (startgas) and how it is billed by miners (gasprice). Those can be useful to verify by the user to make sure that you are not overpaying for your service.
- A value and destination address. Those should definitely be validated.
- Additional arbitrary data, which can also be important to validate when sending the transaction to a contract. Our sample code doesn’t use it, but it is typically something that can be added and matched specifically for each contract with BOLOS, providing an additional layer of security and convenience to the end user.
The key used to identify an account is a Keccak-256 hash of an uncompressed secp256k1 public key. Wallets can use an arbitrary Hierarchical Deterministic derivation scheme to support several accounts (for example Jaxx supports SLIP 44 with Coin Type 60). As the standard keys encoding doesn’t include a checksum, wallets can also support the ICAP format, derived from the banking IBAN format, which adds one.
We implemented the address generation from a Hierarchical Deterministic wallet along with an ICAP representation of the address in another BOLOS application
Trying this at home
You can start playing with BOLOS API on a Trusted Execution Environment today with the following requirements :
- Use a handset with a Trustonic TEE, preferably a Samsung supporting the Trusted UI feature (or you’ll have to modify a bit the samples) — those include all Galaxy S6 variants, all Note 5 variants, Exynos based Note 4 and Exynos based Galaxy S7.
- Clone and compile moxiebox Moxie cross compiler toolchain. A Docker image is also available.
- Clone and compile BOLOS TEE tools and Moxie BOLOS runtime from our github. Generate a secp256k1 keypair (preferably on an offline computer) that you’ll use to sign BOLOS application that can be run on the TEE.
- Get the latest version of the Ledger Trusted application, and provide your public secp256k1 key in the “Options” menu BEFORE purchasing a license
- Clone and compile Ledger Wallet Proxy from our github. This application let you interact easily with the TEE application from your computer — it is a convenient way to develop and debug your TEE logic before using it in a phone application, or if you want to use it as a cheap HSM or dedicated validation hardware.
- Get the BOLOS TEE samples, compile them and sign them (preferably on an offline computer)
- Run the samples through Ledger Wallet Proxy, using the provided Python scripts
- Try new things, without being afraid of breaking anything or revealing your key material
If you are interested in a finalized version of Ethereum support, we will add TEE support to Jaxx shortly.
Our next articles will describe how to write similar applications for Ledger Blue, available for developers this month