Author: StJohn Piano
Published: 2017-07-12
Datafeed Article 3
This article has been digitally signed by Edgecase Datafeed.
2578 words - 335 lines - 9 pages
The recipe in this article has been superseded by a later recipe, which involves using a small transaction to test an address before moving a relatively larger amount of bitcoin into it. The address is created offline. The test transaction is created and signed offline.

Link: Recipe for storing bitcoin on paper using an offline Raspberry Pi #2

The following page is also relevant:
How to store bitcoin

~ StJohn Piano

This preface is unsigned and subject to change at any time.

About a year and a half ago, I decided to buy and store a reasonable amount of bitcoin.

I am indebted to Pete Dushenski for publishing this recipe, which I found and followed. I have included my own version of this recipe at the end of this article.

I created several bitcoin addresses on an offline computer.

Note: A bitcoin private key (a sequence of 256 bits - the value of a bit can be either 0 or 1) is related mathematically to the bitcoin public address. The address can be shown or given to anyone else. Bitcoin is stored on a public distributed ledger (a database that associates bitcoin amounts with public addresses). The private key must be kept secret, as it allows anyone who knows it to spend the bitcoin associated with it. Spending bitcoin is accomplished via the creation and broadcasting of transactions.

Note: This is my current understanding of transactions: A transaction is a signed note that specifies an amount of bitcoin to be sent from a sending address to a receiving address. Transactions are digitally signed with the bitcoin private key, which a) proves that the transaction is authorised by the person who holds the private key and b) prevents third parties from altering them and rebroadcasting a changed version. It is possible to create transactions that send from multiple sending addresses to multiple receiving addresses (this is how you can send only a portion of the bitcoin associated with a particular address to someone else's address - the portion that you keep is also sent in the transaction, but it goes to the original address or to another address that you control).

I then bought some bitcoin using an online exchange service (Bittylicious, which is UK-based) that connects buyers and sellers. I made multiple small- and medium-size payments to multiple sellers over a two month period, so that I did not have to send any particular seller a large amount of money in one payment and trust that he/she would send me the bitcoin. The exchange service required me to a) have a UK bank account with Faster Payments enabled, b) confirm my email address and mobile telephone number, and c) have a bitcoin address ready so that the seller could send bitcoin directly to this address.

Note: If an online exchange service is based in certain countries (mostly Western ones), it will often require buyers to verify various types of personal identification in order to comply with Anti-Money Laundering legislation. Examples: email address, mobile telephone number, address, bank account, photo ID such as driver's licence or passport. If you wish to acquire your bitcoin with some degree of anonymity, I suggest that you find someone who is willing to act as an intermediary.

A year and a half later, none of the bitcoin associated with any of my addresses has been spent. This allows me to be reasonably certain that the code used in the recipe was not written with malicious intent (i.e. that no tricks were inserted that might allow the writer to record or deduce the private keys later and spend the bitcoin I had stored at the corresponding public addresses).

However, this does not prove that the code was written perfectly. It is possible that when I attempt to move some bitcoin from one of my addresses, I will find that the public address was not computed correctly from the private key. If so, I will not be able to construct and sign valid transactions for this public address. The bitcoin would never actually have been in my control.

I tested the validity of my first address by installing a bitcoin wallet program (MultiBit) on an internet-connected computer, importing the first private key, and transferring the bitcoin associated with this address to another of my addresses. The import and transfer worked, so I decided to assume that at least some of the addresses I generated would be valid.

Note: To be certain that an address was correctly generated from a private key, you can create a transaction that moves some or all the bitcoin in the address to another address that you control. The transaction should then be broadcasted to a selection of bitcoin nodes. If the transaction is mined (i.e. included in a new block in the blockchain), you know that the address is valid and that you can move bitcoin into and out of it. The transaction must be signed with the private key corresponding to the sending address. Therefore, in order to protect the private key, the transaction should be constructed and signed on an offline computer (e.g. the same one that was used to generate the address).

I do not yet know how to generate an offline transaction. This meant that as soon as I tested the validity of an address by generating a transaction on an online computer, I could not rely on that address as a secure offline storage address. I decided to take my chances, generate the storage addresses, buy bitcoin and transfer it to those addresses, and study the problem. Eventually, I will be able to generate transactions offline, and then I will know how much (if any) of my bitcoin I actually have.

Here is the recipe for offline generation of bitcoin addresses:

1) Set up an offline computer. Ideally, this should never, ever, at any time, have been connected to the internet.

I used a Raspberry Pi Model B+, which notably does not have built-in WiFi. If your candidate computer has a built-in WiFi transmitter, you should consider physically removing it. You will need suitable peripherals. For my Raspberry Pi, these were: an 8GB micro SD card with NOOBS preinstalled, a Raspberry Pi power cable, a screen with a DVI port, a DVI male-male connector cable, a DVI female to HDMI male converter, a screen power cable, a USB keyboard, a USB mouse, and a plastic case customised for the Raspberry Pi Model B+.

2) Obtain five six-sided dice, two small notebooks, and a sealable container that is large enough to hold both notebooks. Ideally, each die should be made by a different manufacturer.

The dice are used to generate a quantity of entropy (some information without predictable structure). Deriving a private key from this entropy will make it difficult for an attacker to guess the private key. The notebook paper should be of reasonable quality. I recommend writing down all the information in both notebooks so that you have two complete copies. This is insurance against any small amount of damage that makes it hard to read a character or sequence of characters within a single notebook. The purpose of the container is to protect the notebooks against accidental water damage.

Note: A bitcoin private key can be guessed by generating all possible private keys and deriving the corresponding public addresses. An attacker can then check if any of these addresses exist on the bitcoin blockchain. If one does, the bitcoin associated with this address can be stolen. This is known as a brute-force attack. Note that the attacker only has to be able to access the bitcoin blockchain, which is public. He/she does not have to be able to access your home, your computer, or your possessions. There are 2^160 possible bitcoin addresses. It is not feasible to check all of them, so in practice a brute-force attack is not really a problem. However, an attacker can make guesses about which sequences of characters are likely to be used. Some examples: lines of famous poems, idioms, common passwords, names of famous people, your mother's maiden name, your birthplace. This is known as a dictionary attack. A dictionary attack focuses on a much smaller possibility space and is therefore much more feasible. Generating entropy and using it to select your passphrase protects you from a dictionary attack.

3) Install an operating system, a web browser, and a PDF viewer on the offline computer.

I bought a micro SD card with NOOBS preinstalled. NOOBS is an operating system installer that allows you to select from a number of operating systems for Raspberry Pi. I connected the peripherals, inserted the micro SD card, and turned on the Raspberry Pi by inserting the power cable. From the NOOBS menu, I chose the Raspbian operating system (a variant of Debian customised for the Raspberry Pi), which according to the documentation is the only operating system that is actually fully contained within NOOBS (a network connection is required in order to install any of the other systems). My Raspbian version is 7 ("wheezy") (found by running the command $ cat /etc/os-release) and the kernel version is 3.18.7+ (found by running the command $ uname -r). Raspbian included the Web web browser (version 3.8.2) and the Xpdf PDF viewer (version 3.03). The default login is "pi" and the default password is "raspberry".

Note: I was experimenting with several Raspberry Pis at the time and am not completely certain that I used a micro SD card with NOOBS preinstalled for my bitcoin address generation Raspberry Pi. I may have written a Raspbian image to a blank micro SD card instead.

4) Download bitaddress.html, a file that contains JavaScript code for generating a bitcoin address.

I originally downloaded it a year and a half ago from www.bitaddress.org, by right-clicking on the web page and choosing Save As. It can be executed in the web browser on the offline computer (you can think of it as a sort of downloadable, portable website). I cannot be sure (without arduous auditing) that malicious exploits have not been inserted into newer releases of this code. I have therefore uploaded my own copy that I used on my offline Raspberry Pi and linked to it from this article.

5) Download this English dicelist.

I downloaded it from http://world.std.com/~reinhold/dicewarewordlist.pdf. Please note that this is a PDF file - exploits can be hidden inside PDF files and I lack the technical skills required to verify that this file is clean. I can only say that it has not caused any visible problems when I have opened it on my Raspberry Pi.

6) Move the bitaddress.html file and the dicelist file onto your offline computer. You could leave the dicelist file on your online computer and use it there if you wish, but I prefer to store a reference version of the file on the offline computer.

I used a USB flash drive, although I am sure that some exploits exist that could take advantage of this.

I had to learn how to manually mount the flash drive within my Raspberry Pi's operating system in order to access the files on it.

Steps for manually mounting a flash drive on a Raspberry Pi:

Insert the USB flash drive into a USB port on the Raspberry Pi.

Note: If the Raspberry Pi automatically started the graphical user interface, then open the program LXTerminal, which is a terminal emulator. It can be accessed from the Desktop via Menu / Accessories / Terminal. On my Raspbian system I have LXTerminal version 0.1.11.

In the terminal, enter the following commands, which are prefixed with a dollar sign and a space ($ ). Do not include this prefix when typing a command into the terminal.

Make a new directory on the graphical desktop to hold the contents of the flash drive:
$ mkdir /home/pi/Desktop/flash_drive_contents

Make a new directory to be the mount point for the flash drive:
$ sudo mkdir /mnt/flash_drive_mount_point

Mount the flash drive:
$ sudo mount -o uid=pi,gid=pi /dev/sda1 /mnt/flash_drive_mount_point

Note that:

-o (lowercase letter "o", not the number zero) specifies that an option string follows.

uid=pi,gid=pi specifies that the user ID is "pi" and the group ID is "pi" (note there are no spaces allowed between these two terms).

/dev/sda1 is the first partition on the first USB drive that the Raspberry Pi can detect.

Copy the contents of the flash drive to the flash_drive_contents directory on the Desktop:
$ cp -r /mnt/flash_drive_mount_point/* /home/pi/Desktop/flash_drive_contents

Unmount the flash drive:
$ sudo umount /mnt/flash_drive_mount_point

The flash drive can now be unplugged.

7) Use the PDF viewer to open the dicelist file. Roll the five dice ten times on a flat, even surface, writing down the resulting five-digit number each time in each of the notebooks. Derive a ten-word passphrase by looking up each five-digit number in the dicelist and finding the word next to it. Write down this passphrase in each of your notebooks. Write each character separately. Please note that you will need to write carefully in order to avoid any ambiguity in any character.

On the Raspberry Pi, in order to complete this step and the step involving the web browser, you will need to start the graphical user interface if it did not start automatically. Run this command in order to do so:
$ startx

8) Use the web browser to open the bitaddress.html file. You will have to move the mouse around and/or type characters into the text box for a while to satisfy the program's demand for initial entropy generation (this entropy is not used in this recipe). Click Brain Wallet. Enter the passphrase without inserting spaces between the words and click View. Write down the private key in WIF format and the bitcoin address in each of your notebooks. Again, write each character separately and carefully. WIF stands for Wallet Import Format.

I find it easiest to write the characters in groups of four with a space between each group. I underline these capital letters in order to distinguish them from their lower-case equivalents: C, K, L, M, N, O, P, S, U, V, W, X, Y, Z. Additionally, I cross the top of a capital J to distinguish it from j, add a tail to u/U to distinguish it from v/V, and cross the middle of z/Z to distinguish it from 2.

Note: The bitcoin private key (a sequence of 256 bits) is derived from the passphrase (the length of which is variable) via the application of the SHA256 hash algorithm.

9) Test that you have written down everything correctly by clicking Wallet Details and typing in the private key in WIF format. Click View Details. Check that the bitcoin address is the same as the one that you have written down.

10) Shut down the offline computer. Store the computer in a safe location so that you can be sure that it has not been compromised if and when you decide to generate another address. The various peripherals do not have to be so carefully guarded (although I suspect that it is or will become possible to design malware that embeds itself inside a chip within a peripheral component).

11) Open a text file on your online computer, type out the bitcoin address, and save the file. Double-check the bitcoin address in the text file against the bitcoin address in your notebook. If you type it out incorrectly, and send bitcoin to it, you will not be able to retrieve your bitcoin from the incorrect address.

12) Place the notebooks in the sealable container. Store the container in a safe location.

13) This bitcoin public address is now ready for use. Please bear in mind that in order to be absolutely certain of the validity of this address, a transaction from it should be generated offline and accepted into the bitcoin blockchain.