Greg Heartsfield home

Securing Your Bitcoins with Git and GPG

People put enormous resources into securing stores of value. FDIC insures dollars against bank failure, significant amounts of gold or silver are protected with expensive safes, even livestock is protected against theft with brands and surveillance systems. Crucially, when dealing with physical stores of value, the laws of physics provide a type of guarantee as well: an ounce of gold in your home safe will not suddenly vanish in the blink of an eye.

Decentralized crypto-currency like bitcoin is different. Theft can happen in seconds, leaving no trace, and no government is likely to insure or replace your losses. The same characteristics that make bitcoin attractive for mediating exchange across the globe leave it vulnerable if it isn’t well protected. At this point in time, it may very well be that the most dangerous person you must protect bitcoins from is yourself. User error and failure to maintain backups has been the root cause of many documented bitcoin losses.

In this post, I’ll go over how I protect my bitcoin wallets from loss due to several potential causes:

This is not a bitcoin tutorial; If you do not understand the basics of how bitcoin works, I suggest you start by browsing the main bitcoin site. I reference tools that I’m comfortable with, but you should stick with what makes sense for you. Instead of Git, you may prefer Mercurial; instead of Amazon S3, you may feel more comfortable with Dropbox or redundant USB drives in a safety deposit box. The point is that you should layer multiple levels of protection against theft, accidents, and stupidity.

The starting point is identifying exactly what it is we are trying to protect. For myself, this is a set of wallets, each containing a distinct set of public/private keys (addresses). Prior to the introduction of pre-generated keys, one way to lose all your bitcoins was to make a transaction (even a small one), and then lose your most recent wallet (backups wouldn’t save you!). This is less of an issue now, but theft must be a concern if you leave an unencrypted wallet with many BTC on an internet-connected machine. So, it is a sensible precaution to maintain several wallets, similar to having separate checking and savings accounts, and always backup after sending bitcoins.

Protecting against software errors in the bitcoin software itself should also be considered. For that reason that I do not store only the latest wallet file, but snapshots of the wallet state after every transaction. One easy way of doing this is to use version control software, like Git. After every transaction, the wallet is committed to the repository, making it very difficult that I could ever lose a private key.

Finally, this repository is archived, encrypted, and stored on another system (such as Amazon S3). This protects against catastrophic data loss. Archives are not overwritten, I timestamp them and save them all. This introduces a large amount of redundancy, since each archive contains the full history over time of each of my wallets. Disk is cheap; however BTCs no longer are!

I automate most of the wallet management described here with a perl script. It isn’t very well tested, makes some strong platform assumptions (OS X), and it does not go far enough. Soon I hope to actually store “backup” wallets encrypted in the git repository. This will ensure that wallets do not exist on disk unencrypted any longer than necessary, but will require entering GPG passphrases for most operations. However, the script does a fine job of automating the tedious and error-prone work of moving wallet files around. One neat feature is the use of filesystem attributes to keep track of which wallet is “active”, which makes backing up multiple wallets very straightforward (just run “manage-wallet.pl backup”, and it does the right thing).

Until the official client incorporates better wallet management and encryption functionality, this may serve as a nice stop-gap for OS X users who want to be extra-cautious when moving wallets around on disk. The examples below illustrate how it is used (with some output truncated for readability).

Running the script for the first time, we can backup our existing wallet.

$ manage-wallet.pl backup
It looks like this wallet has not been backed up yet.
Please enter an alias for the wallet, and press enter:
  --> checking
Saving wallet with alias "checking"
[master (root-commit) 948b6e9] Automatic wallet backup for checking.
 1 files changed, 0 insertions(+), 0 deletions(-)
 create mode 100644 checking.dat

If we have several wallets, we may want to check which one is “active”, and whether it has any outstanding changes that would need to be backed up.

$ manage-wallet.pl show
Current wallet: checking.
	No difference between active and backup wallet.
All wallet aliases:
	checking, exchanges, savings, testing

After making a payment, we should always backup, which is now very easy.

$ manage-wallet.pl backup
Saving wallet with alias "checking"
[master a3b0928] Automatic wallet backup for checking.
 1 files changed, 0 insertions(+), 0 deletions(-)

Switching wallets is also straightforward.

$ manage-wallet.pl activate checking
activating wallet checking

The script attempts to obtain a lock on the Bitcoin data directory, so it won’t allow itself to be run at the same time as the Bitcoin client.

$ manage-wallet.pl backup
Bitcoin must be shutdown before running this script.

Your git history will show when backups were made, and to which wallet.

$ git log --pretty='%h %s'
a3b0928 Automatic wallet backup for checking.
3901021 Automatic wallet backup for exchanges.
7f648e6 Automatic wallet backup for checking.
948b6e9 Automatic wallet backup for savings.

If this sounds better than manually moving wallet files around, fork the code on github and test it out (and send me a pull request, it could still use a lot of work)! And, the most important thing: if you find this valuable, please send me a tiny bit of BTC: 1KgeamVRTrU8DaBLRU2tv6VruwV9BRWDkm

Validate XHTML Validate CSS