Description
This recipe describes a method for storing bitcoin on paper, using an offline Raspberry Pi computer to perform the necessary computation.
Contents
- Description
- Contents
- Brief Summary
- Notes
- Equipment
- Services
- Recipe
Brief Summary
Using an offline Raspberry Pi to perform the necessary computation, complete the following tasks:
- generate a Bitcoin private key
- generate a Bitcoin address from the private key
- store the private key and address on paper
- test the address by transferring some bitcoin into and out of it
- transfer some bitcoin into the address for long-term storage
Notes
This recipe uses Edgecase Bitcoin Storage Toolset version 2 (EBSTv2).
Suggestion: Before using this recipe, read Effective offline storage of Bitcoin and think about how you could securely store a Bitcoin private key over the long term.
Previous version of this recipe:
Recipe for storing bitcoin on paper using a Raspberry Pi
Equipment
Required equipment for this recipe:
- A Raspberry Pi with Python 2.7.x installed.
- Suitable peripherals for the Raspberry Pi: Screen, mouse, keyboard, power cable, etc.
- An online computer for looking up information on the Bitcoin blockchain and broadcasting transactions.
- A USB flash drive for transferring data between the Raspberry Pi and the online computer.
- A set of 5 dice and a tray with raised edges in which to roll them. Add a dust cloth on top of the tray to muffle the sound of the dice rolls.
- Pen and paper.
Services
You will need access to services that allow you to:
1) Send and receive bitcoin.
This will probably be an online exchange service.
Other possibilities: An online wallet service, someone you know who is willing to sell bitcoin to you, another Bitcoin storage system that you already own.
2) Look up the list of unspent outputs that are stored in a Bitcoin address.
You will need the following details for each unspent output:
- "txid": The txid of the original transaction that sent the unspent output to its current address. It is a 64-hex-character string.
- "previous_output_index": The index of the unspent output in the list of outputs in the original transaction. It is an integer.
- "satoshi_value": The value of the unspent output in satoshi. It is an integer. Alternatively, look up the Bitcoin value of the unspent output, which will be a decimal value with 8 decimal places.
Suggestion: Use this recipe:
Recipe for looking up the unspent outputs in a Bitcoin address #2
The linked recipe relies on a particular feature of a specific block explorer. If that feature is discontinued at some point in the future, you can use the previous version of that recipe, which requires more manual work, but can be used with any block explorer. Link:
Recipe for looking up the unspent outputs in a Bitcoin address
3) Look up current Bitcoin network transaction fee rates in satoshi / byte.
Suggestion: Consult the Other services page. It should list an active service that supplies this information.
4) Decode a signed transaction.
If a transaction can be successfully decoded, this shows that it is formatted correctly.
The Other services page should list an active transaction decoder service.
5) Broadcast a transaction to the Bitcoin network.
The Other services page should list an active transaction broadcast service.
6) Check the status of a transaction: Has it been mined? If so, how many confirmations has it received?
Use a block explorer. The Other services page should list an active block explorer.
Recipe
1) On the online computer, create a project directory.
Choose a location and create a new directory named "storageProject".
Within it, create a subdirectory named "storageAssets".
2) Download assets.
Browse to each of the following articles, go to the Downloadable Assets section, and download all the linked assets. The list of assets is shown here below each article.
Edgecase Bitcoin Storage Toolset version 2:
- bitcoin_functions_2.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_3.py
- create_nonstandard_transaction_3.py
- create_transaction_3.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_4.py
- nonstandard_bitcoin_functions_2.py
- nonstandard_transaction_3.py
- pypy_sha256.py
- transaction_3.py
- bjorn_edstrom_ripemd160.py
- convert_dice_rolls_to_hex_bytes_3.py
- create_nonstandard_transaction_3.py
- create_transaction_3.py
- ecdsa-0.10.tar.gz
- generate_bitcoin_address_4.py
- nonstandard_bitcoin_functions_2.py
- nonstandard_transaction_3.py
- pypy_sha256.py
- transaction_3.py
Tools for storing a Bitcoin private key with a checksum tree:
- private_key_to_storage_key.py
- storage_key_to_private_key.py
- storage_key_to_private_key.py
Move the assets into the storageAssets directory.
These assets will be required by various sub-recipes linked within this recipe.
3) Copy assets to flash drive.
Insert the flash drive into a USB port on the online computer.
It should mount automatically.
Copy the storageAssets directory onto the flash drive.
On the flash drive, create a directory named "transferData".
Eject / unmount the flash drive.
Unplug the flash drive.
4) Raspberry Pi setup.
Set up the Raspberry Pi and its peripherals.
Insert the power cable into the Raspberry Pi in order to boot it.
Wait for the Raspberry Pi to finish booting and log into it. It should boot directly into a Desktop GUI (Graphical User Interface).
If the Raspberry Pi boots into a terminal, start the Desktop GUI by running the command
startx
. In the Desktop GUI, you can:
- open and edit files in a text editor.
- run commands in a terminal emulator program.
- copy output from the terminal emulator program into a text file.
Note: On the Raspbian OS,
- A text editor should be accessible from the Raspbian Desktop via [Raspberry Button] / Accessories / Text Editor.
-- The key combination for copying highlighted text from a text editor should be Ctrl-C. For pasting, Ctrl-V.
- A terminal emulator program should be accessible from the Raspbian Desktop via [Raspberry Button] / Accessories / Terminal.
-- The key combination for copying highlighted text from a terminal window should be Ctrl-Shift-C. For pasting, Ctrl-Shift-V.
5) Check Python version on Raspberry Pi.
In a terminal, run the following command to check the version of Python.
python --version
The result must be Python 2.7.x. The code assets may not work as expected on e.g. Python 2.6.1.
6) On the offline Raspberry Pi, create a work directory.
Change directory to the Desktop directory and create a new directory named "work".
Example command:
cd ~/Desktop; mkdir work
7) Transfer assets to Raspberry Pi.
Insert the flash drive into a USB port on the offline Raspberry Pi. It should mount automatically, and a pop-up entitled "Removable medium is inserted" should appear. The action-to-perform should be set to "Open in File Manager". Click OK. A File Manager window should open, set to show the contents of the flash drive.
If not, use the following recipe to mount it manually:
Recipe for manually mounting a USB flash drive
Copy the assets from the storageAssets directory (on the flash drive) to the work directory (on the Raspberry Pi).
8) Unpack the zipped tape archive file ecdsa-0.10.tar.gz.
This can be done by opening a terminal, changing directory to the work directory, and running the following command:
tar -zxvf ecdsa-0.10.tar.gz
This unpacking will produce a new directory named "ecdsa-0.10" in the work directory. The directory "ecdsa-0.10" will contain a directory named "ecdsa". Copy the "ecdsa" directory into the work directory. The copy operation can be performed using the following command:
cp -r ecdsa-0.10/ecdsa .
9) Generate a Bitcoin private key.
A private key is 32 bytes. On the offline Raspberry Pi, use the following recipe to generate 32 random bytes:
Recipe for generating entropy bytes using dice #2
Example Bitcoin private key:
15e7e195332b0aa8a684dc3be1f29dd04daa0a5434c11a8b9e6ad180df076ae4
Save the private key in a new text file named "privateKey.txt".
10) Write the Bitcoin private key on paper.
Use one of the approaches described in How to write a Bitcoin private key on paper. I recommend Approach 3 - the checksum storage format.
The assets that you downloaded earlier from Tools for storing a Bitcoin private key with a checksum tree will allow you to convert a private key to and from the checksum storage format.
Example Bitcoin private key in storage format:
9
76a2
bd3c c703 534e 7632
15e7 e195 332b 0aa8
a684 dc3b e1f2 9dd0
4daa 0a54 34c1 1a8b
9e6a d180 df07 6ae4
76a2
bd3c c703 534e 7632
15e7 e195 332b 0aa8
a684 dc3b e1f2 9dd0
4daa 0a54 34c1 1a8b
9e6a d180 df07 6ae4
11) Derive the corresponding Bitcoin address from the Bitcoin private key.
Use Recipe for generating a Bitcoin address #2.
Example Bitcoin address:
14gLgyVBiK7i7gtPLLYcVCAKfBuj1rL9JT
12) Write the Bitcoin address on paper.
Keep the address with the private key, but try to do so in a way that allows you to look at the address without uncovering the private key.
Use How to write a Bitcoin address on paper.
Example Bitcoin address in storage format:
14gL gyVB iK7i 7gtP
LLYc VCAK fBuj 1rL9
JT
LLYc VCAK fBuj 1rL9
JT
13) Copy address to online computer.
Save the address in a new text file named "address.txt". For protection against typos, store several copies of the address on consecutive lines.
Copy this file onto the transferData directory on the flash drive.
Eject / unmount the flash drive.
Unplug the flash drive.
Use the flash drive to transfer this file to the project directory on the online computer.
14) Estimate the bitcoin required for testing the address.
To test the address, send some bitcoin to it, and then transfer it out again to a second address. This will confirm that you can successfully move bitcoin back out of the address.
Use the deposit address of your online exchange account as the second address. [0]
Look up the current Bitcoin network transaction fee rates in satoshi / byte. Choose a rate. Later, when creating the test transaction, set its fee rate to be this value.
A standard 1-input 1-output Bitcoin transaction will be ~225 bytes. Multiply the rate by 225 to get the estimated transaction fee.
Check if your online exchange service charges a deposit fee. If it does, then add this fee to the estimated transaction fee.
Multiply this final amount by some factor, e.g. 2, so that you can tolerate a degree of change in the Bitcoin network's transaction fee rates.
Multiply by 0.00000001 to convert this satoshi amount to bitcoin (1 bitcoin == 10^8 satoshi).
15) Transfer the calculated amount of bitcoin to the address.
You can copy the address from the address.txt file in the project directory on the online computer.
Use the online exchange service to make the transfer.
Wait for the transfer transaction to receive 6 confirmations.
16) Create and sign a Bitcoin transaction that will transfer the bitcoin in the address back to the deposit address of your online exchange account.
If the deposit address is standard, use this recipe:
Recipe for creating and signing a standard Bitcoin transaction #2
Standard addresses start with the character '1'.
Example standard address:
1AGygbyEFYduWkkmZbbvirgS9kuBBMLJCP
Working definition of a standard address: An uncompressed single-signature Pay-To-Public-Key-Hash (P2PKH) address.
If the deposit address is nonstandard, use this recipe:
Recipe for creating and signing a nonstandard Bitcoin transaction #2
Example of a nonstandard address:
- A Pay-To-Script-Hash (P2SH) address.
Pay-To-Script-Hash (P2SH) addresses begin with the character '3'.
Example nonstandard P2SH address:
328cTqexYnQRbN5Dgs12D89sYiPPvtWVbF
On the online computer, look up the necessary information:
- The deposit address.
- The details of the unspent output in the test address:
-- the txid.
-- the previous output index.
-- the satoshi value (or bitcoin value).
- The details of the unspent output in the test address:
-- the txid.
-- the previous output index.
-- the satoshi value (or bitcoin value).
Save the deposit address and the details in a new text file named "details.txt".
Double-check the current fee rates.
Use the flash drive to transfer this file to the Raspberry Pi.
On the Raspberry Pi:
- Generate 32 bytes of new entropy for signing the transaction.
- Set the fee rate.
- Assign all the bitcoin value to the deposit address. Note: If there is some mistake, and some value is left over, this value will be assigned to the change address.
- Set the deposit address as the change address.
- Create and sign the transaction.
Example signed Bitcoin transaction:
0100000001cde23540f3033b59d8c00fd9d8703c80d5928a177244b12fec8d580f34dbce070f0000008a473044022005fc767d513f285c38f718f4c9cfb0909d4ba2d80131aed21b3f26aa630a79f0022047367d93de1ebbcd0b4f0bc20c96821a94de5430638b3982799adf4d9f7114760141043ab692792d6c8838fd30c2ff45bf3cbd44286a5cac52ba64dc06452810202b3206f5c7799c3b72ff77fd1976f105ced3cd7700b0412e11266f3888b88c3052c3ffffffff01c2d30200000000001976a91465beb01aab71c9da76f38a383c65e3693dff54cc88ac0000000001000000
Copy the signed transaction and save it in a new text file named "signedTransaction.txt".
17) Broadcast the Bitcoin transaction.
Use the flash drive to transfer the signed transaction file to the online computer.
Use a transaction decoder service to decode the transaction, which will confirm that its format is valid.
Use a transaction broadcast service to broadcast the transaction to the Bitcoin network.
Wait for the transaction to receive 6 confirmations.
If the transaction is not mined, follow this recipe:
Recipe for managing the fee and broadcast of a Bitcoin transaction #2
Once the transaction is mined with 6 confirmations, the test is complete. You can now move a large amount of bitcoin into this address and be certain that you can retrieve it.
The test has shown that the address is correctly derived from the private key. If you later construct a new transaction that turns out to be invalid, and discover that the cause was an error in the code stack used to create and sign a transaction, you know that eventually this error can be fixed and a valid transaction can be created. You risk only a temporary lack of access to the bitcoin stored in this address, not its permanent loss.
18) Use the tested Bitcoin address for long-term storage.
You can now transfer more bitcoin into this address for long-term storage.
Suggestion: Re-read Effective offline storage of Bitcoin and make backup copies of your private key.
Suggestion: Delete the private key file privateKey.txt from the Raspberry Pi. Type it back in from paper storage when you need to use it in future.
19) Shut down the Raspberry Pi.
In the terminal, you can use the following command to shut down the Raspberry Pi:
sudo halt
Wait until it has completely shut down. This should take about 10-15 seconds.
Store the Raspberry Pi in a safe location.
Suggestion: Consider preparing and storing a duplicate offline Raspberry Pi in case the first one is lost, damaged, or destroyed.
[start of footnotes]
[0]
Alternatively, you could create a second Bitcoin address yourself. By later transferring bitcoin from this second address back to the first address, you would have successfully tested both addresses.
[return to main text]
[end of footnotes]