MultiSig with HardwareWallets

2014 is touted as the year of multi-signature for BitCoin. It is being integrated into some wallets and services. But not quite the way I expected.

  • Electrum has an implementation that assumes multiple hierarchical deterministic wallets distributed over different machines, that know the other’s master private keys. -> This should work well for corporate environments or other organizations.
  • GreenAddress has a cool, but for my taste too obscure solution. I would recommend it for new users. But for myself, I want to be fully in control.
  • OpenBazaar, although not fully functional yet, will integrate arbitration with multi-sig.
  • and I hear more announcements almost on a daily basis…

When I first read into MultiSig, I understood it like I could combine any Bitcoin Addresses of my choosing to create a MultiSig address. If one of the involved addresses was in my wallet, it would automatically display the MultiSig address as well. And I could then partially sign a transaction with the GUI, and magically forward to the other signing parties. Turns out that is not quite how it works. To combine addresses of my choosing into a MultiSig address, I have to resort to the commandline. There are a couple of good tutorials on the net on how to do that, and also on how to spend. But it’s not like executing a few simple commands. It’s quite hardcore. There are wallets where you can add them as view only addresses, but I’m not aware of a wallet where you can partly sign a transaction in such a setting.

MultiSig brings us escrow services and a load of similar stuff that was not even imaginable before the rise of BitCoin. MultiSig is also good if you want to implement a setting where at least two of your accountants need to sign transaction in a corporate environment. What this adds is security. You surely saw movies where a few generals had to use their physical keys to launch missiles. That’s done to add security. So that the terrorists would have to steal the keys from more than one general, before they could launch a missile. The same works for bank vaults. And the same idea is behind BitCoin MultiSig, only that it goes much further.

MultiSig is just one facet of pay to script (P2SH). You can implement other rules than just MultiSig. I became only recently aware of that, when GreenAddress gave me a transaction that I could use to get my funds off the MultiSig wallet in case they went out of business. What that means, is that if too many parties loose their keys, funds on a MultiSig address are rendered inaccessible. As a measure against that, they created and signed a transaction with their key to transfer all funds, but with a time restriction. This transaction will only become valid after a certain configurable point in time. BitCoin has a stack based scripting language for expressing such rules. For my taste it’s very complicated at first sight, but it’s cool what you can do with it. That’s actually, where ethereum’s main focus is to improve. That’s all good and nice, but wasn’t it possible to program rules for a long time? Of course, but with BitCoin nobody can cheat, and you have to trust nobody. You cannot just change the system time on your computer, or buy a fake certificate to trick a system into using your timestamp server. BitCoin has a distributed consensus, that is very hard to come by.

So in essence, MultiSig is about increasing the security. This is mainly against malware that can infect your notebook and steal the files of your wallet software. There is also another cure against the same threat: HardwareWallets. I wrote about the Trezor and HW1 on my blog before. Now how about combining the two measures? That should raise the level of security up to a point equivalent as storing your gold and silver and diamonds inside a bunker in the Swiss mountains, and guard it with a Russian tank, driven by a rogue artificial intelligence. But I can tell you upfront: just like that rogue AI, it’s not going to be user friendly. While user friendliness and security are often opposing, this is an extreme case. After reading this, don’t be tempted to think BitCoin was difficult to use. BitCoin is wonderful and easy – for normal use.

So let’s begin with the commandline fu. I won’t repeat every step from the gist from atweiden, but concentrate on the special parts:

You don’t need to create any wallets. I assume, the hardware wallets are initialized and ready to use.

Extracting the public keys from the addresses has to be done inside electrum, to make sure the plugins are operational. The last tab in the GUI is an interactive console.

# in the electrum console with the hw1 wallet loaded:
>> getpubkeys('1Pv3ThmdjtRfLtcbdDz52gc61JGknTgEJJ')
    "address": "1Pv3ThmdjtRfLtcbdDz52gc61JGknTgEJJ",
    "pubkeys": [

# in the electrum console with the trezor wallet loaded:
>> getpubkeys('1DonzPnDZ4LP3jFnWeTY2TS6fShuueMQ6C')
    "address": "1DonzPnDZ4LP3jFnWeTY2TS6fShuueMQ6C",
    "pubkeys": [

The next part can be done in the bash shell:

# create the 2of3 multisig address
./electrum -w multisig_hww.dat createmultisig 2

    "address": "3EogeV3JgM99X544AnwErvdiRiw1oFJMBW",
    "redeemScript": "5241048e83c40cbe396048d3efe7d6bbdc6a2837a8c66783275b308f93220512388dea10c989af525e8b7fd192b5a9c5776417398f3efb1cbb672950f6626028f783bd21033a62e5382ea945c03087b74bd87d2cad9faeff5b88a7249cd4b1984c473243d021030e65b7823e3783de7cddb65dff8a89a5c92020ba4f8ac1992169bb313f507f2553ae"

Then send some coins to the MultiSig address:

# fund the multisig address
./electrum -w ~/.electrum/wallets/default_wallet mktx
    --fromaddr 1BeerjF6FZLvdcyWd7zhtdj8gm81hrwaJT
    --changeaddr 1BeerjF6FZLvdcyWd7zhtdj8gm81hrwaJT
    --fee 0.0 3EogeV3JgM99X544AnwErvdiRiw1oFJMBW 0.001

tx : 34bc438c8aa0c7ede4719b467346263d1f49375307df1c933aad07fc5341d464

./electrum -w ~/.electrum/wallets/default_wallet getrawtransaction
starting daemon (PID 8551)
    "complete": true,
    "hex": "010000000135722684e3b45c32be8c3dd88761e9f01c99b501dbf4a67d94dac2e148a555492a0000008a4730440220418bf8cb928846b5b0ec971dce4e4e54e12403a86ac7f78a2524da7490f039b10220752221d082d3d50900a8604b23f4c35c7a6faa4b7a413657aa304ada3a64b0580141047a20883eee86de0ac608623cb502e7ef7a2ecbb68451efd7f91b36659bee04f3e50863d042621efa99cb62b941434ddb6fb5c3475ad40316ec0a3e9f225a9d24ffffffff0213520200000000001976a91404d6b174978fa483e8f8546362def58caaa4d07288aca08601000000000017a9148fdc74942e194de4a3fe2dcfaeff6da87788b25c8700000000"

./electrum -w ~/.electrum/wallets/default_wallet decoderawtransaction
010000000135722684e3b45c32be8c3dd88761e9f01c99b501dbf4a67d94dac2e148a555492a0000008a4730440220418bf8cb928846b5b0ec971dce4e4e54e12403a86ac7f78a2524da7490f039b10220752221d082d3d50900a8604b23f4c35c7a6faa4b7a413657aa304ada3a64b0580141047a20883eee86de0ac608623cb502e7ef7a2ecbb68451efd7f91b36659bee04f3e50863d042621efa99cb62b941434ddb6fb5c3475ad40316ec0a3e9f225a9d24ffffffff0213520200000000001976a91404d6b174978fa483e8f8546362def58caaa4d07288aca08601000000000017a9148fdc74942e194de4a3fe2dcfaeff6da87788b25c8700000000 -o
    "txid" : "34bc438c8aa0c7ede4719b467346263d1f49375307df1c933aad07fc5341d464",
    "version" : 1,
    "locktime" : 0,
    "vin" : [
            "txid" : "4955a548e1c2da947da6f4db01b5991cf0e96187d83d8cbe325cb4e384267235",
            "vout" : 42,
            "scriptSig" : {
                "asm" : "30440220418bf8cb928846b5b0ec971dce4e4e54e12403a86ac7f78a2524da7490f039b10220752221d082d3d50900a8604b23f4c35c7a6faa4b7a413657aa304ada3a64b05801 047a20883eee86de0ac608623cb502e7ef7a2ecbb68451efd7f91b36659bee04f3e50863d042621efa99cb62b941434ddb6fb5c3475ad40316ec0a3e9f225a9d24",
                "hex" : "4730440220418bf8cb928846b5b0ec971dce4e4e54e12403a86ac7f78a2524da7490f039b10220752221d082d3d50900a8604b23f4c35c7a6faa4b7a413657aa304ada3a64b0580141047a20883eee86de0ac608623cb502e7ef7a2ecbb68451efd7f91b36659bee04f3e50863d042621efa99cb62b941434ddb6fb5c3475ad40316ec0a3e9f225a9d24"
            "sequence" : 4294967295
    "vout" : [
            "value" : 0.00152083,
            "n" : 0,
            "scriptPubKey" : {
                "asm" : "OP_DUP OP_HASH160 04d6b174978fa483e8f8546362def58caaa4d072 OP_EQUALVERIFY OP_CHECKSIG",
                "hex" : "76a91404d6b174978fa483e8f8546362def58caaa4d07288ac",
                "reqSigs" : 1,
                "type" : "pubkeyhash",
                "addresses" : [
            "value" : 0.00100000,
            "n" : 1,
            "scriptPubKey" : {
                "asm" : "OP_HASH160 8fdc74942e194de4a3fe2dcfaeff6da87788b25c OP_EQUAL",
                "hex" : "a9148fdc74942e194de4a3fe2dcfaeff6da87788b25c87",
                "reqSigs" : 1,
                "type" : "scripthash",
                "addresses" : [

Next, we want to spend the funds from the MultiSig address.

./electrum -w ~/.electrum/wallets/default_wallet createrawtransaction
      "redeemScript":"5241048e83c40cbe396048d3efe7d6bbdc6a2837a8c66783275b308f93220512388dea10c989af525e8b7fd192b5a9c5776417398f3efb1cbb672950f6626028f783bd21033a62e5382ea945c03087b74bd87d2cad9faeff5b88a7249cd4b1984c473243d021030e65b7823e3783de7cddb65dff8a89a5c92020ba4f8ac1992169bb313f507f2553ae"}]' '{"1RichiU2EDbGTPwe8jBRjgnWrV2dJWoxQ":0.001}'

Now this always returns a KeyError: ‘num_sig’. I didn’t dig into the code yet to find out. But it works if I try it in the bitcoin-qt console:

>createrawtransaction '[{"txid":"34bc438c8aa0c7ede4719b467346263d1f49375307df1c933aad07fc5341d464","vout":0,
    "redeemScript":"5241048e83c40cbe396048d3efe7d6bbdc6a2837a8c66783275b308f93220512388dea10c989af525e8b7fd192b5a9c5776417398f3efb1cbb672950f6626028f783bd21033a62e5382ea945c03087b74bd87d2cad9faeff5b88a7249cd4b1984c473243d021030e65b7823e3783de7cddb65dff8a89a5c92020ba4f8ac1992169bb313f507f2553ae"}]' '{"1RichiU2EDbGTPwe8jBRjgnWrV2dJWoxQ":0.001}' -> 010000000164d44153fc07ad3a931cdf075337491f3d264673469b71e4edc7a08a8c43bc340000000000ffffffff01a0860100000000001976a91404acb8d4b7c43a2fbd2cb8cdf096ee9e548e2a7088ac00000000

Next we need to sign the transaction. Since the private keys are well protected on the hardware devices, I can’t dump them to provide to signrawtransaction. Since I need to use the console tab inside a running electrum anyway to have the plugins available, I examined the API there. The signtxwithkey() function also needs the private key, but signtxwithwallet() could work from only looking at the API. But I assume it is ment for the special multisig wallets that electrum offers.


Bummer. Looks like what I envisioned doesn’t work just yet. I will update this post when I know more…

Join the Conversation


    1. Hi Micha,
      thanks for pointing it out. I know about it, and I want to try it. I just had not the time so far.
      I also didn’t update my post, even though I learned some more details in the meantime.
      HW1 has supported multisig transactions for a while, but only in their API. If I remember correctly, it’s a bit harder to use in the python code than with the C API.
      The multisig functions in electrum are really only for the special electrum multisig wallets. They need the key derivation path to be the same on all three wallets involved.

Leave a comment

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.