How to use Python to sign data with the hierarchical deterministic wallet on a MIRkey or eHSM Hardware Security Module

Last updated July 11, 2019

In this Python example we will show you how easy it is to sign data with a HD ECC key on the MIRkey or eHSM.

For some background information on hierarchical deterministic wallets you might want to have a look at the BIP32 specification. In a nutshell, the BIP32 specification (or “HD wallets”) defines a way to derive ECC keys from a master key (“m”) and address those keys using a derivation path. The derivation path is basically an index to a key in the derived key tree.

graph LR M(fa:fa-key Master key m) --> Z(Child Key m/0) M --> One(Child Key m/1) M --> N(Child Key m/N) Z --> ZZ(Child Key m/0/0) Z --> ZOne(Child Key m/0/N) style M fill:#ccf,stroke:#f66,stroke-width:2px,stroke-dasharray: 5, 5

For example, looking that the graph above, to sign with key “m/0/N” using the ehsm library you will provide the following array as parameter: [0,0,N], where N is the child key number at depth 2. The array length is the tree depth and the value at the depth is number of the child key.

As usual, for the full source code, refer to the github repository.

Prerequisites

  1. If you have not done so already, download and install the native shared library for your platform here: https://ellipticsecure.com/downloads/

    Important: Always verify the signature of the downloaded files

  2. Initialize the device and set a user PIN with the eHSM Manager or pkcs11 tool

  3. Install the ehsm Python wrapper

     pip install ehsm
    

Looking at the code

First, we need to initialize the library, find an available device slot, and get a logged in session using the user PIN:

    ...
    mirkey = ehsm.load_ehsm()
    slots = mirkey.enumerate_slots()

    if len(slots) > 0:
        # Use the first available slot
        slot = slots[0]
        # Initialize the library
        mirkey.init()
        try:
            session = mirkey.get_logged_in_rw_session(slot, pin)
            ...
        finally:
            mirkey.finalize()

Note that we always use a try/finally block to ensure resources and device handles are properly cleaned up.

With the logged in session handle, we can now sign a 32 byte hash of the data using the desired indexes to the key as explained above:

        ...
        sig = mirkey.bip32_sign_data(session, to_sign_hash, indexes)
        print(binascii.hexlify(sig).decode("utf-8"))
        ...

To use the example code on the command line you can provide the derivation path using a csv string and the hash to sign, ie.:

  ./hdwallet-example.py 0,0,1 30440220644ff4e8877ac01ba12e72b1c1dcfee67a4d932d28b721b1249eaf16

Questions or suggestions? Please contact us using the Support widget or submit a ticket.

Subscribe to receive updates

* indicates required