Most Bitcoin users store and transact via mobile smartphone wallet software such as Breadwallet, Mycelium, among the other lesser known smartphone apps. Some use web wallets such as blockchain.info’s or Green Address. Some users run Electrum SPV light client software on their desktops or laptops. Some users run fully validating node software such as Bitcoin Core (you guys rock!). These solutions are all great in their own ways which we will expand upon in further posts, but they also have their shortcomings. This post, however, is for the paranoid poweruser.
What we are building today is a split Bitcoin wallet. Traditionally, Bitcoin Core software downloads and verifies the historical transaction ledger called the blockchain which it then stores on-disk. Bitcoin Core then starts relaying transactions from one peer to another peer, because Bitcoin is a peer-to-peer network of fully validating nodes. By having a peer-to-peer network, there is no single point of failure that an adversary can attack and shut down the network. With that said, opening up a port to enable other peers to connect to your node can, in a way, broadcast to the world that “Hey, I’m running Bitcoin here. I may or may not have stored Bitcoins on it.”
So in order to run a fully validating Bitcoin Core node and also store our Bitcoins locally, we have to isolate the Bitcoin private keys which can be used to spend our Bitcoins from the node software which accepts inbound connections. There are a few ways to do this. One way is to have two separate computers preferably on the same LAN; with one relaying transactions, verifying, and storing blocks. The other simply generates and stores the Bitcoin private keys. Bitcoin Core developers have created a way to import only our Bitcoin addresses (not with their corresponding private keys) into Core so that Core can “watch” those addresses for transactions. Utilizing this feature, we can run a fully validating node and keep tabs on our Bitcoins without the risks of storing money on a computer which is open to the outside world.
Qubes OS is a Linux-based operating system designed to isolate individual applications from other applications running on the same computer. How Qubes does this is by utilizing Xen virtualization software to create an “AppVM” virtual machine for different sets of tasks. Out of the box, Qubes comes with “Work”, “Personal”, and “Untrusted” AppVMs. These AppVMs are just guidelines for how one should use Qubes.
What we want to do is create a separate AppVM to run Bitcoin Core in, in order to synchronize the blockchain and relay transactions. We also want to generate and store our Bitcoin private keys in the “vault” VM which comes out-of-the-box with every Qubes OS install.
The requirements for a split Bitcoin wallet with Qubes OS:
- The latest verified Qubes OS ISO image installed on compatible hardware (with VT-d or AMD-v)
- The latest (or any recent version) verified Bitcoin Core. We use version 0.13.2 in this guide
- Intermediate to advanced Linux/Unix knowledge
- An AppVM for Bitcoin Core to sync the blockchain in
- Storage space to accommodate 100GB+ of the blockchain, or ~4GB for a pruned node
Firstly, create an AppVM for which we will install and run Bitcoin Core 0.13.2 in.
Resize the maximum storage of the online Core VM if you are not running a pruned node
Move Core to the “vault” VM to generate keys
Generate your addresses offline in the vault VM. The vault virtual machine in Qubes OS is isolated from the outside internet. Its usage is for storing passwords and other sensitive information. You can also generate PGP keys and Bitcoin addresses from within the vault VM.
Finally, import addresses into the online wallet running in the designated AppVM:
You now have a split Bitcoin wallet. Your Bitcoin private keys are protected by a network-isolated Xen paravirtualized virtual machine. Now you can run a fully validating node, relay transactions, and not have to worry about having your funds stolen!
Thanks for reading! If this article helped you secure your Bitcoins, please donate a tip to 1C41Mc3yR5gM9hwf46iGp1uRopFdGCGsEF