We have been working on a Nervos application for the Ledger Nano S and Nano X devices. During our work we’ve identified some changes to CKB-CLI that would allow for the support of hardware wallets with on-device operation validation through plugins specific to each hardware wallet, including but not limited to Ledger devices (see CKB-CLI Issue #268). We’ve also found additional areas of improvement that build upon the work of our initial grant proposal. We intend to make these improvements through this grant proposal. When this is done the Nervos community can use the Ledger application with Nervos’ command line, integrations with additional hardware wallets will be easier, and valuable new features will be supported in the Nervos Ledger app.
Obsidian Systems was founded in 2014 by Ali Abrar and Ryan Trinkle, who continue to serve as its managing partners today. It consists of approximately 39 software developers, quality assurance engineers, management professionals, and other staff.
Obsidian Systems designs and develops high quality software solutions to pressing business problems. Our experienced team has delivered mission-critical solutions to a variety of high-profile clients, including several Fortune 500 companies and national retail firms, and blockchains such as Tezos, Kadena, and Nervos. These solutions secure millions of dollars in cryptographic assets (Tezos Baking/Wallet Ledger applications), lower the technical barrier to participation in consensus (Kiln), and facilitate the development of smart contracts (Pact and Chainweaver).
Our solutions are currently used by thousands of employees and tens of thousands of consumers every day.
Hardware Support in CKB-CLI
Storage of Hardware wallet root public keys in CKB-CLI
CKB-CLI should store the root public key of hardware wallets in the client so it is able to compute the source and change address according to BIP44 specification. With our work thus far, the client can discover a connected hardware wallet using account-list, which returns an opaque device identifier:
CKB> account list - "#": 0 account_source: ledger hardware wallet ledger_id: 0x27fe5acb022cd7b8be0eb7009d42ff4600c597d28b6affefcab6f7396d1311c2
With that device identifier, keys could then be imported with an extension of account-new functionality:
CKB> account new --ledger <opaque-id> —account <num> * `--ledger` passes ledger_id found using account list (shown above) * `--account` (optional) defaults to the lowest value upon which it does not find a transaction history. This corresponds to m/44'/309'/ACCOUNT'/change/address_index.
Pass Hardware Wallets Unhashed Transaction and Context Data
The security model of hardware wallets relies on being able to verify all the contents of an operation on the device so the user can operate securely even when the client has been compromised. For this to work properly, the hardware wallet cannot securely sign pre-hashed data, as its contents are not verifiable.
We’ve started making these changes to the extent that it was necessary for development of the Ledger BOLOS application, but some items remain. Specifically:
- All signing should happen through
tx_helper’s functionality instead of directly via a
- Our work thus far on CKB-SDK should be made hardware wallet agnostic with the goal of supporting each hardware wallet through their own plugin. As it stands, it contains some
is_ledgerbooleans throughout CKB-CLI which should be removed.
List Multiple Connected Ledger Devices
When calling the account list function shown above, the client will return the first ledger device it finds. We’ll improve upon this so all connected Ledger devices with the Nervos application open will be found by account list.
Shift Ledger Support to a Plugin
Once all the changes detailed above have been made in CKB-CLI, all relevant Ledger code will be well contained within the CKB-Ledger crate. This create should then be converted to a plugin. Once completed, CKB-CLI will continue to support signing with software wallets, agnostically support signing for hardware wallets, and a plugin for Ledger devices will be available.
We’ll make the following improvements to the Nervos Ledger application and LedgerJS:
Message signing allows an individual to prove ownership of an address without providing a signature which can be used maliciously. Nervos has an existing sign-message utility available in CKB-CLI which we’d extend to call the ledger device when given a Ledger address. We will also prepend message signing operations with a magic byte so they are easily discernible from other operation types and use this as our cue to show a verifiable prompt to the Ledger application which let’s the user know they are signing a message.
Multi-sig Lock Script Signing
The Ledger application can sign transactions and DAO operations when it is the only signature necessary for a given lock script. We will extend this to also support signing of multi-sig transactions from the Ledger device.
LedgerJS Maintenance and Improvements
While LedgerJS is feature complete in its support of Nervos, We’d like to keep it up to date with upstream LedgerJS (now on v5.13.1 as of this writing), ensure new features added to the Ledger application in this proposal are supported, and add refinements so it is more palatable for an upstream merge.
While we have submitted an upstream merge to LedgerJS, Ledger has this to say on the topic:
We invite all third party app developers to not send PR to this repository to provide more implementations but instead to maintain your own version in your own repository and we would be happy to reference them here .
Whether merged into upstream LedgerJS or maintained in our repository and referenced upstream, wallet providers and the community can expect no difference in their ability to use this library to communicate with the Nervos Ledger application.
We estimate the implementation of this spec will take between 5 and 8 developer weeks.
There are four checkpoints we can use to track progress:
- Client Changes Complete Natively - We feel it is cleaner to be feature complete first, then address organization.
- Ledger Features Complete - This includes message signing and multisig lock script signing. Note that message signing will include adjustments in the client.
- Ledger-Specific code moved into the plugin - Once the client is feature complete and the corresponding Ledger development is done, it should be clear which sections of code should be moved into the plugin system and which should stay within the client.
- LedgerJS Maintenance and Improvements Complete - Once the new Ledger features are ready, we can support them in LedgerJS. Maintenance tasks to LedgerJS can be done in parallel with other checkpoints listed above.