Inspiration

Following our implementation of Schnorr Signatures on the Satochip hardware wallet, we explored the feasibility of implementing MuSig2 multi-signature scheme (BIP327) for this hackaton. MuSig2's advanced cryptography enables compact, private, and cost-effective Bitcoin multi-sig transactions.

What it does

Satochip (https://satochip.io) is an open-source hardware wallet based on a smartcard, with a firmware ('applet') written in javacard language. Satochip already supported BIP32 seed derivation, ECDSA signatures and Taproot (based on Schnorr signatures). We have now added MuSig2 for Bitcoin multi-signature transactions. Compared to traditional Bitcoin multi-signatures, MuSig2 signatures are indistinguishable from single signatures, and they are more compact, thus increasing privacy and reducing the fees for multi-sig.

Satochip supports both contact and contactless communications, using either a smartcard reader (i.e. with computer) or NFC (for smartphone) to communicate with the wallet application on mobile or computer.

How we built it

Given the resource limitations of smartcards (no display/button and constrained memory), we’ve implemented a partial version of the BIP327 specification, specifically the following algorithms that involve the private key and/or random nonce:

  • Nonce generation: NonceGen(sk, pk, aggpk, m, extra_in)
  • Partial signing: Sign(secnonce, sk, session_ctx)

NonceGen:

  • The private key (sk) is derived from a seed imported onto the card during setup.
  • The card uses the internal sk, along with wallet-provided data (pk, aggpk, 32-byte m, and 32-byte extra_in) and 32 bytes of internal randomness to generate the pubnonce and secnonce.
  • The pubnonce is returned to the wallet, and the secnonce is encrypted using a random 16-byte key only known to the card.
  • Exporting the encrypted secnonce avoids having to store it in card memory, enabling multiple parallel NonceGen() sessions.

Sign:

  • The wallet sends back the encrypted secnonce and session context data to the card.
  • The card decrypts the secnonce, verifies it matches the expected public key, and performs the signing operation using its internal private key.
  • The final output is the 32-byte psig.

Due to limited card resources, some session context data is preprocessed externally by the wallet. The card requires the following data for signing (as per BIP327 notation):

  • b (32 bytes)
  • e*a mod n (32 bytes)
  • has_even_y(R) (1 byte)
  • g*gacc (1 byte)

Note: The smartcard performs blind signing, so limited checks are possible on the session context data. The card internally computes: psig = (k1 + b*k2 + e*a*d) mod n.

The implementation is available on our github:

This implementation has been validated against BIP327 test vectors and firmware for testing and test cases are published on our github repository:

Challenges we ran into

Smartcard have very limited resources (limited RAM, storage memory and CPU, no network), they don't have a screen or buttons. For these reasons, implementation of BIP327 is not straightforward. We decided to implement only the algorithms involving sensitive data (random nonces and private keys). the rest of the computation is processed on the wallet application side, outside of the secure chip.

To accelerate the cryptographic operations, we leveraged the smartcard chip crypto coprocessor, which allows to obtain a very efficient implementations (less than 1 sec to generate a random nonce or partial signature).

Accomplishments that we're proud of

We are one of the first implementation of MuSig2, and (AFAIK) the first open-source hardware wallet implementation.

What we learned

We have learned the intricacies of BIP327, the security aspects and how we can optimize its implementations on constrained devices such as smartcards.

What's next for MuSig2 support for open-source hardware wallet Satochip

We are looking for wallet applications on mobile and desktop that would be interested in integrating Satochip wallet MuSig2 functionality. We have open-source Swift, Java and Python SDK libraries for easy integration.

Built With

Share this project:

Updates