Signing Bitcoin PSBTs with QR codes with the Pi Zero (ZeroTrust Level 6)

Translations: German 🇩🇪

I was originally going to write about using QR codes for PSBTs on an air-gapped Raspberry Pi Zero, but I’ve expanded to also include a general discussion of PSBTs, specifically using the Electrum Desktop Wallet. Gentle advice: I highly recommend you learn to use Electrum if you are a serious Bitcoiner. Don’t play exclusively with dumbed-down software for the masses. Learn the “tools of the trade.” You could start here.


This is a Bitcoin transaction confirmation window in Electrum:

The top window has the input details of the transaction (the coins that are being used to pay), and the bottom window displays the output details (where the coins are going). Note at the top-left, it says “Unsigned” at this stage.

The details here can be saved before signing or after, and moved to another computer.

There are three types of transaction “stages” I want to discuss below:

PRESIGNED: For a pre-signed transaction, you may have a setup where you generate a transaction from a watching-only wallet (on an internet-capable computer, preferably connected to your own node), and move the transaction to an offline computer to sign. This computer is much more protected from having the private keys compromised. I show how to build a cheap air-gapped Raspberry Pi Zero here, (or buy one ready-made from me if you lack time), but of course, you could buy a custom-built dedicated desktop computer with no WiFi or Bluetooth capabilities (an expensive option, but faster than a Pi Zero). A laptop won’t do because they all have WiFi chips, as far as I know, and I assume you don’t want to be opening them up and removing the chip yourself.

FULLY SIGNED: After this offline computer signs, it becomes fully signed, and you then send the transaction back to your internet-capable computer and load it into your wallet. Then you broadcast it. (You can’t broadcast a transaction from an air-gapped computer of course). Another reason you might want to export a fully signed transaction is if you prepare a transaction in advance, and save it for later to broadcast.

PARTIALLY SIGNED: This is used in a multisignature wallet setup (make one; if you are scared, at least make a practice one). You generate a pre-signed transaction on your watching-only wallet (on an internet-capable computer, preferably connected to your own node), and move the transaction to your first offline computer which signs the transaction. Now it becomes a partially signed transaction (PSBT). Then you move it to your other offline computer, and add the next signature, and so on until there are enough signatures to make the transaction valid. Once the minimum number of signatures required is achieved, it is classified as “fully signed”, and as mentioned before, you send it back to the watching-only wallet, and broadcast.

UNDERAPPRECIATED BENEFIT OF MULTISIGNATURE WALLETS: People ask, “why can’t I just use a single signature wallet with a passphrase and store them separately?” – Well, that replicates the storage benefits of multisignature somewhat, but the great advantage of multisignature comes at the moment when you are spending. With the seed splitting method, if you ever spend, you need to get your key and your passphrase and enter it into a SINGLE computer, in one physical location to spend. What if that computer was compromised? What if the location was compromised? By using multisignature, you can spread the spending conditions to different computers in different places, using partially signed Bitcoin transactions. This is very reassuring for the modern-day paranoid Bitcoiner like myself.

To be able to do this, you need to know the various ways of moving transactions (signed, partial, or fully signed – it matters not) to other devices. There are three steps I’ll discuss:

  1. Export the transaction
  2. Transfer the transaction
  3. Import the transaction


The data that is being exported is actually encoded as some form of text. Here is an example:


Electrum can read this and populate a transaction window.

You can save this text in a file, such as “MyTransaction.psbt”, or you can copy the text to the clipboard and email it to another computer if you so wish, or you can generate a QR code and beam the photons to the camera of another computer (in the same room or anywhere in the world via video link, for example).

Once making a transaction and you have checked all the details, you click “finalise”. Then the “export” button appears. This is the sub-menu:

The “copy to clipboard” option copies text to the clipboard encoding the transaction details. You could save that to a file, or even in a document and then write it down on paper (don’t).

The “Show as QR code” option is incredibly useful to keep air-gapped computers from never contaminating each other by sharing USB devices to transmit data. See how to set this up a bit later. QR codes are amazing. They can encode any text, not just bitcoin transactions, or web addresses. For example:

The “Export to file” option does just that. Save it to your desktop, send the file in an email, or copy it to an SD card that goes into your hardware wallet for signing – although, that’s not quite true, I’ve tested on the ColdCard, and it doesn’t work unless you save the file specifically under the last item on the menu, “For hardware device; include xpubs“. I do not know why.

I have never tested “For CoinJoin; strip privates” so I won’t comment.


By file – you can copy the file to a USB storage device, and then copy that to the next computer. The potential problem is that any malware on the first computer may infect the next computer.

Or you can attach the file to an email and send it to another computer (not an air-gapped one of course, impossible) anywhere in the world. This will reduce the risk that malware gets transported, although not impossible.

Clipboard – the text data of the transaction is copied to the computer’s memory – that’s mainly useful for moving the transaction to another wallet on the same computer. But it’s also a way to extract the text data, and paste it into a document.

By hand – If you extracted the text data from the clipboard, you can actually write it all down on a piece of paper. Making a transcribing error won’t send the bitcoin to the wrong place, it will just make the whole transaction invalid. Not a recommended way, but it’s pretty cool that that’s possible. You can then send it in traditional physical mail, across the world, just for a laugh.

QR – once a QR code for the transaction is generated, the screen can be shown to another computer’s camera to transmit the data.


On the receiving computer’s Electrum wallet, you’ll find the transaction loading menu like this…

From file – you’ll be able to navigate to the location of the file you have transferred over (typically the USB drive)

From text – you’ll be able to input text into a pop-up window; either type it in manually (don’t!) or copy it from an email and paste it in from the clipboard.

From the blockchain – Never done that. I suppose you could load a confirmed transaction from the blockchain to inspect the transaction for some reason. With this method, you input a transaction ID into a pop-up window.

From QR code – this is the interesting bit. This will open the camera of the receiving computer. Point it to the QR code on the screen of the sending computer, and the transaction will copy across. Beautiful.


The main point of the QR transmission is to send pre-signed or partially signed transactions to without potentially compromising the air-gap.

For the Pi-Zero computer, I have tested a couple of USB webcams. You can buy a cheap one on eBay or Amazon. Make sure you don’t get one with a built-in microphone, although it’s not the end of the world if you use one of those. The theoretical risk is that a microphone could be hacked and function as a microphone, and send out data to an attacker via sound (even sound outside the frequency range of your hearing – OK, James Bond stuff, but non-zero risk).

A while ago I couldn’t make this work in a plug-and-play fashion. I was able to create a workaround, but it’s no longer needed. Plug and play is now working. I think because newer versions of Electrum have fixed some issues, now the cameras work as plug-and-play on the Raspian OS of the Pi Zero.


  1. Plug in the camera to the Pi Zero – nothing will happen, that’s ok.
  2. Load Electrum on the watching-only wallet on the internet-capable computer, and open your wallet.
  3. Make a transaction on the watching wallet, and finalise. The “sign” and “broadcast” buttons will be greyed out because this wallet has no private key. You then export the transaction to QR code.
  4. Open the same wallet on the Pi Zero, but this wallet has a private key and can sign.
  5. Go to the Electrum menu at the top and select Tools –> Load transaction –> From QR code
  6. A camera window will open up. Point the Pi Zero camera to the QR code on the other computer. Note, the Pi Zero is VERY slow, and an image will be shown every few seconds, not video. It’s quite hard getting delayed feedback and trying to position the camera (and hold still) to point accurately towards the QR code. It’s doable with effort and practice. On a powerful desktop air-gapped computer, it’s a breeze and a joy.
  7. Once the QR is recognised, the transaction will magically appear on the air-gapped computer. You can then review the transaction, and click “sign”.
  8. The transaction will change from saying “unsigned” to signed.
  9. Export the signed transaction from the Pi Zero, by clicking the “export” button in the transaction window, and selecting “Show as QR code”.
  10. On the internet computer, close the unsigned transaction, and go to the menu again: Tools –> Load transaction –> From QR code.
  11. A camera window will open up on the desktop. Point the internet computer’s camera to the Pi’s monitor and capture the QR code.
  12. The transaction will appear on the internet computer. It will say “signed”.
  13. The “broadcast” button will be available for clicking. Click it.

And that’s it! You’ve signed a transaction and broadcast it without ever allowing the internet-capable computer from contacting any private key, and your air-gapped computer remains unbesmirched, never having touched a dirty USB pen drive.


Static Lightning Address:

On-chain or Lightning

%d bloggers like this: