itsy-btc

itsy is a funny little bitcoin wallet for people who can't trust their computers to keep a secret, especially when their money exists entirely as a collection of secrets. It also feels a lot like using git, where transactions are like commits that you create, sign, and then push to the distributed repository, i.e. the blockchain. If you like git, then you will feel right at home with this tool.

Rationale

Here's the main problem this tool tries to solve: You likely have a computer that is years old, and over those many years you have downloaded and run countless executables from the internet, many of which themselves run on your computer and accept all sorts of connections to your computer from anyone in the world. You have to assume there are vulnerabilities in some of the code you have ran during your computer's history, and so you really can't assume that there isn't some ~~bad~~ code running that is inspecting your computer's memory for secrets and broadcasting them periodically to ~~bad~~ people.

Now it does seem rather unlikely to me that my keys are being logged, or my screen is being shot, or my RAM is being scanned, for purposes of skimming bitcoin private keys. But I think it's good to be paranoid about the possibility of my secrets being stolen even if their unencrypted form only exists in RAM for short amounts of time. As bitcoin gets more popular, these kinds of attacks will probably become common. (Probably mostly by frustrated miners who can no longer afford the hardware to keep up, so they have to "mine" their precious bitcoins in more creative ways...) Another thing to worry about is all the intentional backdoors at the OS or hardware level that have been uncovered lately, through which who-knows-how-many employees could get into your computer and swipe some secrets.

So the only solution I see is to create and manage all your secrets on a computer that is permanently offline. A nice cheap, convenient solution is to use a Raspberry Pi for this.

Install

Install the itsy-btc gem on your online, every-day computer:

$ gem install itsy-btc

Then you want to install it on your offline computer as well. Simply fetch the gem file and its dependencies and transfer them to your offline computer with a USB stick or similar, and install:

$ gem fetch itsy-btc bitcoin-ruby ffi highline
$ cp *.gem /mnt/usb/
... switch computers ...
$ cd /mnt/usb
$ gem install itsy-btc-0.0.1.gem

Basic usage

Most commands operate on a file called WALLET.itsy that is in your current directory. To create this file, use the init command:

$ itsy init

It will ask what passphrase to use to encrypt the wallet with. Make it a good one!

Now generate an address:

$ itsy gen "optional comment"

You can generate as many as you want. List them like this:

$ itsy list

To make transactions, your online computer needs to know what all your addresses are, so copy your wallet file to your online machine. Your private keys are encrypted in this file, so as long as you never type your passphrase on your online computer, they should be safe.

$ cp WALLET.itsy /mnt/usb/

Then on your online machine, after you've received money into your address, you can create a transaction to send some money to someone:

$ cd /mnt/usb
$ ls
WALLET.itsy
$ itsy tx 0.25 18wh2CbAjeB7i1w3zjPX8iCasy1zMYYgnv
Will send 0.25 BTC to 18wh2CbAjeB7i1w3zjPX8iCasy1zMYYgnv with a fee of 0.0001 BTC.
Transaction saved to 8b1738aaadb37a6c51d9caeec31a0b4f6bb0e0aa6ef7346a36a2813437298964.json.

It figures out what inputs to use using information downloaded from blockexplorer.com.

Okay, you have the transaction as a json file on your USB device. Now switch to your offline computer to sign the transaction:

$ itsy sign 8b1738aaadb37a6c51d9caeec31a0b4f6bb0e0aa6ef7346a36a2813437298964.json
1 input signed, transaction saved to 8b1738aaadb37a6c51d9caeec31a0b4f6bb0e0aa6ef7346a36a2813437298964-signed.json.

Finally, transfer this new file to your online computer and push the signed transaction to the block chain:

$ itsy push 8b1738aaadb37a6c51d9caeec31a0b4f6bb0e0aa6ef7346a36a2813437298964-signed.json
Transaction pushed successfully.

Advanced usage

Create custom transaction:

$ itsy tx
(1) Add input, (2) Add output, (3) Save, or (4) Cancel? 1
Prev tx? f480a09eb541c27fa4d3b7f3d3fceabde50840758248327fd0fb3cc6970c7486
Output index? 0
Input added. (Amount: 0.25 BTC)
(1) Add input, (2) Add output, (3) Save, or (4) Cancel? 2
Address? 1B2p7d1BPMqVrQMb97kTk5RbUvUH9CetBK
Amount? 0.1
Output added.
(1) Add input, (2) Add output, (3) Save, or (4) Cancel? 2
Address? 1C19FTsSj2ahsRjGfRFuiyDm9QJg9UZVSJ
Amount? 0.1499
Output added.
(1) Add input, (2) Add output, (3) Save, or (4) Cancel? 3
Will send 0.1 BTC from 1 input to 1B2p7d1BPMqVrQMb97kTk5RbUvUH9CetBK with a 0.0001 BTC fee.
Transaction saved to 9e62c79d41670168e11e98f68ed709ea22004a73978c37384e7d9613e5e2961e.json.

Authenticate to access encrypted wallet during a session (otherwise it will ask for your key every time you sign a transaction or modify your wallet, which might be okay):

$ itsy auth
Your passphrase? mysup3rs3cretpassw0rd
Wallet unlocked until poweroff.

TODO

  • Unit tests
  • Tighten error checking, integrity checks all over, i.e. make it hard for users to do anything stupid
  • Document commands thoroughly, so itsy help <command> gives lots of info for each command
  • Experiment with interacting with the bitcoin network directly (with bitcoin-ruby) to remove some of the dependency on blockexplorer.com (especially for the push command)

  • Idea: maybe wallet should be partitioned into hot and cold storage, with simple ways of transferring one to the other. Then you can have the best of both worlds.

Warning

This project is just me trying to do bitcoin the way I like to do things. I'm actually very new and inexperienced in bitcoin, crypto, and security. So read all the code and understand how it works before using it in any serious way, please.