We'll discuss how to safely create and spend from offline Bitcoin accounts. |
There's another class of investment that is also at an all-time high, and that has been performing even better than stocks: Namely, the electronic currency Bitcoin. There are good reasons for this:
- Bitcoin is gaining in mainstream acceptance, as the largest exchange (Mt. Gox) moves its trading operations to the U.S., in affiliation with an actual bank (Silicon Valley Bank), in preparation to meet demand from Wall Street investors for better-regulated access to the Bitcoin economy. Also, a licensed Bitcoin hedge fund is opening up in Malta.
- The underlying fundamentals of Bitcoin remain strong, with an underlying cryptographic protocol that still has never been hacked, and that will likely remain unhackable for the foreseeable future; Bitcoin remains the most secure and lowest-cost medium for the digital storage and transmission of wealth.
The most secure Bitcoin accounts or "wallets" are ones that are never exposed to the Internet at all. |
This then provides a means for a relatively technically unsophisticated user to remain 100% confident that his stash of Bitcoins remains safe from theft, while still retaining the ability to spend or transfer portions of that store of liquid wealth on demand, as needed.
In this post, I will describe this process.
Part I. Creating an Unhackable Offline Wallet
One of the major premises of the method I'll describe here is "trust nobody." If you plan to store large amounts of wealth in Bitcoin, and you expect the value of those Bitcoins to grow significantly in the future, and you are paranoid about somebody, someday, stealing that wealth, then you want to make extra-sure that it is totally unhackable.
The first step in this process is creating an offline Bitcoin account, that is, one where the critical private information required to access that account never touches any computer that is connected to the Internet. This precludes your private data (and thus, your Bitcoins in that account) from being stolen by any electronic means - including compromised software.
Even so, you will need to use some software to run the algorithms required to compute your public Bitcoin address from a (typically randomly-generated) private key. If the software you use for this purpose is not trustworthy, then it could do things like instead generate fake "predefined" accounts built into the software, where the authors of the software already have the keys to that account. Given this risk, how can you make sure that your new Bitcoin account is generated as securely as possible?
The most essential requirement is that the random data that goes into selecting a key is truly randomly generated, and cannot be corrupted or influenced by an attacker so as to make it come out one way rather than another. Once you have the initial random data, with confidence that it is secure, you can verify that it is being transformed to a Bitcoin account correctly by redundantly performing this standard transformation with several different pieces of software (on an offline computer), making sure that they all return the same result. If they do then it becomes very unlikely that all those pieces of software were corrupted in the same way to give you a fake address.
Now, good random number generators are complex pieces of software, which would generally be difficult for the lay user to verify (to make sure they are generating high-quality, not-predictable random numbers). Therefore, what I recommend is: don't generate your random numbers using a computer at all. Instead, use a simple physical method, such as flipping coins or rolling dice. In this post, I will assume that you have access to at least one ordinary, 6-sided die. A pack of these can be purchased at many convenience stores.
Armed with a die, you are now ready to generate the truly random, private data needed to securely create a new Bitcoin account. This can be done by hand, using a procedure which I will describe; however, to simplify and partially automate the steps of the process, I have written a little program to help you. This program is simple enough that, if you know anything about computer programming at all, a quick look through it can convince you that it is not doing anything insecure.
First, I will describe how to download and run the program; then, I will take you through what the program is doing, so you can verify the code for yourself or (if you're not confident in your ability to do that), go through the steps by hand.
The first step in this process is creating an offline Bitcoin account, that is, one where the critical private information required to access that account never touches any computer that is connected to the Internet. This precludes your private data (and thus, your Bitcoins in that account) from being stolen by any electronic means - including compromised software.
Even so, you will need to use some software to run the algorithms required to compute your public Bitcoin address from a (typically randomly-generated) private key. If the software you use for this purpose is not trustworthy, then it could do things like instead generate fake "predefined" accounts built into the software, where the authors of the software already have the keys to that account. Given this risk, how can you make sure that your new Bitcoin account is generated as securely as possible?
The most essential requirement is that the random data that goes into selecting a key is truly randomly generated, and cannot be corrupted or influenced by an attacker so as to make it come out one way rather than another. Once you have the initial random data, with confidence that it is secure, you can verify that it is being transformed to a Bitcoin account correctly by redundantly performing this standard transformation with several different pieces of software (on an offline computer), making sure that they all return the same result. If they do then it becomes very unlikely that all those pieces of software were corrupted in the same way to give you a fake address.
This is a totally secure and unhackable random-number generator. |
Armed with a die, you are now ready to generate the truly random, private data needed to securely create a new Bitcoin account. This can be done by hand, using a procedure which I will describe; however, to simplify and partially automate the steps of the process, I have written a little program to help you. This program is simple enough that, if you know anything about computer programming at all, a quick look through it can convince you that it is not doing anything insecure.
First, I will describe how to download and run the program; then, I will take you through what the program is doing, so you can verify the code for yourself or (if you're not confident in your ability to do that), go through the steps by hand.
I(A). Downloading and Running the Dice-Wallet Program
GitHub is a popular site for hosting open-source programming projects. |
To download the program, you can either click the ZIP button (if you know how to unzip a file), or (perhaps easier), download the files individually, by, one file at a time, clicking on the file name and then clicking the "Raw" button, then selecting "Save as..." in your browser. Save them all to the same folder.
Python is a popular and easy-to-use programming language. |
Note that using the Python language technically means you have to trust it. But, if you don't even trust Python, which is one of the most popular and beloved of all computer languages, then may God have mercy on your soul. (Anyway, you can always verify the program's output by hand if you're suspicious.)
How to run the program may vary with your operating system. In Windows, double-clicking the dicewallet icon should be enough to start it, if Python has been installed successfully. It should bring up a window that looks something like this (you may have to expand it and scroll to see the full contents):
Initial window contents when you run the dicewallet.py program. |
At this point you have a menu with three options, to select what size you want your randomly-generated data to be, measured in bits or binary digits. The choices are:
- 64 bits' worth of random data. This is relatively quick to generate, since it requires only 25 rolls of a 6-sided die. The random information is translated for you by the program into a 5-word passphrase. This is relatively easy to memorize, but it also might be cracked more quickly by a determined hacker.
- 128 bits' worth of random data. This takes twice as long to generate (50 rolls), and (at 10 words long) is at least twice as difficult to memorize accurately. However, it is much more difficult to hack
- 256 bits' worth of random data. This takes twice as long again to generate (100 rolls) as the 128-bit option, at at 20 words is a challenge to memorize. But it is virtually impossible to hack, and is at the very highest level of security that the Bitcoin system currently supports.
Let's now illustrate what happens when you enter option 3:
Dicewallet console after selecting option 3 (max amount of random data). |
Note the program displays some information about your selected choice, and then loads the diceware dictionary. This is a plain-text file which you should examine; it provides an English word or symbol corresponding to each of the 7,776 possible sequences of 5 die rolls. The top portion of it looks like this:
-----BEGIN PGP SIGNED MESSAGE-----11111 a11112 a&p11113 a's11114 aa11115 aaa11116 aaaa11121 aaron11122 ab11123 aba11124 ababa...
And so on. At the very bottom of the file is a PGP signature which you can use, if you're really paranoid, to verify that the word list has not been modified; here's some information about where to get PGP by its original author. GPG is a good substitute for most purposes. Here's the signature in my copy:
I downloaded the word list file originally from this link and some additional information about Diceware can be found on this page. I'll sum it up below.-----BEGIN PGP SIGNATURE-----Version: PGP for Personal Privacy 5.0Charset: noconviQCVAwUBOn7XUmtruC2sMYShAQHp4AQAh5x14GkCvdpz1RyXkywa/nBlmVNrcecti/8z4jvFsBOJQgzRC/BdwDuFv2NVPbEjE33e8YXcOP6dnyCqzF0nmKpqNchMPHS3QICqA9fIs9azxl/0Zro4fxzl3ewRxldyW8TY9Vj6uayNAqy+mYUXC5FZFSX3kOHobgR/yfB40fA==c65y-----END PGP SIGNATURE-----
IMPORTANT: For security, you need to go OFFLINE before doing this next step. Unplug your computer from the Internet, turn off your router, disable its network interface - whatever you have to do. The very safest thing would be to run the program on a computer that was set up from the original factory settings and was NEVER connected to the Internet. However, even if it has never been connected to the Internet before, as long as it never WILL BE connected to the Internet in the future, you know your private data can't be hacked. So, really paranoid users may want to reserve a dedicated computer for this sort of thing.
I(B). Rolling the Dice
Let's show the screen after the first 25 rolls:
Diceware interface after entering 1st chunk of dice-roll data for a 4-chunk passphrase. |
Note that the data entry is broken into "chunks" of 5 dicewords each (corresponding to 25 die rolls); each of these providing about 64 bits' worth of random data. This is just done for organizational purposes.
Note the program is doing two things here: Converting the die rolls to a number in base 6 (from 00000 to 55555), which will be used in a later step; and looking up the Diceware word corresponding to each group of 5 die rolls. You can see that, for this first chunk, the 5 word sequence selected was "11 other porto wow nice." If this was a 64-bit run, we would be finished with data entry at this point, and would have an easy-to-remember passphrase.
However, this is a 256-bit run, so we have 3 other chunks worth of die rolls (75 more rolls) to enter. I'll skip the gory details of that process, and just show you the final result. At the conclusion of the process, the final output is as follows (and this would look better on a wider terminal):
Final output of Dicewallet for a 256-bit random key. |
Here is what the output would look like, with the same data, if the application is run within the IDLE editor that comes with Python: You may find that a little easier to read since the long data strings aren't wrapping around. (To get this in Windows, right-click the dicewallet icon, select "Edit with IDLE", then in that window, hit function key F5 or select Run --> Run Module from the menu.)
Dicewallet output in the IDLE environment. |
So, a couple of things to note about the output here:
- The entered chunk of random data is displayed in several forms. You may use any of these to generate a Bitcoin account. The passphrase (sequence of words/symbols) might be the easiest to remember and to communicate to others. But the decimal and hexadecimal passcodes (which are mathematically equal to the base-6 number derived from the die rolls) may be faster to type. You might want to omit the commas when typing the decimal code.
- Since the entered data was actually a little more than 256 bits' worth, we can also generate a 256-bit hexadecimal Bitcoin private key directly by just taking the last 256 bits (64 hex characters, 32 bytes) of the hexadecimal passcode, and use that directly. That is, this would not need to be put through a brainwallet key-generation algorithm to turn it into a private key - it is already a private key.
I(C). Making Your Public Address
Now that you have a randomly-generated passphrase or private key, how do you convert it to a public Bitcoin address that people can send money to?
As I've discussed in previous posts, perhaps the easiest way to do this currently is to download the HTML source code to the website bitaddress.org, store it on your offline computer, and run it (without being connected to the network). It is self-contained JavaScript in a single HTML file, and will run without needing to connect to any servers. To verify that it is working correctly, you may want to compare the output with that produced by some other offline tool, such as an offline copy of http://brainwallet.org/, or the Casascius Bitcoin Address Utility. (Or, compare output with an online tool such as blockchain.info, but with a "test" key that you are not planning to actually use.)
As an example, here's what bitaddress.org shows for the above passphrase (here I'm using it online, just for demonstration purposes, but it works the same offline):
BitAddress.org after entering our 20-word random Diceware passphrase. |
And, for comparison, here is brainwallet.org with the same input:
BrainWallet.org after entering the same 20-word random Diceware passphrase. |
As you can see, both sites come up with the same account information, namely:
- Public Bitcoin address: 1FuKeiWSyu6gAxFvWXs1hPzJRpUm5vBLQC
- Private key (WIF format): 5J3rXKZWszMKgwdMUHbjNLN2XA9cW8jzkQDQCmtGat49g1BnsPi
At this point, it's essential that you make multiple backups (paper and/or offline electronic) of this derived account data, or at minimum the passphrase that was used to generate it, to make sure that you will be able to recover any Bitcoins put into this account. Again, I recommend paper backups in multiple secure locations that you have physical control over. If you encrypt your electronic backups, be careful - this raises a sort of chicken-and-egg problem, where now you have to worry about forgetting the encryption passphrase, if it's sufficiently strong, so now you have to make backups of it, and you haven't really solved the problem.
In the next section, we'll discuss: Now that you have this nice safe offline Bitcoin account, how can you securely send money from it, without needing to risk exposure of your private key data?
Part II. Spending from Offline Accounts
In this part, I'll discuss: Now that you have this nice safe offline Bitcoin account, how can you securely send money from it, without needing to ever risk exposure of your private key data?
The StrongCoin service proves a simple tool which you can run offline to generate your transaction details. You can download it here. To use it, you have to look up the transaction history for the Bitcoin address you are trying to spend coins from. This can be done from the "mytransactions" query service at Blockexplorer.com, using a URL starting with "http://blockexplorer.com/q/mytransactions/" followed by the address. I'll illustrate this process, step-by-step, for an actual example below. I actually was forced to go through this process today to retrieve some coins from a paper wallet, because other clients were not accepting its private key for some reason.
I previously used BitAddress.org.html (offline) to generate a paper wallet with the following details (safe for me to give out, now that the coins are emptied from it):
At this point, all you have to do is type the necessary command name "sendrawtransaction" at the prompt, followed by a space, and paste your transaction data copied from the last field of the offlineTransaction tool, which in this case gives me:
The StrongCoin service proves a simple tool which you can run offline to generate your transaction details. You can download it here. To use it, you have to look up the transaction history for the Bitcoin address you are trying to spend coins from. This can be done from the "mytransactions" query service at Blockexplorer.com, using a URL starting with "http://blockexplorer.com/q/mytransactions/" followed by the address. I'll illustrate this process, step-by-step, for an actual example below. I actually was forced to go through this process today to retrieve some coins from a paper wallet, because other clients were not accepting its private key for some reason.
Step 1. Create Offline Wallet
- Private key: 5KVkdnmRqbiRvuvzQdMpiUbCyGrxJUzUpU83HNcbMK3tRT1BPqN
- Public address: 1CrkvauazZGd7cegyYkw2PK4M9MMNmVNek
Step 2. Fund Wallet
At some point, I sent 10 BTC to this address from another account, and then used Blockchain.info to send 2 BTC from it to Mt. Gox, with a 0.001 BTC transaction fee, and sent the 7.999 BTC change back to the same paper wallet.
However, a little later, I ran into problems, because a temporary glitch in blockchain.info's transaction database prevented me from spending any of the remaining balance. Fortunately, I still had my paper wallet printout, so I tried importing the private key into Electrum, as well as the official "Satoshi" client, now called Bitcoin-Qt (v0.8). Unfortunately, these did not work either! (I still don't know why yet.) So, I decided to try out this offline spending method instead.
Step 3. Find Account's Transaction History.
The next step is to obtain the complete transaction history of your account, in a certain format. This can be done by going to http://blockexplorer.com/q/mytransactions/ followed by your account address, in my case http://blockexplorer.com/q/mytransactions/1CrkvauazZGd7cegyYkw2PK4M9MMNmVNek. The complete output from this was:
{ "53a602149fc54b72d5e0b6fb888451014c30237c45fc1ee1c3701cf73cc4e4d1":{ "hash":"53a602149fc54b72d5e0b6fb888451014c30237c45fc1ee1c3701cf73cc4e4d1", "ver":1, "vin_sz":2, "vout_sz":2, "lock_time":0, "size":440, "in":[ { "prev_out":{ "hash":"66aa708e2c3ba7884d99e7e57a686846a662bcc397e12ca6af72d0a8d78a078b", "n":1 }, "scriptSig":"3046022100fa94cb6ce0810ad37972df074aa9f4477fd246e84731d6325e14a232f1fbab69022100fc531111e2dd49c2d8550c61fe0d1aca4de1b3f7158d07c55ee79fb7bb6e56db01 049da190afa6511f738d695b5c5178e890ff04e4f85b1ad7b83fa97d538b232c1067c9679facb04fea4120e0bb878871e5aeca02f11ebd1222938b616f1c938d82", "address":"18drA1GCocJ3FVcSj4bqeTmUDmg479XC8m" }, { "prev_out":{ "hash":"e4ee8b473f08cf0fa985ee357bbd8f096043d692c6e236fba3bcf8570e2bf814", "n":1 }, "scriptSig":"3046022100a3ec31eb91a945f0288c5b5a8d055665800a5d279bec2104d38fe9f5ecf013cb022100820a2d203bd6f44120cd8b2f24604d6f3685392871048ab84eab26fa3f5559be01 0466f9e3fea3b01035369c2615a2546a74e0ee660814f5d540975c840aafb970c03f01424fee9b05b3966c33296b5150cedca602fcd35814e846af0b9dbf7d8e30", "address":"1Lg1XqLo7pvTqoa49NXXewGfMnPztMVhFs" } ], "out":[ { "value":"10.14810000", "scriptPubKey":"OP_DUP OP_HASH160 b7bbc94f4810f4b2baf5458d46ffe680668f082a OP_EQUALVERIFY OP_CHECKSIG", "address":"1HkVcjN7vobUetiW89f79P9HouXNweSJvg" }, { "value":"10.00000000", "scriptPubKey":"OP_DUP OP_HASH160 82126e7a2729c87a7ddd75577c87cc170429857a OP_EQUALVERIFY OP_CHECKSIG", "address":"1CrkvauazZGd7cegyYkw2PK4M9MMNmVNek" } ], "block":"00000000000000af338999746c3a8c08d75d848d8d8bbd223058ee16eea6175f", "blocknumber":"223674", "time":"2013-03-01 01:26:21" }, "87e6e5b30ce286fa50389391fe7d6cb547d1817dd1194ac5ff4017b15a672b5b":{ "hash":"87e6e5b30ce286fa50389391fe7d6cb547d1817dd1194ac5ff4017b15a672b5b", "ver":1, "vin_sz":1, "vout_sz":2, "lock_time":0, "size":257, "in":[ { "prev_out":{ "hash":"53a602149fc54b72d5e0b6fb888451014c30237c45fc1ee1c3701cf73cc4e4d1", "n":1 }, "scriptSig":"304402206bd8e1bbde33ba97a702e93286c764db4d1cdec8448c96b6d419d4055ca1756902206a78a3bb81db0a7d7a16d8f388de5f5b33e93f0418d3968ee9bb3596f9a053f201 04ee17f6e9f51926d9d07d19cd1d1bb73c993fb190fedbc2c6f1b8fa05d04682b62043076036e642fc80b176e3645edad73d8ff5bb5f2e4f571f620b2fd0fc4e44", "address":"1CrkvauazZGd7cegyYkw2PK4M9MMNmVNek" } ], "out":[ { "value":"2.00000000", "scriptPubKey":"OP_DUP OP_HASH160 305d8de76154bc34281c0fd582e652eae6f73d6b OP_EQUALVERIFY OP_CHECKSIG", "address":"15QjWUaFwP4nU8qZbVziLRgkvBgNNZ1S5W" }, { "value":"7.99900000", "scriptPubKey":"OP_DUP OP_HASH160 82126e7a2729c87a7ddd75577c87cc170429857a OP_EQUALVERIFY OP_CHECKSIG", "address":"1CrkvauazZGd7cegyYkw2PK4M9MMNmVNek" } ], "block":"0000000000000103673aad34c8073127549c27ccb9e98460d1598c5bdefaa37e", "blocknumber":"224766", "time":"2013-03-08 01:52:32" } }
You can see, near the end, where I previously sent out two coins and sent myself back the 7.999 BTC change.
Step 4. Generate Offline Transaction
Then, on your offline machine, you run StrongCoin's offlineTransaction.html page, and fill in the various fields (hitting the Parse button after the top two to verify your balance), and then hit the Generate button. Then the tool gives you, in the last field, a long hexadecimal string which is the digitally-signed transaction order. In my case, the screen looked like this:
StrongCoin's offlineTransaction.html tool, with fields filled in. |
Step 5. Move Signed Transaction Back to Online Computer
You can do this using an SD card, USB flash drive, or other removable media. For safety, I recommend a bare card with no other data on it. To be extra-safe, you should make sure that there really is no other data on the card by checking it on yet another offline computer that you trust has not been compromised. If you are extremely paranoid, you can even avoid digital media, and just write down the transaction code on paper - that way, you know that no malware is stowing away your private key data in a hidden file somewhere on the media.
Step 6. Insert Transaction Order into Bitcoin Network
This last step is very easy, but requires running a client that can handle raw transactions. The default Bitcoin-Qt client does this, through its Debug console interface. I used version 0.8.0 of the client. Select menu Help --> Debug window, and click the "Console" tab. The debug window then looks like this:
Bitcoin-Qt (0.8) Debug Console |
At this point, all you have to do is type the necessary command name "sendrawtransaction" at the prompt, followed by a space, and paste your transaction data copied from the last field of the offlineTransaction tool, which in this case gives me:
sendrawtransaction 01000000015b2b675ab11740ffc54a19d17d81d147b56c7dfe91933850fa86e20cb3e5e687010000008a473044022028d0ecf4101826b3c9890480ff9e291fe22aa8b00d877d139b420027f4ab82800220d0197fc20a0bf96c3b660a01bd5ae06eb366e873d36d5736c146fa53dd5d85e8014104ee17f6e9f51926d9d07d19cd1d1bb73c993fb190fedbc2c6f1b8fa05d04682b62043076036e642fc80b176e3645edad73d8ff5bb5f2e4f571f620b2fd0fc4e44ffffffff01c0faab2f000000001976a9147781393fa77a8e3abc472bd430ca3f9424ba933688ac00000000
And hit enter. The transaction (if properly formatted and verified) will then be immediately injected into the Bitcoin network. You have to wait several minutes for block confirmation(s), as usual. (Note that you cannot re-enter this same transaction, because those coins have already been spent; if you want to practice, you'll have to make your own!)
Or, even easier (and, this way, you don't have to wait for your full node to catch up to the block chain) - just visit https://blockchain.info/pushtx and paste your transaction data there. (Thanks to Eric Heaney for the tip!)
Or, even easier (and, this way, you don't have to wait for your full node to catch up to the block chain) - just visit https://blockchain.info/pushtx and paste your transaction data there. (Thanks to Eric Heaney for the tip!)
That's it for now! Have fun playing with your offline wallets and offline transactions!